【问题标题】:Joda time week calculation reasoningJoda时间周计算推理
【发布时间】:2024-01-14 11:06:01
【问题描述】:

下面的代码演示了周计算的有问题的 joda-time 实现。这种行为不是错误,而是设计决策Joda-Time uses the ISO standard Monday to Sunday week.(也许它应该是错误?)

给定一个我需要计算周数的日期,这个计算本质上必须是 i18n。意思是我必须根据用户的区域设置考虑正确的周编号。

下面的演示代码显示了 Joda-Time 的错误计算和 JDK 的正确计算,在应用程序中,我们尝试坚持 Joda-Time 作为日期操作的卓越解决方案。那么,我应该混合两个时间计算库吗?我显然不希望这样做,这甚至是安全的事情吗,还是我会遇到极端情况(有使用 Date、Calendar 的经验,我知道这对 Java 来说是一个痛苦的问题)。

底线:针对所述要求推荐的最佳实践是什么?

问题演示代码

请参阅此online calendar displaying week numbers 了解正确的周计算示例。

public class JodaTest {
 static DateTimeFormatter formatter = DateTimeFormat.forPattern("ww yyyy");
 static SimpleDateFormat jdkFormatter = new SimpleDateFormat("ww yyyy");

 public static void main(String[] args) {
  DateTime time = new DateTime(/*year*/2009, /*monthOfYear*/12, /*dayOfMonth*/6, /*hourOfDay*/23, /*minuteOfHour*/0, /*secondOfMinute*/0, /*millisOfSecond*/0);

  StringBuilder buffer = new StringBuilder()
   .append("Testing date ").append(time.toString()).append("\n")
   .append("Joda-Time timezone is ").append(DateTimeZone.getDefault()).append(" yet joda wrongly thinks week is ").append(formatter.print(time)).append("\n")
   .append("JDK timezone is ").append(TimeZone.getDefault().getID()).append(" yet jdk rightfully thinks week is ").append(jdkFormatter.format(time.toDate())).append(" (jdk got it right ?!?!)");

  System.out.println(buffer.toString());
 }
}

输出:

Testing date 2009-12-06T23:00:00.000+02:00
Joda-Time timezone is Asia/Jerusalem yet joda wrongly thinks week is 49 2009
JDK time zone is Asia/Jerusalem yet jdk rightfully thinks week is 50 2009 (jdk got it right ?!?!)

【问题讨论】:

  • 是什么阻止您以 -1 偏移量呈现一周?或者在需要时从 joda 转换为 JDK 类?
  • 这实际上不是 -1 周的偏移量。在耶路撒冷,一周不是从星期一开始,而是从星期日开始。而且.. JodaTime 比 JDK 日期/日历更好!只有他运气不好,没有生活在遵守 ISO 日期时间标准的国家。我认为除了通过在一周前增加 1 天来解决这个问题之外,没有什么可做的了。
  • 伙计们,您的建议实际上是重新为自己实施时区。耶路撒冷只是当前的例子。该代码可能在欧洲/阿姆斯特丹甚至非洲/布琼布拉运行,您不会指望我跟踪我应该添加/减去多少天。

标签: java calendar jodatime week-number


【解决方案1】:

最好的可用解决方案是编写DateTimeField 的实现,它包含逻辑以根据语言环境提取您需要的值。在内部,您可能仍会依赖 JDK 数据。目的是将所有 JDK 代码包装在一个可重用的类中。然后你像这样使用它:

int value = dateTime.get(new LocaleAwareWeekField("en_GB"));

【讨论】:

  • Hmmmm... 我想是这样,尽管由于我们在世界时间测量系统中存在的所有“人类时间”极端情况,这里的特征率误差会非常高。我会接受你的回答,因为这可能是正确的选择。
最近更新 更多