在 Java 中将 Long 转换为 Date 返回 1970tl;博士了解您的数据您的数据城大时间java.time

2022-08-31 08:17:52

我有一个包含长值的列表(例如:1220227200,1220832000,1221436800...),这是我从Web服务下载的。我必须将其转换为日期。不幸的是,这种方式,例如:

Date d = new Date(1220227200);

返回 1970 年 1 月 1 日。有人知道正确转换它的另一种方法吗?


答案 1

Date 构造函数(单击链接!)接受以毫秒为单位的时间,而不是秒。您需要将其乘以 1000,并确保将其作为 .longlong

Date d = new Date(1220227200L * 1000);

这显示在这里

周日 8月31日 20:00:00 GMT-04:00 2008


答案 2

tl;博士

java.time.Instant                    // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.

了解您的数据

纪元以来,人们使用各种精度来跟踪时间作为数字。因此,当您获得一些要解释为自某个纪元以来的计数的数字时,您必须确定:

  • 什么时代?
    许多纪元日期已在各种系统中使用。常用的是 POSIX/Unix 时间,其中纪元是 UTC 中 1970 年的第一个时刻。但你不应该假设这个时代。
  • 精度是多少?
    我们是在谈论自纪元以来秒、毫秒、微秒还是纳秒
  • 什么时区?
    通常,由于 epoch 处于 UTC/GMT 时区,因此计数根本没有时区偏移量。但有时,当涉及没有经验或对日期时间不了解的程序员时,可能会有一个隐含的时区。

在你的情况下,正如其他人所指出的,自Unix时代以来,你似乎得到了几秒钟。但是,您正在将这些秒数传递给期望毫秒的构造函数。因此,解决方案是乘以1,000。

经验 教训:

  • 确定,不要假设,接收到的数据的含义。
  • 阅读文档

Graph showing various granularities of resolution in date-time systems including whole seconds, milliseconds, microseconds, and nanoseconds.

您的数据

您的数据似乎在整整几秒钟内。如果我们假设一个 1970 年初的时代,如果我们假设 UTC 时区,那么就是 2008 年 9 月第一天的第一个时刻。1,220,227,200

城大时间

java.util.Date 和 .与Java捆绑在一起的日历类是出了名的麻烦。避免它们。请改用 Joda-Time 库或捆绑在 Java 8 中的新 java.time 包(并受到 Joda-Time 的启发)。

请注意,与 j.u.Date 不同,Joda-Time 中的 DateTime 真正知道自己分配的时区。因此,在下面看到的示例Joda-Time 2.4代码中,请注意,我们首先使用默认的UTC假设来解析毫秒。然后,其次,我们分配巴黎的时区进行调整。宇宙时间线中的相同时刻,但不同的挂钟时间。为了进行演示,我们再次调整为 UTC。几乎总是最好显式指定所需的/预期的时区,而不是依赖于隐式默认值(通常是日期时间工作中出现问题的原因)。

我们需要毫秒来构造一个 DateTime。因此,以你输入的秒数,乘以一千。请注意,结果必须是 64 位,因为我们会溢出 32 位 。longint

long input = 1_220_227_200L;  // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".

将毫秒数馈送到构造函数。该特定构造函数假定计数来自 1970 年的 Unix 时代。因此,在施工后根据需要调整时区。

使用正确的时区名称,即大洲和城市/地区的组合。切勿使用3或4个字母的代码,因为它们既不是标准化的也不是唯一的。EST

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );

对于演示,请再次调整时区。

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );

转储到控制台。请注意,蒙特利尔的日期有何不同,因为新的一天已在欧洲开始,但尚未在美国开始。

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );

运行时。

dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00

java.time

Joda-Time的制造商要求我们尽快迁移到它的替代品java.time框架。虽然Joda-Time继续得到积极支持,但所有未来的开发都将在ThreeTen-Extra项目中的java.time类及其扩展上完成。

Java-time 框架由 JSR 310 定义,并内置于 Java 8 及更高版本中。java.time类已经移植到ThreeTen-Backport项目中的Java 6和7以及ThreeTenABP项目中的Android。

即时是时间轴上以 UTC 为单位的一个时刻,分辨率为纳秒。它的时代是UTC中1970年的第一个时刻。

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

应用“从 UTC 区域偏移”偏移获取 OffsetDateTime

更好的是,如果已知,请应用时区ZoneId以获取ZonedDateTime

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Table of all date-time types in Java, both modern and legacy