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

时间:2011-09-20 15:08:34

标签: java date long-integer

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

Date d = new Date(1220227200);

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

11 个答案:

答案 0 :(得分:138)

Date constructor(点击链接!)在毫秒中接受long的时间,而不是秒。您需要将其乘以1000,并确保将其作为long提供。

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

这里显示

  

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

答案 1 :(得分:43)

TL;博士

Instant.ofEpochSecond( 1_220_227_200L )

了解您的数据

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

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

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

经验教训:

  • 确定,不要假设接收数据的含义。
  • 阅读the 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 package(受Joda-Time启发)。

请注意,与j.u.Date不同,Joda-Time中的DateTime确实知道自己分配的time zone。因此,在下面看到的示例Joda-Time 2.4代码中,请注意我们首先使用UTC的默认假设解析毫秒。然后,其次,我们指定一个巴黎时区进行调整。宇宙时间轴中的相同时刻,但wall-clock time不同。为了演示,我们再次调整为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纪元。因此,在构造之后根据需要调整时区。

使用proper time zone名称,即大陆和城市/地区的组合。切勿使用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-time框架由JSR 310定义,并内置于Java 8及更高版本中。 java.time类已经被反向移植到Java 6& ThreeTen-Backport项目中的7和ThreeTenABP项目中的Android。

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

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

应用offset-from-UTC ZoneOffset获取OffsetDateTime

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

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

答案 2 :(得分:37)

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

Date d = new Date(timeInSeconds * 1000);

答案 3 :(得分:9)

这些可能是中的时间戳,而不是毫秒中的时间戳,这是java new Date(long)构造函数所必需的。只需将它们乘以1000就可以了。

答案 4 :(得分:9)

仅在日历对象

中设置工厂的时间
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());

答案 5 :(得分: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); 

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

以下是将转换后的long值显示为java.util.Date的结果 使用和使用DateFormat:

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

答案 6 :(得分:4)

试试这个:

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

答案 7 :(得分:2)

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

答案 8 :(得分:1)

尝试调整日期格式。

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

注意:检查24小时或12小时周期。

答案 9 :(得分:0)

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

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

答案 10 :(得分:0)

适合我。你可能想要将它与1000相乘,因为你得到的是从1970年开始的秒数,你必须从1970年1月1日开始传递毫秒数