[英]Java Date and Timestamp from instance of ZonedDateTime UTC
我有一个 Java 应用程序,我希望在其中使用 UTC 时间。 目前,该代码混合使用java.util.Date
和java.sql.Timestamp
。 为了获得UTC时间,我之前的程序员使用:
日期:
Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
对于时间戳:
Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
但是,我自己使用此代码运行了多个测试,这两行都返回当前日期/时间(在我当前的时区)。 从我读过的所有内容来看,日期/时间戳似乎没有 zoneOffset 值,但我找不到具体的说明。
无论如何要在 Date 或 Timestamp 对象中保留 timeZone (UTC),或者我是否需要进行一些重构并在整个应用程序中使用实际的 ZonedDateTime 对象? 这个 ZonedDateTime 对象是否与当前的 sql 时间戳对象兼容?
例子:
public static void main (String args[])
{
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
Timestamp timestamp = Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
Date date = Date.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
System.out.println("ZonedDateTime: " + zonedDateTime);
System.out.println("Timestamp: " + timestamp);
System.out.println("Date: " + date);
}
输出:
ZonedDateTime: 2017-04-06T15:46:33.099Z
Timestamp: 2017-04-06 10:46:33.109
Date: Thu Apr 06 10:46:33 CDT 2017
Instant.now() // Capture the current moment in UTC with a resolution up to nanoseconds.
仅使用java.time类。 避免在 Java 8 之前添加的麻烦的旧的遗留日期时间类。
您之前的程序员正在使用新的现代 java.time 类,这些类现在取代了臭名昭著的旧的遗留日期时间类,例如Date
、 Calendar
、 Timestamp
。
Instant
Instant
类表示UTC时间轴上的一个时刻,分辨率为纳秒(最多九 (9) 位小数)。 获取 UTC 中的当前时刻非常简单: Instant.now
。
Instant instant = Instant.now();
您应该坚持使用 java.time 类,并避免使用遗留类。 但如果绝对必要,例如与尚未为 java.time 更新的旧代码接口,您可以转换为/从 java.time。 寻找旧类的新方法。 旧类java.util.Date
等效项是Instant
。
java.util.Date d = java.util.Date.from( myInstant); // To legacy from modern.
Instant instant = myJavaUtilDate.toInstant(); // To modern from legacy.
避免使用旧的日期时间类。 改用 java.time 类。
您的JDBC 4.2兼容驱动程序可能能够通过调用PreparedStatement::setObject
和ResultSet::getObject
直接处理 java.time 类型。
myPreparedStatement.setObject( … , instant ) ;
… 和 …
Instant instant = myResultSet.getObject( … , Instant.class ) ;
如果不是,请回退到使用 java.sql 类型,但要尽可能简短。 使用添加到旧类的新转换方法。
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;
… 和 …
Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
ZonedDateTime
请注意,我们不需要您提到的ZonedDateTime
因为您说您只对 UTC 感兴趣。 Instant
对象始终采用 UTC。 这意味着您引用的原始代码:
Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
……可以简单地缩短为:
Date.from( Instant.now() ) ;
请注意, java.util.Date
也始终采用 UTC。 然而,不幸的是,它的toString
在生成字符串时隐式地应用了 JVM 的当前默认时区。 正如您可以通过在 Stack Overflow 上搜索看到的那样,此反功能会造成无休止的混乱。
如果您想通过区域挂钟时间的镜头查看Instant
对象的 UTC 值,请分配时区ZoneId
以获取ZoneDateTime
。
以continent/region
的格式指定正确的时区名称,例如America/Montreal
、 Africa/Casablanca
或Pacific/Auckland
。 切勿使用 3-4 个字母的缩写,例如CDT
或EST
或IST
因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Chicago" );
ZonedDateTime zdt = instant.atZone( z );
java.time框架内置于 Java 8 及更高版本中。 这些类取代麻烦的老传统日期时间类,如java.util.Date
, Calendar
,和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle 教程。 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310 。
您可以直接与您的数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC 驱动程序。 不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
ThreeTen-Extra项目用额外的类扩展了 java.time。 该项目是未来可能添加到 java.time 的试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多。
在 Java 中, Date
代表一个时间点。 它与时间戳无关。 当您调用Date
对象的toString()
方法时,它会将该时间转换为平台的默认时间戳,例如以下将以 UTC 打印日期/时间(因为它将默认时区设置为 UTC):
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
Timestamp timestamp = Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
Date date = Date.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
System.out.println("ZonedDateTime: " + zonedDateTime);
System.out.println("Timestamp: " + timestamp);
System.out.println("Date: " + date);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.