为什么通过SimpleDateFormat解析时Java纪元时间会延迟30分钟

t9aqgxwy  于 2024-01-05  发布在  Java
关注(0)|答案(1)|浏览(219)

以某种方式解析日期时间字符串并将其转换为纪元后的毫秒,在不同的环境中会有不同的工作方式。这似乎是时区或其他东西的问题。理论上,这个字符串应该表示纪元后的0秒:“1970-01- 01 T00:00:00 Z”
实际上,在开发人员的机器上,这是神秘的30分钟(18000000毫秒)。

  1. /**
  2. * This really ought to return 0, but locally it returns 30 minutes worth of milliseconds.
  3. * @return The milliseconds since the common epoch. Really ought to be zero, but isn't always.
  4. */
  5. public long determineMysteriousMachineTimeDelta() {
  6. String strDateOfEpochStart = "1970-01-01T00:00:00Z";
  7. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
  8. Date dateStartOfEpoch = null;
  9. try {
  10. dateStartOfEpoch = format.parse(strDateOfEpochStart);
  11. } catch (ParseException e) {
  12. return -1;
  13. }
  14. return dateStartOfEpoch.getTime();
  15. }

字符串
谢谢你,谢谢

dphi5xsq

dphi5xsq1#

tl;dr

  1. Instant.parse( "1970-01-01T00:00:00Z" )

字符串

Z,从不'Z'

永远不要在格式模式中的Z周围加上引号。
这个字母表示offset from UTC的零小时-分钟-秒。发音为“Zulu”。
你的引号表示“期待这段文字,但忽略它”,所以你的格式模式丢弃了关键信息。

避免使用旧的日期时间类

永远不要使用SimpleDateFormatCalendarDate类。这些都是遗留类,存在严重缺陷。它们在几年前就被JSR 310中定义的现代 java.time 类所取代。

java.time

您的输入字符串符合ISO 8601标准。
当解析/生成文本时,默认情况下在 java.time 类中使用该标准。因此无需指定格式模式。
要表示UTC中的某个时刻,请使用Instant类。

  1. Instant instant = Instant.parse( "1970-01-01T00:00:00Z" ) ;

epoch计数

询问从UTC(1970-01- 01 T00:00 Z)中看到的1970年第一个时刻的epoch reference开始的毫秒数。
因此,在您的示例中,我们期望计数为零毫秒。

  1. long millis = instant.toEpochMilli() ;


代码run at Ideone.com
顺便说一句,小心这里的数据丢失-Instant解析为纳秒,比毫秒精细得多。

展开查看全部

相关问题