在Java中将Long转换为Date将返回1970年

mmm*_*iki 104 java date long-integer

我有从Web服务下载的长值列表(例如:1220227200,1220832000,1221436800 ...).我必须把它转换成日期.不幸的是这种方式,例如:

Date d = new Date(1220227200);
Run Code Online (Sandbox Code Playgroud)

返回1970年1月1日.任何人都知道另一种方法正确转换它?

Bal*_*usC 147

Date构造函数(点击链接!)接受的时间long毫秒,不秒.你需要将它乘以1000,并确保你提供它long.

Date d = new Date(1220227200L * 1000);
Run Code Online (Sandbox Code Playgroud)

这显示在这里

Sun Aug 31 20:00:00 GMT-04:00 2008

  • 或者,使用`Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));`用于更清洁且更少*magic-numberesque*解决方案. (19认同)

Bas*_*que 50

TL;博士

Instant.ofEpochSecond( 1_220_227_200L )
Run Code Online (Sandbox Code Playgroud)

了解您的数据

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

  • 什么时代?
    许多时代日期已被用于各种系统.常用的是POSIX/Unix时间,其中纪元是UTC中1970年的第一个时刻.但你不应该假设这个时代.
  • 什么精度?
    我们是否谈论自纪元以来的秒,毫秒,微秒纳秒
  • 什么时区?
    通常,自纪元以来的计数是UTC/GMT时区,即根本没有时区偏移.但有时,当涉及无经验或日期时间无知的程序员时,可能存在隐含的时区.

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

得到教训:

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

图表显示日期时间系统中各种粒度的分辨率,包括整秒,毫秒,微秒和纳秒.

你的数据

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

乔达时间

与Java捆绑在一起的java.util.Date和.Calendar类非常麻烦.避免他们.请使用Joda-Time库或Java 8中捆绑的新java.time包(灵感来自Joda-Time).

请注意,与juDate不同,DateTimeJoda-Time真正知道自己指定的时区.因此,在下面看到的示例Joda-Time 2.4代码中,请注意我们首先使用UTC的默认假设解析毫秒.然后,其次,我们指定一个巴黎时区进行调整.宇宙时间轴上的相同时刻,但不同的挂钟时间.为了演示,我们再次调整为UTC.几乎总是更好地明确指定您期望/预期的时区而不是依赖于隐式默认值(通常是日期时间工作中的麻烦的原因).

我们需要毫秒来构造DateTime.所以你要输入几秒钟,然后乘以一千.注意,结果必须是64位,long因为我们会溢出32位int.

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".
Run Code Online (Sandbox Code Playgroud)

向构造函数提供毫秒数.该特定构造函数假定计数来自1970年的Unix纪元.因此,在构造之后根据需要调整时区.

使用适当的时区名称,大陆和城市/地区的组合.切勿使用3或4个字母代码,EST因为它们既不标准也不唯一.

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );
Run Code Online (Sandbox Code Playgroud)

要进行演示,请再次调整时区.

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );
Run Code Online (Sandbox Code Playgroud)

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

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );
Run Code Online (Sandbox Code Playgroud)

跑步时

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
Run Code Online (Sandbox Code Playgroud)

java.time

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

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

An InstantUTC时间轴上的一个时刻,分辨率为纳秒.它的时代是1970年UTC的第一个时刻.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );
Run Code Online (Sandbox Code Playgroud)

应用偏移量来自UTC ZoneOffset以获得OffsetDateTime.

更好的是,如果已知,则应用时区ZoneId来获得ZonedDateTime.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Run Code Online (Sandbox Code Playgroud)

  • 干杯伙计。很好的解释。当我意识到我以秒为单位给出并以毫秒为单位要求时,我从 1970 年开始获得新的 DateTime(<long number>) (2认同)

Cod*_*nci 38

看起来你的长期是秒,而不是毫秒.日期构造函数需要时间作为毫秒,所以

Date d = new Date(timeInSeconds * 1000);
Run Code Online (Sandbox Code Playgroud)

  • 为什么这会得到一个downvote?在这里,享受反投票. (4认同)
  • @ f1sh:我没有downvote,但最初的答案是不同的.他在5分钟的宽限期内编辑了它. (4认同)

Mar*_*lon 10

仅在Calendar对象的工厂中设置时间

Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());
Run Code Online (Sandbox Code Playgroud)


Mag*_*ter 9

这些可能是以为单位的时间戳,而不是以java新的Date(long)构造函数所需的毫秒数.只需将它们乘以1000就可以了.

  • 更恰当的30000毫秒太慢了 (23认同)

Jac*_* G. 5

长值很可能与Epoch时间戳对应,值为:

1220227200 =周一,2008年9月1日00:00:00 GMT

1220832000 =周一,2008年9月8日00:00:00 GMT

1221436800 =星期一,2008年9月15日00:00:00 GMT

可以将这些长值转换为java.util.Date,考虑到事实java.util.Date使用毫秒 - 如前所述,但有一些缺陷 - 像这样:

// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L); 
Run Code Online (Sandbox Code Playgroud)

现在,要正确显示日期,可以使用java.text.DateFormat,如下所示:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));
Run Code Online (Sandbox Code Playgroud)

下面是在不使用和使用DateFormat的情况下将转换后的long值显示到java.util.Date的结果:

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC
Run Code Online (Sandbox Code Playgroud)