纪元毫秒以 UTC 为单位
没有“toEpochMilli in specific timeZone”这样的东西,如果你按照传统定义去的话。从纪元引用算起的毫秒数始终为 UTC。
一个纪元的毫秒计数以 UTC 时间计算。 java.time 和 Unix/POSIX 使用的纪元参考是 1970 年的第一个时刻 UTC,1970-01-01T00:00Z。末尾的Z 表示UTC,发音为“Zulu”。到了今天,各种信息系统使用了几十个其他纪元参考。
所以说“时区中的纪元毫”是没有意义的。
如果您有自 1970 年第一刻 UTC 以来的毫秒数,则解析为 Instant。
Instant instant = Instant.ofEpochMilli( milliseconds ) ;
要通过特定地区的人们使用的挂钟时间查看同一时刻,请调整到时区以获取ZonedDateTime。
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Instant 和 ZonedDateTime 都表示同一时刻,时间轴上的同一点,自纪元引用以来的相同毫秒数。
您可以从ZonedDateTime 中提取Instant 以返回到原来的count-from-epoch。
long millisecondsSinceEpoch = zdt.toInstant().toEpochMilli() ;
你会发现milliseconds和millisecondsSinceEpoch长整数是同一个数字。
您的代码instant.atZone(zoneId).toInstant() 没有意义。您从Instant 开始,转换为ZonedDateTime,然后转换回Instant。所有三个对象都代表同一个时刻,自 epoch 引用以来的相同毫秒数。你的那些电话没有完成任何有用的工作。
德国时间到 UTC
进一步澄清,你说:
我需要 UTC 时间戳中的德国当地时间
定义您的特定时区。
ZoneId z = ZoneId.of( "Europe/Berlin" ) ;
捕捉那里看到的当前时刻。
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
通过提取 Instant 来调整到 UTC。
Instant instant = zdt.toInstant() ;
如果绝对需要,询问毫秒数。
long milliseconds = instant.toEpochMilli() ; // Beware of data loss, as any microseconds/nanoseconds are ignored.
我确实不建议将时刻作为从纪元开始的计数来传达,因为分辨率(毫秒与整秒与微秒与纳秒与其他东西)并不明显,纪元参考也不明显。取而代之的是,以标准ISO 8601 格式以文本形式传达时刻。 java.time 类在生成/解析文本时默认使用 ISO 8601 格式。所以不需要指定格式模式。
如果您只需要毫秒,请截断任何现有的微秒或纳秒。
String output = instant.truncatedTo( ChronoUnit.MILLIS ).toString() ; // Generate text in standard ISO 8601 format.
看到这个code run live at IdeOne.com。
zdt.toString(): 2020-05-09T23:57:35.363701+02:00[欧洲/柏林]
instant.toString(): 2020-05-09T21:57:35.363701Z
毫秒:1589061455363
输出:2020-05-09T21:57:35.363Z