如何在特定时区将 UTC 时间转换为 EpochMilli

0 time timezone utc instant kotlin

编辑:对不起,也许我的问题不正确......

我正在尝试将 UTC 时间戳转换为 Java(Kotlin) 中的本地时间戳

F。前任

UTC 时间 18:00 德国本地时间是 20:00 我需要 UTC 时间戳中的德国本地时间.....

    fun getLocalizedTime(locationId: Long, utcTimeInMs: Long? ): Long{
        val instant = Instant.ofEpochMilli(utcTimeInMs?:Instant.now().toEpochMilli())
        val zoneIdAsString = locationDataService.locationData.locations[locationId]?.timeZone
                ?: "UTC"
        val zoneId = ZoneId.of(zoneIdAsString)
        val zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId)

        return instant.atZone(zoneId).toInstant().toEpochMilli()
    }
}
Run Code Online (Sandbox Code Playgroud)

返回UTC时间:(

如何在特定时区将 UTC 时间转换为 EpochMilli

Bas*_*que 6

纪元毫秒是 UTC

没有“toEpochMilli in specific timeZone”这样的东西,如果你按照传统的定义去的话。从纪元参考开始的毫秒数始终是 UTC。

一个纪元的毫秒数以 UTC 计算。java.time和 Unix/POSIX使用的纪元参考是UTC 中的 1970 年的第一个时刻,1970-01-01T00:00Z。在Z上月底表示UTC,发音为“祖鲁”。到今天,各种信息系统使用了数十个其他纪元参考。

所以说“一个时区的纪元”是没有意义的。

如果您在 UTC 中计算了自 1970 年第一时刻以来的毫秒数,请解析为Instant.

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

要通过特定地区的人们使用的挂钟时间查看同一时刻,请调整到时区以获取ZonedDateTime.

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

TheInstant和 theZonedDateTime两者代表相同的同时时刻,时间线上的相同点,自纪元参考以来相同的毫秒数。

您可以Instant从 a 中提取 aZonedDateTime以返回到原始计数从纪元。

long millisecondsSinceEpoch = zdt.toInstant().toEpochMilli() ;  
Run Code Online (Sandbox Code Playgroud)

你会发现整数millisecondsmillisecondsSinceEpoch长整数是同一个数字。

你的代码instant.atZone(zoneId).toInstant()没有意义。您从 an 开始Instant,转换为 a ZonedDateTime,然后转换回 an Instant。所有三个对象都代表同一时刻,自纪元引用以来的相同毫秒数。你的那些电话没有完成任何有用的工作。

德国时间与UTC时间

在进一步澄清时,您说:

我需要 UTC 时间戳中的德国本地时间

定义您的特定时区。

ZoneId z = ZoneId.of( "Europe/Berlin" ) ;
Run Code Online (Sandbox Code Playgroud)

捕捉在那里看到的当前时刻。

ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Run Code Online (Sandbox Code Playgroud)

通过提取一个Instant.

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

如果绝对需要,询问毫秒数。

long milliseconds = instant.toEpochMilli() ;  // Beware of data loss, as any microseconds/nanoseconds are ignored. 
Run Code Online (Sandbox Code Playgroud)

建议将时刻作为纪元计数,因为分辨率(毫秒与整秒对比微秒对比纳秒对比其他)并不明显,纪元参考也不明显。相反,以标准ISO 8601格式以文本形式传达时刻。该java.time类生成/解析文本时默认使用ISO 8601种格式。所以不需要指定格式模式。

如果您只需要毫秒,请截断任何现有的微秒或纳秒。

    String output = instant.truncatedTo( ChronoUnit.MILLIS ).toString() ;  // Generate text in standard ISO 8601 format.
Run Code Online (Sandbox Code Playgroud)

查看此代码在 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


Java 中的日期时间类型表,现代和传统