来自ZoneDateTime UTC实例的Java日期和时间戳
我有一个java应用程序,我希望时间是UTC。目前,代码混合使用了来自ZoneDateTime UTC实例的Java日期和时间戳,java,sql,date,timestamp,Java,Sql,Date,Timestamp,我有一个java应用程序,我希望时间是UTC。目前,代码混合使用了java.util.Date和java.sql.Timestamp。为了获得UTC时间,我之前的程序员使用: 截止日期: Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant(); 对于时间戳: Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant()); 但是,我自己用这段代码运行了多个测试,这两行都返
java.util.Date
和java.sql.Timestamp
。为了获得UTC时间,我之前的程序员使用:
截止日期:
Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
对于时间戳:
Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
但是,我自己用这段代码运行了多个测试,这两行都返回当前日期/时间(在我当前的时区)。从我所读到的一切来看,日期/时间戳似乎没有区域偏移值,但我找不到这方面的具体说明
是否要将时区(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
在Java中,
Date
表示一个时间点。它与时间戳无关。当您调用toString()
对象的Date
方法时,它会将该时间转换为平台的默认时间戳,例如,下面将以UTC打印日期/时间(因为它将默认时区设置为UTC):
tl;博士
仅使用java.time类。避免在Java8之前添加麻烦的旧遗留日期时间类
使用java.time
您之前的程序员正在使用新的现代java.time类,这些类现在取代了臭名昭著的旧日期时间类,如日期
,日历
,时间戳
Instant
该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)。获取UTC当前时刻非常简单:Instant.now
Instant instant = Instant.now();
转换
您应该坚持使用java.time类,并避免使用遗留类。但是,如果绝对必要,例如与尚未更新为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.
JDBC
避免遗留日期时间类。改用java.time类
您的compliant可以通过调用和直接寻址java.time类型
……还有
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
如果没有,请返回使用java.sql类型,但要尽可能简短。使用添加到旧类中的新转换方法
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;
……还有
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
不需要ZoneDateTime
请注意,我们不需要您提到的ZoneDateTime
,因为您说您只对UTC感兴趣。Instant
对象始终以UTC为单位。这意味着您引用的原始代码:
Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
…可以简单地缩短为:
Date.from( Instant.now() ) ;
请注意,java.util.Date
也始终使用UTC。然而,它的toString
不幸地在生成字符串时隐式地应用了JVM的当前默认时区。通过搜索堆栈溢出,您可以看到,此反功能带来了无尽的混乱
如果要通过区域的镜头查看对象的UTC值,请指定时区ZoneId
,以获取ZoneDateTime
以大陆/地区
的格式指定,例如,或太平洋/奥克兰
。切勿使用3-4个字母的缩写,如CDT
或EST
或IST
,因为它们不是真正的时区,不标准化,甚至不是唯一的(!)
关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,& 该项目现已启动,建议迁移到类 要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是 您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*
类
从哪里获得java.time类
- 、和更高版本-标准Java API的一部分,带有捆绑实现。
- Java9添加了一些次要功能和修复
- 及
- 大部分java.time功能都在中向后移植到Java6和Java7
-
- 更高版本的Android捆绑包实现了java.time类
- 对于早期的Android(“…返回当前日期/时间(在我当前的时区)…”,可能您刚刚使用了方法
得出结论,但此方法仅使用外部默认时区打印自身。偏移量或时区从来不是toString()
上的java.util.Date
的一部分,其真实状态由方法java.util.Date
。因此,请澄清您真正做了什么。日期和时间戳都以GMT存储时间。切换时区只会更改显示值。getTime()反映
Date.from(ZonedDateTime.now(ZoneOffset.UTC.toInstant())和
。除前者外,前者更容易混淆。通常我不建议查看源代码,因为类的行为是由其契约(javadoc)定义的,但从Java 8开始,它只有两个实例字段:一个长值和一个“BaseCalendar”对象,仅由现在已弃用的方法使用(可追溯到日历类不存在且date类试图提供所有与日历相关的功能时)。它只包装一个毫秒值;不保留时区信息。为什么建议使用new Date()之间没有逻辑差异
而不是使用setObject()
类型java.sql
?@mFeinstein,因为timestamp
是一个糟糕的类设计的憎恶。java.time框架是由Sun、Oracle和JCP设计并采用的,以完全支持timestamp
Date.from( Instant.now() ) ;
ZoneId z = ZoneId.of( "America/Chicago" ); ZonedDateTime zdt = instant.atZone( z );