我正在使用JodaTime实现安卓应用程序的倒计时。根据设备的不同,输出是不同的。
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天4:39:18,而是错的:0天11788:49:11。我做错了什么?
发布于 2017-02-08 16:25:07
感谢您的评论,,我现在可以重现您的问题。只需将以下静态初始化程序添加到您的测试类(首先),以模拟您观察预期输出的设备:
static {
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
}根据规范(也请参阅接受此邮件的答复),转换duration.toPeriod(periodType)应该只使用所谓的精确持续时间字段,即小时、分钟、秒和毫秒,而不是天数。
我对Joda-Time源代码的分析(v2.9.6):
内部类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()持续时间字段的精度属性的额外区域依赖关系,即对于固定区域(例如UTC和else不精确的.)精确。
我不知道被分析和观察到的行为是一个特征还是一个缺陷。比方说,期望Period-objects由duration.toPeriod(...)创建是危险的。如果系统区域是固定的,那么有一个精确的天分量是在那里没有记录的。
不幸的是,默认时区的隐式依赖通过其年表设计被深度编码为Joda-Time。作为解决办法,您可以使用
Period p = new Period(nowDateTime, openingDateTime, PeriodType.dayTime());https://stackoverflow.com/questions/42114339
复制相似问题