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


118

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

Date d = new Date(1220227200);

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


您能说出您期望什么价值吗?秒/毫秒的问题可能是有效的,但1220227200不是1/1/1970。看起来您正在将0传递给构造函数。其他一些代码可能会有所帮助。
2011年

1
@mmmiki-您应该接受答案
Stewart

它返回的是1970年1月15日,而不是1月1日。
njzk2 2014年

仅供参考,非常有缺陷的日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8和更高等级。
罗勒·布尔克

Answers:


161

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

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

这显示在这里

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


22
或者,使用Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));更干净,更神奇的数字解决方案。
Priidu Neemre

56

tl; dr

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年第一刻。但是您不应该承担这个时代。
  • 什么精度?从纪元开始
    我们是在说秒,毫秒微秒还是纳秒
  • 什么时区?
    通常,由于纪元是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中的a真正知道自己分配的时区。因此,在下面显示的示例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时代开始的。因此,在构造之后,可以根据需要调整时区。

使用正确的时区名称,并结合大陆和城市/地区。切勿使用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时间框架由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 );

应用从UTC偏移 ZoneOffset获得OffsetDateTime

更好的是,如果知道的话,可以应用时区ZoneId来获取ZonedDateTime

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

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


1
干杯哥们。很好的解释。我从1970年开始获取新的DateTime(<long number>),当时我意识到我以秒为单位并以毫秒为单位进行
赋值

40

看来您的长数是秒,而不是毫秒。日期构造器将时间作为毫秒,因此

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh:我没有投票,但最初的答案有所不同。他在5分钟的宽限期内对其进行了编辑。
BalusC

感谢您的澄清。这就是SO自身的缺点...:-/
f1sh 2011年

11

仅在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

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


23
更合适的是30000毫秒太慢
SJuan76'9

5

long值很可能对应于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使用millisecs的事实,将这些长值转换为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

4

试试这个:

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

2

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


2

尝试调整日期格式。

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

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


0

New Date(number)返回的日期是number1970年1月1日之后的毫秒数。奇怪的是,您的日期格式未显示小时,分钟和秒,因此您看到它只是在1970年1月1日之后。

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


0

为我工作。您可能想将其乘以1000,因为您得到的是1970年的秒数,并且您必须传递1970年1月1日的毫秒数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.