Closed mel4tonin4 closed 3 years ago
Well, the compiler is right to reject the code above because a Moment
extending TimePoint<TimeUnit, Moment>
uses TimeUnit
while a net.time4j.Duration
uses IsoUnit
(or more concrete: CalendarUnit
resp. ClockUnit
).
The key to understand the nature of the problem is: Moment
and TimeUnit
are global types in universal time (UT), but the units (and duration) you wish - CalendarUnit
resp. ClockUnit
- work in context of a time zone.
If you insist on moments (UT) then the appropriate timespan type is usually MachineTime
which will satisfy the compiler because it works with TimeUnit
, too. There is one limitation however. TimeUnit
only supports days or smaller units but not months or years. Days in UT are always 24 hours long, but days in a time zone might be longer or shorter. The same with months or years. Just think of what happens around a switch from summer to winter time for example. Time4J is simply strict in making a difference here.
If you wish to support years or months, too, and also wish to support moments (at least indirectly) then I recommend first to do a conversion from Moment
to PlainTimestamp
using the appropriate time zone and then to construct a duration like following:
Moment t1 = SystemClock.currentMoment();
Moment t2 = t1.plus(4646, TimeUnit.DAYS);
Timezone tz = Timezone.ofSystem(); // or choose an explicit zone
PlainTimestamp tsp1 = t1.toZonalTimestamp(tz.getID());
PlainTimestamp tsp2 = t2.toZonalTimestamp(tz.getID());
TimeMetric<IsoUnit,Duration<IsoUnit>> zonedMetric =
Duration.in(
tz,
CalendarUnit.YEARS, CalendarUnit.MONTHS, CalendarUnit.DAYS,
ClockUnit.HOURS, ClockUnit.MINUTES);
Duration<IsoUnit> duration = zonedMetric.between(tsp1, tsp2);
After this step, you are free to normalize or to print the duration.
@MenoData Thank you very much, Meno!
I adopted Time4J for my application.
At the moment I'm doing a very basic usage of Time4J: only as a final stage when displaying the time elapsed from the creation of various database objects, using this class to format the description:
sealed class ElapsedTimeDescription(
val tz: Timezone = Timezone.ofSystem()
) {
companion object : ElapsedTimeDescription() {
}
val zonedMetric = Duration.`in`(
tz,
CalendarUnit.YEARS, CalendarUnit.MONTHS, CalendarUnit.DAYS,
ClockUnit.HOURS, ClockUnit.MINUTES
)
fun format(a: Moment, b: Moment, locale: Locale = Locale.US, textWidth: TextWidth = TextWidth.WIDE) : String {
val tsp1 = a.toZonalTimestamp(tz.id)
val tsp2 = b.toZonalTimestamp(tz.id)
val d = zonedMetric.between(tsp1, tsp2)
return PrettyTime.of(locale).print(d, textWidth)
}
fun format(a: Instant, b: Instant = Instant.now(), locale: Locale = Locale.US, textWidth: TextWidth = TextWidth.WIDE): String =
format(
TemporalType.INSTANT.translate(a),
TemporalType.INSTANT.translate(b),
locale,
textWidth
)
}
and some JavaFX Text
, updated with Kotlin coroutines, to display the description.
Thanks again!
thanks for feedback and happy coding.
Hello. I'm trying to compute a duration between
Moment
s in differents units, but I can't compile my code because of type errors.The following code
generates
despite
Moment
extending extendsTimePoint<TimeUnit, Moment>
.What am I doing wrong?
Thanks.