Last active
December 20, 2017 05:33
-
-
Save hohonuuli/7d21c2d61df30576394aa24fce2d2cae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.time.temporal.{ChronoField, TemporalAdjusters} | |
import java.time.{Duration, Instant, ZoneId} | |
/** | |
* A OneTime transaction does not reoccur in our model. | |
*/ | |
case class OneTime(label: String, | |
value: Double, | |
date: Instant) extends Transaction { | |
override val next: Option[Transaction] = None | |
override val accumulatedValue: Double = value | |
} | |
/** | |
* Ongoing transactions occur at a regular interval. e.g. a paycheck every 14 days. | |
*/ | |
case class Ongoing(label: String, value: Double, | |
date: Instant, | |
repeatInterval: Duration, | |
accumulatedValue: Double = 0) | |
extends Transaction { | |
lazy val next: Option[Transaction] = { | |
Some(Ongoing(label, value, date.plus(repeatInterval), repeatInterval, | |
accumulatedValue + value)) | |
} | |
} | |
object Monthly { | |
/** | |
* Helper function to get next the a date on the same day in the next month. | |
* For example, if the date of a transaction is 2017-11-04, nextDate will | |
* return 2017-12-04 | |
*/ | |
def nextDate(date: Instant): Instant = { | |
val zdt = date.atZone(ZoneId.systemDefault()) | |
val dayOfMonth = zdt.get(ChronoField.DAY_OF_MONTH) | |
zdt.`with`(TemporalAdjusters.firstDayOfNextMonth()) | |
.plus(Duration.ofDays(dayOfMonth - 1)) | |
.toInstant | |
} | |
} | |
/** | |
* A transaction that occurs on the same day of every month ... forever! | |
*/ | |
case class Monthly(label: String, | |
value: Double, | |
date: Instant, | |
accumulatedValue: Double = 0) | |
extends Transaction { | |
lazy val next: Option[Transaction] = { | |
Some(Monthly(label, value, Monthly.nextDate(date), | |
accumulatedValue + value)) | |
} | |
} | |
/** | |
* A monthly event that does not occur forever. e.g. A car loan. | |
*/ | |
case class Loan(label: String, | |
value: Double, | |
date: Instant, | |
endDate: Instant, | |
accumulatedValue: Double = 0) | |
extends Transaction { | |
override lazy val next: Option[Transaction] = { | |
val nextDate = Monthly.nextDate(date) | |
if (nextDate.isBefore(endDate)) { | |
Some(Loan(label, value, nextDate, endDate, accumulatedValue + value)) | |
} | |
else None | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment