来自ZonedDateTime UTC实例的Java日期和时间戳

Dev*_*per 16 java sql timestamp date

我有一个java应用程序,我想在UTC中的时间.目前,该代码使用的混合java.util.Datejava.sql.Timestamp.为了得到UTC的时间,我之前的程序员使用了:

对于日期:

 Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
Run Code Online (Sandbox Code Playgroud)

对于时间戳:

 Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
Run Code Online (Sandbox Code Playgroud)

但是我自己用这个代码运行了多个测试,这两行都返回当前日期/时间(在我当前的时区).从我读过的所有内容看来,Date/Timestamp没有zoneOffset值,但我找不到具体的声明.

无论如何要将timeZone(UTC)保留在Date或Timestamp对象中,还是需要进行一些重构并在整个应用程序中使用实际的ZonedDateTime对象?此ZonedDateTime对象也将与sql的当前Timestamp对象兼容吗?

例:

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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

 ZonedDateTime: 2017-04-06T15:46:33.099Z
 Timestamp: 2017-04-06 10:46:33.109
 Date: Thu Apr 06 10:46:33 CDT 2017
Run Code Online (Sandbox Code Playgroud)

Bas*_*que 32

TL;博士

Instant.now()  // Capture the current moment in UTC with a resolution up to nanoseconds.
Run Code Online (Sandbox Code Playgroud)

仅使用java.time类.避免在Java 8之前添加麻烦的旧遗留日期时间类.

使用java.time

你被利用的新型现代化java.time类,现在取代了臭名昭著的麻烦旧的遗留日期时间类,如之前的程序员Date,Calendar,Timestamp.

Instant

Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).获取UTC中的当前时刻非常简单:Instant.now.

Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)

转换

您应该坚持使用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.
Run Code Online (Sandbox Code Playgroud)

JDBC

避免遗留日期时间类.请改用java.time类.

您的JDBC 4.2兼容驱动程序可以通过调用PreparedStatement::setObject和直接解决java.time类型ResultSet::getObject.

myPreparedStatement.setObject( … , instant ) ;
Run Code Online (Sandbox Code Playgroud)

......而且......

Instant instant = myResultSet.getObject( … , Instant.class ) ;
Run Code Online (Sandbox Code Playgroud)

如果没有,请回退到使用java.sql类型,但尽可能简短.使用添加到旧类的新转换方法.

myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;
Run Code Online (Sandbox Code Playgroud)

......而且......

Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
Run Code Online (Sandbox Code Playgroud)

没必要 ZonedDateTime

请注意,我们不需要您提到的,ZonedDateTime因为您说您只对UTC感兴趣.的Instant对象都可以在UTC.这意味着您引用的原始代码:

Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
Run Code Online (Sandbox Code Playgroud)

......可以简单地缩短为:

Date.from( Instant.now() ) ;
Run Code Online (Sandbox Code Playgroud)

请注意,java.util.Date它始终也是UTC.但是,toString遗憾的是,它在生成String时隐式应用JVM的当前默认时区.通过搜索Stack Overflow,您可以看到这种反特征不会产生混淆.

如果您想Instant通过区域挂钟时间的镜头查看对象的UTC值,请指定时区ZoneId以获得a ZoneDateTime.

指定适当的时区名称,格式continent/region,如America/Montreal,Africa/CasablancaPacific/Auckland.切勿使用3-4个字母的缩写,如CDTESTIST因为他们没有真正的时区,不规范,甚至不是唯一的(!).

ZoneId z = ZoneId.of( "America/Chicago" );
ZonedDateTime zdt = instant.atZone( z );
Run Code Online (Sandbox Code Playgroud)

关于java.time

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-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.

  • @mFeinstein因为'时间戳'是一种可怜的阶级设计的憎恶.*java.time*框架由Sun,Oracle和JCP设计和采用,完全取代了旧的日期时间类.JDBC 4.2更新的一个要点是向现代*java.time*类的过渡. (2认同)

Dar*_*hta 5

在Java中,Date代表一个时间点.它与时间戳无关.当您调用对象的toString()方法时Date,它会将该时间转换为平台的默认时间戳,例如,以下将以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);
Run Code Online (Sandbox Code Playgroud)