Joda Time的Java时区问题

时间:2013-08-30 17:33:12

标签: java date tomcat timezone jodatime

我有一个相当棘手的问题,一些日期解析并从我的格式中获取正确的日期/时间。这是执行格式化的代码(精简版)

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
log.debug("Trying to convert {} using format {}.", val, "yyyy-MM-dd");
Date toDate = formatter.parseDateTime(inputText).toDate();
log.debug("Converted value to {}", toDate);

以下是不正确的值的输出。此处的时区设置为EDT。 (通过date命令和/ etc / localtime符号链接检查。

13:14:53.618 [http-bio-8080-exec-13] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd.
13:14:53.619 [http-bio-8080-exec-13] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Sun Jul 07 20:00:00 EDT 2013

这是在使用OpenJDK 7的Tomcat 7上的AWS-LINUX上运行。我们在AWS上运行了另一个实例,相同的代码生成了这个:

17:22:46.164 [http-bio-8080-exec-239] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd.
17:22:46.165 [http-bio-8080-exec-239] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Mon Jul 08 00:00:00 UTC 2013

此机器上的时区设置为UTC。

在我的本地机器上,输出也是正确的(回到EDT这里在OS X上运行oracles JDK):

13:24:55.967 [ajp-bio-8009-exec-176] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Trying to convert 2013-07-08 using format yyyy-MM-dd.
13:24:56.089 [ajp-bio-8009-exec-176] DEBUG c.s.e.p.j.AbstractParamToObjectProvider - Converted value to Mon Jul 08 00:00:00 EDT 2013

同样,所有三个点都有相同的代码。我不能为我的生活弄清楚为什么我们有一个不像其他人那样行动的实例。我将添加一些调试输出以尝试缩小范围,但截至目前我还是运气不好。

另外,另一个有趣的一点。在错误的机器上运行Tomcat外部,使用相同的jdk和以下代码,我得到了我的期望:

DateTimeFormatter f = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime parseDateTime = f.parseDateTime("2013-07-08");
System.out.println(parseDateTime.toDate());

输出:

Mon Jul 08 00:00:00 EDT 2013

更新

看起来Joda没有使用系统默认时区。这是我输出数据的方式:

log.debug("Using joda timezone of: {}", DateTimeZone.getDefault());
log.debug("Default timezone of: {}", TimeZone.getDefault());

这是输出:

AbstractParamToObjectProvider - Using joda timezone of: UTC
AbstractParamToObjectProvider - Default timezone of: sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]]

其中一件事与其他事情不符......任何想法为什么?

乔恩的回答是正确的,但这是最后的决定。

不知何故,user.timezone被设置为UTC而Joda正在使用它,而默认的TimeZone则没有(使用系统时区)。对于补丁,我做了以下事情:

DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));

只是为了确保事情符合。 “正确”修复是在应用启动时明确设置系统默认时区。

1 个答案:

答案 0 :(得分:4)

Joda Time经历以下步骤:

  • 使用user.timezone系统属性
  • 根据TimeZone.getDefault()
  • 的ID创建时区
  • 回归UTC

TimeZone.getDefault()可能会有点复杂,但在很多情况下它也会使用user.timezone

一个选项是显式在应用程序启动时将TimeZoneDateTimeZone的默认时区设置为UTC:对于Web服务器,它是最合理的默认使用(虽然我个人更喜欢在适当的时候明确说明时区)。