繁体   English   中英

将joda.time.DateTime转换为java.sql.Date并保留时区

[英]Convert joda.time.DateTime to java.sql.Date and retain time zone

我有以下场景:

  • 返回Calendar对象的Swing控件
  • 我用来做重日期/时间操作的中间DateTime对象(joda)
  • 仅接受java.sql.Date对象的数据库连接( OraclePreparedStatement

我的问题是CalendarDateTime对象正在以GMT(我想要)正确显示日期,但是当我转换为java.sql.Date以便发送到数据库时,日期将转换为本地时区。

例如:

  • CalendarDateTime是2012-08-13T23:59:59.000Z(正确的GMT)
  • 产生的java.sql.Date是2012-08-14(本地UTC + 2日期不正确)

下面是我用来进行转换的代码。

DateTime dateGmt = new DateTime(calendarGmt.getTimeInMillis(), DateTimeZone.UTC);
java.sql.Date sqlDate = new java.sql.Date(dateGmt.getMillis());

我不知道如何创建一个java.sql.Date对象,同时保留正确的时区。 我完全有可能做错误的转换。

浪费时间

一个问题可能是java.sql.Date应该是......

通过在与实例关联的特定时区中将小时,分钟,秒和毫秒设置为零来“标准化”。

......根据文件 这意味着,日期时间的时间部分将从java.util.Date或Joda-Time DateTime对象中清除。

没有时区

正如Gilbert Le Blanc指出的正确答案 ,java.util.Date和java.sql.Date都没有内部时区的概念。 它们存储自Unix 纪元以来的毫秒数。

这些类带来了一个讨厌的技巧 :它们的toString方法将JVM的默认时区应用于字符串的呈现。 很混乱。 Date对象没有时区,但当显示为字符串时,您会看到一个时区。

如果您的java.util.Date对象包含自纪元(1970年开始)以来的1344902399000L毫秒数,则表示2012-08-13T23:59:59.000Z (UTC / GMT)。 但如果您的JVM认为自己在夏令时有效,那么您将看到提前2小时的UTC / GMT: 2012-08-14T01:59:59.000+02:00在该课程中描述糟糕的字符串格式。 同一时刻在不同的时区有不同的日期意义(13对14),墙上的时钟已经过了午夜。

Joda-救援时间

Joda-Time 2.4库在这里很有帮助。 将java.sql.Date或java.util.Date对象与UTC时区对象一起传递给DateTime构造函数,以获得您正在苦苦挣扎的值的清晰图片。

java.util.Date date = new java.util.Date( 1390276603054L );
DateTime dateTimeUtc = new DateTime( date, DateTimeZone.UTC );
System.out.println( "dateTimeUtc: " + dateTimeUtc );

跑的时候......

2014-01-21T03:56:43.054Z

将另一个方向从Joda-Time转换为java.util.Date ...

java.util.Date date = myDateTime.toDate();

将另一个方向从Joda-Time转换为java.sql.Date ...

java.sql.Date date = new java.sql.Date( myDateTime.getMillis() );

更新 - java.time

Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。

java.util.Date的等价物是Instant Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。

Instant instant = Instant.ofEpochMilli( 1390276603054L );

应用时区ZoneId生成ZonedDateTime ,类似于java.util.Calendar和Joda-Time DateTime

ZoneId z = ZoneId.of( "Europe/Kaliningrad" );
ZonedDateTime zdt = instant.atZone( z );

现在提取一个仅限日期的值,即ZonedDateTime的日期部分,作为LocalDate LocalDate类表示没有时间且没有时区的仅日期值。 因此, LocalDatejava.sql.Date假装的:仅限日期的值。

LocalDate localDate = zdt.toLocalDate() ;

在JDBC 4.2及更高版本中,您可以通过PreparedStatement::setObjectResultSet::getObject直接将java.time类型与兼容的驱动程序一起使用。

myPreparedStatement.setObject( … , localDate );

…和…

LocalDate ld = myResultSet.getObject( … , LocalDate.class );

对于较旧的不兼容驱动程序,通过使用添加到旧类的新方法简单地转换为/来自LocalDatejava.sql.Date对象: toLocalDatevalueOf( LocalDate )

java.sql.Date的内部表示是自1970年1月1日00:00:00.000 GMT以来经过的毫秒数。

你确定你没有看到toString问题吗? toGMTString()方法虽然已经折旧,但仍然存在。

我想你可能需要添加配置文件TIMEZONE = GMT

在Web应用程序中,这是在web.xml中定义的

<context-param> <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</p‌​aram-name> <param-value>true</param-value> </context-param>

问候

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM