Skip to content

Instantly share code, notes, and snippets.

Created November 26, 2021 15:27
What would you like to do?
Destructuring a Date into Years, Months, Weeks, Days, Hours, Minutes and Seconds in Kotlin
object TimeAgo {
fun toRelative(millis: Long, spans: List<Span>): Map<Span, Long> {
var millisMutable = millis
return spans.sortedBy(Span::order).associateWith { span ->
val timeDelta: Long = millisMutable / span.millis
if (timeDelta.isGreaterThanZero()) millisMutable -= span.millis * timeDelta
enum class Span(val order: Int, val millis: Long) {
YEARS(0, TimeUnit.DAYS.toMillis(365)),
MONTHS(1, TimeUnit.DAYS.toMillis(30)),
WEEKS(2, TimeUnit.DAYS.toMillis(7)),
DAYS(3, TimeUnit.DAYS.toMillis(1)),
HOURS(4, TimeUnit.HOURS.toMillis(1)),
MINUTES(5, TimeUnit.MINUTES.toMillis(1)),
SECONDS(6, TimeUnit.SECONDS.toMillis(1))
fun Map<Span, Long>.getYears(): Long = this[YEARS] ?: 0L
fun Map<Span, Long>.getMonths(): Long = this[MONTHS] ?: 0L
fun Map<Span, Long>.getWeeks(): Long = this[WEEKS] ?: 0L
fun Map<Span, Long>.getDays(): Long = this[DAYS] ?: 0L
fun Map<Span, Long>.getHours(): Long = this[HOURS] ?: 0L
fun Map<Span, Long>.getMinutes(): Long = this[MINUTES] ?: 0L
fun Map<Span, Long>.getSeconds(): Long = this[SECONDS] ?: 0L
class TimeAgoTest {
fun timeAgoTest() {
TimeAgo.toRelative(ONE_YEAR, listOf(YEARS)).getYears().shouldBe(1)
TimeAgo.toRelative(ONE_MONTH, listOf(MONTHS)).getMonths().shouldBe(1)
TimeAgo.toRelative(ONE_WEEK, listOf(WEEKS)).getWeeks().shouldBe(1)
TimeAgo.toRelative(ONE_DAY, listOf(DAYS)).getDays().shouldBe(1)
TimeAgo.toRelative(ONE_HOUR, listOf(HOURS)).getHours().shouldBe(1)
TimeAgo.toRelative(ONE_MINUTE, listOf(MINUTES)).getMinutes().shouldBe(1)
TimeAgo.toRelative(ONE_SECOND, listOf(SECONDS)).getSeconds().shouldBe(1)
TimeAgo.toRelative(ONE_MONTH, listOf(WEEKS, DAYS, HOURS)).run {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment