給定2日期,我如何根據ISO 8601Year Month Day, Hour Minute Second持續時間計算它們之間的格式差異?
我只找到了可以在幾天或更短的時間內產生差異的 Java 庫。
鑒于月份和年份的天數不規則,我不確定如何計算月份和年份的差異。
EvenDuration.between()很接近,但它以小時分鐘秒為單位給出結果:
ZonedDateTime event1 = ZonedDateTime.of(2022, 2, 2, 2, 2, 2, 0, ZoneId.of("UTC-7"));
ZonedDateTime event2 = ZonedDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC-7"));
//ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC-7"));
Duration duration = Duration.between(event1, event2);
Log.d("Duration ISO-8601: ", duration.toString());
Output: PT25533H57M58S
即25533 小時、57 分鐘、58 秒。
我想看到類似的東西:
__ years, __ months, __ days, 9 hours, 57 minutes, 58 seconds
uj5u.com熱心網友回復:
您可以創建一個自定義類來維護Period和Duration欄位(感謝@Ole VV,因為他在評論中早些時候提到過)。
這是此類實作的示例,它公開了一個靜態方法between(),該方法需要兩個型別的引數LocalDateTime。
類似getYears()and的方法getHours()會將呼叫委托給Period和Duration物件。
class DateTimeSlot {
private Period period;
private Duration duration;
private DateTimeSlot(Period period, Duration duration) {
this.period = period;
this.duration = duration;
}
public int getYears() {
return period.getYears();
}
public int getMonth() {
return period.getMonths();
}
public int getDays() {
return period.getDays();
}
public int getHours() {
return duration.toHoursPart(); // this method can be safely used instead `toHours()` because `between()` implementation guerantees that duration will be less than 24 hours
}
public int getMinutes() {
return duration.toMinutesPart();
}
public int getSeconds() {
return (int) (duration.getSeconds() % 60);
}
public static DateTimeSlot between(LocalDateTime from, LocalDateTime to) {
if (from.isAfter(to) || from.equals(to)) {
throw new IllegalArgumentException();
}
Duration duration;
Period period;
if (from.toLocalTime().isBefore(to.toLocalTime())) {
duration = Duration.between(from.toLocalTime(), to.toLocalTime());
period = Period.between(from.toLocalDate(), to.toLocalDate());
} else {
duration = Duration.between(to.withHour(from.getHour())
.withMinute(from.getMinute())
.withSecond(from.getSecond())
.minusDays(1), to); // apply shift one day back
period = Period.between(from.toLocalDate()
.plusDays(1), to.toLocalDate()); // apply shift one day forward (to compensate the previous shift)
}
return new DateTimeSlot(period, duration);
}
@Override
public String toString() {
return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
getYears(), getMonth(), getDays(), getHours(), getMinutes(), getSeconds());
}
}
main()- 演示
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.of(2022, 5, 20, 18, 0, 18);
LocalDateTime withTimeBefore = LocalDateTime.of(2020, 12, 31, 15, 9, 27);
LocalDateTime withTimeAfter = LocalDateTime.of(2020, 12, 31, 22, 50, 48);
DateTimeSlot slot1 = DateTimeSlot.between(withTimeBefore, now);
DateTimeSlot slot2 = DateTimeSlot.between(withTimeAfter, now);
System.out.println(slot1);
System.out.println(slot2);
}
輸出
1 years, 4 months, 20 days, 2 hours, 50 minutes, 51 seconds // between 2020-12-31T15:09:27 and 2022-05-20T18:00:18
1 years, 4 months, 19 days, 19 hours, 9 minutes, 30 seconds // between 2020-12-31T22:50:48 and 2022-05-20T18:00:18
uj5u.com熱心網友回復:
我相信我已經解決了:
ZonedDateTime event1 = ZonedDateTime.of(2022, 2, 2, 2, 2, 2, 0, ZoneId.of("UTC-7"));
ZonedDateTime event2 = ZonedDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC-7"));
Duration duration = Duration.between(event1, event2);
Period period = Period.between(event1.toLocalDate(), event2.toLocalDate());
Log.d("Duration ISO-8601: ", period.toString() duration.toString());
這列印:
P2Y10M30DPT25533H57M58S
也就是 2 年 10 個月 30 天 25533 小時 57 分 58 秒。
提取單個值(這是我需要的)時,使用模數解決了小時的問題:
String.valueOf(duration.toHours() % 24)
如果分鐘和秒有任何問題,% 60 會修復它。
uj5u.com熱心網友回復:
我的庫Time4J支持計算和列印此類持續時間。使用您的輸入的示例:
PlainTimestamp event1 = PlainTimestamp.of(2022, 2, 2, 2, 2, 2);
PlainTimestamp event2 = PlainTimestamp.of(2025, 1, 1, 0, 0, 0);
TZID tzid = ZonalOffset.ofHours(OffsetSign.BEHIND_UTC, 7);
Duration<IsoUnit> duration =
Duration.in(
Timezone.of(tzid),
CalendarUnit.YEARS,
CalendarUnit.MONTHS,
CalendarUnit.DAYS,
ClockUnit.HOURS,
ClockUnit.MINUTES,
ClockUnit.SECONDS)
.between(event1, event2);
System.out.println(PrettyTime.of(Locale.US).print(duration));
// 2 years, 10 months, 29 days, 21 hours, 57 minutes, and 58 seconds
一個很大的優勢是輸出的良好國際化,包括依賴于語言的復數規則,另請參見javadoc。
如果您的輸入發生變化(一些轉換示例),您還可以使用瞬間/時刻作為輸入,然后像這樣轉換為本地時間戳:
tzid = () -> "America/Chicago"; // probably better than your fixed offset
event1 = TemporalType.LOCAL_DATE_TIME.translate(LocalDateTime.of(2022, 2, 2, 2, 2, 2));
event2 = Moment.nowInSystemTime().toZonalTimestamp(tzid);
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/479578.html
