I, too, was disappointed that TimeCategory declares it to be its own duration and does not support Java 8. This prompted me to write some of my own code, which I thought would be relevant to this issue. He focused on ZonedDateTime , not LocalDateTime because I was interested in the TimeZone logic, where I use it. This is not as complete as the groovy.time.TimeCategory class, and I only have a few operations that interest me, so feel free to add to them.
Without further ado:
import java.time.Duration import java.time.ZoneOffset import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit class TimeCategory { static getDays(Integer self) { Duration.ofDays self } static getHours(Integer self) { Duration.ofHours self } static getMillis(Integer self) { Duration.ofMillis self } static getMinutes(Integer self) { Duration.ofMinutes self } static getNanos(Integer self) { Duration.ofNanos self } static getSeconds(Integer self) { Duration.ofSeconds self } static getWeeks(Integer self) { Duration.ofDays self * 7 } static getDay(Integer self) { Duration.ofDays self } static getHour(Integer self) { Duration.ofHours self } static getMilli(Integer self) { Duration.ofMillis self } static getMinute(Integer self) { Duration.ofMinutes self } static getNano(Integer self) { Duration.ofNanos self } static getSecond(Integer self) { Duration.ofSeconds self } static getWeek(Integer self) { Duration.ofDays self * 7 } static ZonedDateTime getAgo(Duration self) { ZonedDateTime.now() - self } static ZonedDateTime getUtc(ZonedDateTime self) { self.withZoneSameInstant(ZoneOffset.UTC) } static ZonedDateTime getLocal(ZonedDateTime self) { self.withZoneSameInstant(ZoneOffset.systemDefault()) } static ZonedDateTime getNow() { ZonedDateTime.now() } static Duration minus(ZonedDateTime self, ZonedDateTime other) { Duration.between(self, other) } static BigInteger getTotalNanos(Duration self) { self.seconds.toBigInteger() * 10 ** 9 + self.nano } static String toString(ZonedDateTime self, String pattern) { self.format(DateTimeFormatter.ofPattern(pattern)) } static Duration mod(Duration self, Duration other) { def (long seconds, int nanos) = (self.totalNanos % other.totalNanos).divideAndRemainder(10g.pow(9)) Duration.ofSeconds(seconds) + nanos.nanos } static load() { Integer.mixin(TimeCategory) ZonedDateTime.mixin(TimeCategory) Duration.mixin(TimeCategory) } }
Usage example:
// I prefer putting this in a start-up location and pollute the namespace rather than use // `use() {...}` TimeCategory.load() // Construct readable java 8 durations Duration d = 1.day + 2.hours + 3.minutes - 4.seconds // Easily construct dates relative to now ZonedDateTime yesterday = 1.day.ago // Of course, you can still call "unsugared" functions like truncatedTo for rounding down ZonedDateTime today = TimeCategory.now.truncatedTo(ChronoUnit.DAYS) // Converting between local and utc doesn't change the underlying instant assert 0.seconds == yesterday.utc - yesterday.local // Modulo arithmetic. Cool! assert 1.minute % 17.seconds == 9.seconds // Slightly cleaner date formatting println "Today in strange format ${today.toString('dd/yy/MM')}"
source share