使用Joda-Time在Java中的UTC区域中的日期

时间:2014-03-13 19:27:43

标签: java date datetime jodatime utc

我需要将Joda-Time日期/时间转换为java.util.Date。我正在做如下。

DateTimeFormatter dateTimeFormatter=DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa");
DateTime dateTime = dateTimeFormatter.parseDateTime("2-Oct-2013 11:34:26 AM").withZone(DateTimeZone.UTC);

System.out.println(dateTime);

按预期显示由UTC区域表示的日期/时间。在这种情况下,它是2013-10-02T06:04:26.000Z

将此dateTime转换为java.util.Date时,如下所示

System.out.println(dateTime.toDate());

显示,Wed Oct 02 11:34:26 IST 2013。它应该是UTC格式。

从Joda-Time转换后,有没有办法在Date中代表UTC

我希望将日期存储到UTC区域所代表的数据库中。在将org.joda.time.DateTime插入数据库之前,需要将java.util.Date转换为java.sql.Timestamp(或{{1}})。如何克服这种情况?

3 个答案:

答案 0 :(得分:5)

每个定义的java.util.Date对象始终为UTC!
(时间戳是自1.1.1970 UTC以来的毫秒数)

但是你必须在时间格式化之前将timeZone设置为utc:

TimeZone utc = TimeZone.getTimeZone("UTC")

SimpleDateFormatter df = new SimpleDateFormatter (PATTERN);
df.setTimeZone(utc);

System.out.println(df.format(date));

在您的代码中,您使用了使用系统默认TimeZone的java.util.Date.toString()方法。

答案 1 :(得分:2)

java.util.Date字符串输出不是UTC

来自你的问题:

  

它显示,10月02日星期三11:34:26 IST 2013.它应该是UTC格式。

不应该采用UTC格式。这可能是你想要的,但这并不是课堂行为的记录方式。

您的代码:

System.out.println(dateTime.toDate());

...首先将Joda-Time DateTime转换为java.util.Date对象,然后在该j.u.Date对象上隐式调用toString方法。 j.u.Date对其toString方法的记录行为是将JVM当前的默认时区应用于生成的字符串。在内部,j.u.Date确实是UTC,但它生成的字符串不是。它的toString的这种行为是一个善意但最终非常糟糕的Java团队设计决策,它给无数程序员带来了混乱。但它记录了行为。您应该始终仔细阅读库的文档,而不是假设库的行为与您想象的一样。

以UTC

显示Joda-Time DateTime

来自你的问题:

  

从Joda-Time转换后,有没有办法用UTC表示日期?

是的,在Joda-Time中生成DateTime UTC的字符串表示非常简单明了,与java.util.Date/.Calendar/SimpleDateFormat不同。只需调用withZone即可根据原始实例显示新的DateTime,但调整为另一个时区。

Joda-Time 2.5中的一个小例子源代码应该很明显。还可以使用Joda-Time搜索StackOverflow以获取数百个示例。

DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime nowInMontréal = DateTime.now( zoneMontréal );

DateTimeZone zoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTime nowInKolkata = nowInMontréal.withZone( zoneKolkata ); // Instantiating a new date-time object based on the original but adjusted for another time zone.

DateTime nowInUtc = nowInMontréal.withZone( DateTimeZone.UTC ); // Ditto, new object, adjusted time zone.

通过在每个DateTime上调用toString转储到控制台:

nowInMontréal: 2014-11-14T02:03:19.932-05:00
nowInKolkata: 2014-11-14T12:33:19.932+05:30
nowInUtc: 2014-11-14T07:03:19.932Z

所有这三个代表宇宙时间轴中的同时时刻。蒙特利尔时间比UTC晚5个小时,印度时间比UTC早5个半小时。同一时刻,但不同的挂钟时间。

将Joda-Time DateTime放入数据库

来自你的问题:

  

我希望将日期存储到UTC区域所代表的数据库中。在将org.joda.time.DateTime插入数据库之前,需要将其转换为java.util.Date(或java.sql.Timestamp)。如何克服这种情况?

易。通过传递自Unix纪元以来的毫秒数来构造java.sql.Timestamp对象。请注意,计数必须是long,而不是int

java.sql.Timestamp ts = new java.sql.Timestamp( dateTime.getMillis() );

提示:请注意数据库的日期时间数据类型的性质。例如,Postgres对此类类型提供了出色的支持,包括SQL规范定义的类型。许多数据库都没有,使用旧的遗留类型或只有少数弱类型。阅读文档和实验,以确保您了解行为。

答案 2 :(得分:0)

public Date toDate(TimeZone timeZone)

  

使用指定的时区将日期时间作为java.util.Date获取。

     

创建的Date对象与此日期时间具有完全相同的字段,除非由于夏令时间隙而导致时间无效。在这种情况下,时间将设置为差距之后的最早有效时间。

     

在夏令时重叠的情况下,选择较早的时刻。

     

转换为JDK日期充满了复杂性,因为JDK Date构造函数的行为与您在DST转换时的预期不同。该方法通过先猜测然后调整来工作。这也处理JDK时区数据与Joda-Time时区数据不同的情况。

     

与toDate()不同,此实现不依赖于Java的同步时区初始化逻辑,并且应该展示更好的并发性能特征。

所以这看起来像:

Timezone utc = Timezone.getTimezone("UTC")
System.out.println(dateTime.toDate(utc));

让我知道它是否有效。