it-swarm.cn

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

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

Date d = new Date(1220227200);

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

97
mmmiki

Date构造函数 (单击链接!)接受时间为long in milliseconds ,而不是秒。您需要将它乘以1000,并确保将其作为long提供。

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

这显示在这里

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

138
BalusC

tL;博士

Instant.ofEpochSecond( 1_220_227_200L )

了解您的数据

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

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

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

得到教训:

  • 确定,不假设接收数据的含义。
  • 阅读 doc

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

你的数据

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

乔达时间

与Java捆绑在一起的Java.util.Date和.Calendar类非常麻烦。避免他们。而是使用 Joda-Time 库或Java 8中捆绑的新 Java.time包 (受Joda-Time启发)。

请注意,与j.u.Date不同,Joda-Time中的 DateTime 确实知道自己分配的 时区 。因此,在下面看到的示例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".

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

使用 适当的时区 名称,大陆和城市/地区的组合。切勿使用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继续得到积极支持,但未来的所有开发都将在Java.time类及其在ThreeTen-Extra项目中的扩展上完成。

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

InstantUTC 中时间轴上的一个时刻,分辨率为纳秒。它的纪元是1970年UTC的第一个时刻。

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

应用 offset-from-UTCZoneOffset 来获取 OffsetDateTime

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

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

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

Date d = new Date(timeInSeconds * 1000);
36
Codemwnci

这些可能是而不是 毫秒 Java新的Date(长)构造函数所需的时间戳。只需将它们乘以1000就可以了。

9
Magnus Winter

仅在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());
9
Marlon

长值很可能对应于 Epoch timestamps,值为:

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); 

现在,要正确显示日期,可以使用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));

下面是在不使用和使用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
5
Jack G.

试试这个:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
4
Mohammad Namvar

1220227200对应于1980年1月15日(实际上新的日期(1220227200).toString()返回“Thu Jan 15 03:57:07 CET 1970”)。如果您将长值传递给日期,即1970年1月1日之前,它实际上将返回日期01/01/1970。确保您的值不在这种情况下(低于82800000)。

2
Shivan Dragon

请尝试调整日期格式。

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

注意:检查24小时或12小时循环。

1
abhimanyu

新日期(数字)返回1970年1月1日之后number毫秒的日期。可能的日期格式没有显示小时,分钟和秒,您可以看到它在1970年1月1日之后的一点点。

您需要根据正确的解析路由解析日期。我不知道1220227200是什么,但是如果它是在1970年1月1日之后的几秒钟,那么将它乘以毫秒。如果不是,则在1970年之后以某种方式将其转换为毫秒(如果您想继续使用Java.util.Date)。

0
Edwin Buck

适合我。你可能想把它乘以1000,因为你得到的是1970年的秒数,你必须从1970年1月1日开始经过毫秒

0
leifg