[英]Different behavior of PeriodFormatter on different devices (JodaTime)
我正在使用 JodaTime 為 android 應用程序實現倒數計時器。 根據設備的不同,輸出是不同的。
DateTime openingDateTime = new DateTime(2018, DateTimeConstants.JUNE, 14, 21, 0, 0, DateTimeZone.forID("Europe/Moscow"));
DateTime nowDateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"));
long difference = openingDateTime.getMillis() - nowDateTime.getMillis();
(...)
onTick(difference);
(...)
PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
.printZeroAlways()
.appendDays().appendSuffix(" day", " days")
.appendSeparator(" ")
.appendHours()
.appendSeparator(":")
.appendMinutes()
.appendSeparator(":")
.appendSeconds()
.toFormatter();
(...)
@Override
public void onTick(long millisUntilFinished) {
Duration duration = new Duration(millisUntilFinished);
Period period = duration.toPeriod(PeriodType.dayTime());
tvCounter.setText(periodFormatter.print(period));
}
在一個設備上輸出正確: 491 days 4:39:18另一台錯誤: 0 days 11788:49:11 。 我究竟做錯了什么?
感謝您的評論,我現在可以重現您的問題。 只需將以下靜態初始化程序添加到您的測試類(首先)以模擬您觀察預期輸出的設備:
static {
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
}
根據規范(另請參閱此 SO-post 上已接受的答案),轉換duration.toPeriod(periodType)
應僅使用所謂的精確持續時間字段,即小時、分鍾、秒和毫秒,而不是天。
內部類org.joda.time.chrono.BasicChronology包含以下常量:
private static final DurationField cDaysField = new PreciseDurationField(DurationFieldType.days(), 86400000L);
所以我們看到這里這個持續時間字段被標記為“精確”,但是:子類 ZonedChronology 包裝它並覆蓋方法isPrecise()的行為:
public boolean isPrecise() {
return iTimeField ? iField.isPrecise() : iField.isPrecise() && this.iZone.isFixed();
}
這顯示了 days()-duration-field 的 precision 屬性的額外區域依賴性,即對於 UTC 等固定區域是精確的,否則是不精確的。
我不知道分析和觀察到的行為是功能還是錯誤。 比方說,期望通過duration.toPeriod(...)
創建Period
-objects 與區域無關是危險的。 如果系統區域是固定的,則那里沒有記錄有精確的天數組件。
不幸的是,對默認時區的隱式依賴通過其年表設計深深地編碼到 Joda-Time 中。 作為解決方法,您可以使用:
Period p = new Period(nowDateTime, openingDateTime, PeriodType.dayTime());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.