little-time
The Scala library that provides extension methods to java.time.
Getting Started
To use little-time, add it as a dependency to your project:
libraryDependencies += "com.github.losizm" %% "little-time" % "0.7.0"
A Taste of little-time
Here's a taste of what little-time offers.
Iterating over Dates
You can create an iterator from one LocalDate
to another, stepping thru each date between the two.
import java.time._
import little.time.Implicits._
// Convert String to LocalDate
val start = "2018-04-01".toLocalDate
val end = "2018-07-01".toLocalDate
// Iterate over dates, one day at a time (end inclusive)
start.iterateTo(end).foreach { date =>
println(s"$date is on a ${date.getDayOfWeek}")
}
// Iterate over dates, one day at a time (end exclusive)
start.iterateUntil(end).foreach { date =>
println(s"$date is on a ${date.getDayOfWeek}")
}
Specifying Step Unit
When creating the iterator, you can specify the Period
by which to step.
// Iterate over dates, two weeks at a time
start.iterateTo(end, Period.ofWeeks(2)) foreach { date =>
println(s"$date is on a ${date.getDayOfWeek}")
}
You can iterate forward or backward, based on the supplied period. If the period is negative, you step backward to the end date.
import java.time.temporal.ChronoUnit
val oneDay = Period.ofDays(1)
val startDate = LocalDate.now()
val endDate = startDate - 7
// Iterator backward over dates, 1 day at a time
startDate.iterateUntil(endDate, -oneDay).foreach { date =>
val daysAgo = date.until(startDate, ChronoUnit.DAYS)
println(s"$date is $daysAgo days(s) ago")
}
Iterating over Other Types
You can create iterators of other types, like YearMonth
and LocalTime
. Similar to LocalDate
, you specify a Period
by which to step when creating an iterator of YearMonth
; whereas, for LocalTime
, you must specify a Duration
.
// Convert String to YearMonth
val startMonth = "2018-04".toYearMonth
val endMonth = "2020-03".toYearMonth
// Iterate over months, 3 months at a time
startMonth.iterateTo(endMonth, Period.ofMonths(3)).foreach { month =>
val diff = startMonth.until(month, ChronoUnit.MONTHS)
println(s"$month is $diff month(s) after $startMonth")
}
// Convert String to LocalTime
val startTime = "09:00".toLocalTime
val endTime = "17:00".toLocalTime
// Iterate over times, 15 minutes at a time
startTime.iterateUntil(endTime, Duration.ofMinutes(15)).foreach {
case time if time.getMinute == 0 => println(s"It's $time, back to work")
case time if time.getMinute == 45 => println(s"It's $time, take a break")
case time => println(s"It's $time")
}
For LocalDateTime
, you can specify either a Period
or Duration
by which to step.
val twoYears = Period.ofYears(2)
val startDateTime = "2019-06-15T12:30:45".toLocalDateTime
val endDateTime = startDateTime + twoYears * 3
// Iterate over 6 years, 2 years at a time
startDateTime.iterateTo(endDateTime, twoYears).foreach { dateTime =>
println(s"Date-time is $dateTime")
}
val _45secs = Duration.ofSeconds(45)
val otherDateTime = startDateTime + Duration.ofMinutes(3)
// Iterate over 3 minutes, 45 seconds at a time
startDateTime.iterateTo(otherDateTime, _45secs).foreach { dateTime =>
println(s"Date-time is $dateTime")
}
Lastly, you can iterate between one Duration
and another.
val _17mins = Duration.ofMinutes(17)
// Iterate from 17 minutes to 34 minutes, 45 seconds at a time
_17mins.iterateTo(_17mins * 2, _45secs).foreach { duration =>
println(s"${duration.toMillis / 1000} secs from now is ${LocalTime.now() + duration}")
}
Setting Dates to Common Boundaries
When working with dates, you can set them to common boundaries.
import DayOfWeek._
val now = LocalDate.now()
// Get first and last date of current month
val startOfMonth = now.atStartOfMonth
val endOfMonth = now.atEndOfMonth
// Get first and last date of current week
val startOfWeek = now.atStartOfWeek
val endOfWeek = now.atEndOfWeek
// Print first and last date of current week, with Monday as first day of week
println(now.atStartOfWeek(MONDAY))
println(now.atEndOfWeek(SUNDAY))
Setting Times to Common Boundaries
When working with times, you can set them to common boundaries, too. However, to set an end boundary, you must specify the TimePrecision
. You may do this explicitly by passing the precision in the method call, or keep an implicit precision in scope.
import little.time.TimePrecision
// Implicitly set time precision to milliseconds
implicit val precision = TimePrecision.Milliseconds
val now = LocalTime.now()
// Get first and last millisecond of current hour
val startOfHour = now.atStartOfHour
val endOfHour = now.atEndOfHour
// Get first and last millisecond of current minute
val startOfMinute = now.atStartOfMinute
val endOfMinute = now.atEndOfMinute
// Get first and last millisecond of current second
val startOfSecond = now.atStartOfSecond
val endOfSecond = now.atEndOfSecond
The same applies to LocalDateTime
, which is both a date and a time. You must ensure an implicit TimePrecision
is in scope when setting to an end boundary – or supply one explicitly in the method call.
implicit val precision = TimePrecision.Seconds
val dateTime = "2017-05-12T15:23:17.123456789".toLocalDateTime
// Set to last second of year
val endOfYear = dateTime.atEndOfYear
// Set to last microsecond of day
val endOfDay = dateTime.atEndOfDay(TimePrecision.Microseconds)
Working with CronSchedule
A CronSchedule
provides a cron-like utility for specifying times at which something should occur.
import java.time.{ LocalDateTime, Period }
import java.time.LocalTime.NOON
import java.time.Month.{ OCTOBER, NOVEMBER, DECEMBER }
import little.time.CronSchedule
import little.time.Implicits._
// Create schedule
val schedule = CronSchedule(
times = Seq(NOON),
daysOfMonth = Seq(1, 15),
months = Seq(OCTOBER, NOVEMBER, DECEMBER),
daysOfWeek = Nil)
val start = LocalDateTime.now()
val end = start + Period.ofYears(1)
// Iterate over scheduled times
schedule.between(start, end).foreach { time =>
println(s"${time.toLocalDate} at ${time.toLocalTime}")
}
// Create schedule using cron-like syntax
val altSchedule = CronSchedule("0 12 1,15 Oct-Dec *")
assert(altSchedule.next(start) == schedule.next(start))
API Documentation
See scaladoc for additional details.
License
little-time is licensed under the Apache License, Version 2. See LICENSE file for more information.