Java将长期转换为date?
我有很长的价值列表(例如:1220227200,1220832000,1221436800 …),我从networking服务下载。 我必须将其转换为date。 不幸的是,这样,例如:
Date d = new Date(1220227200);
返回1970年1月1日。任何人都知道另一种方法正确地转换它?
Date
构造函数 (单击链接!)接受的时间只有毫秒 ,而不是秒。 你需要乘以1000,并确保你提供它long
。
Date d = new Date(1220227200L * 1000);
这显示在这里
星期日8月31日20:00:00 GMT-04:00 2008
看起来你的多头是秒,而不是毫秒。 date构造函数需要时间毫秒,所以
Date d = new Date(timeInSeconds * 1000);
TL;博士
Instant.ofEpochSecond( 1_220_227_200L )
了解你的数据
自从一个时代以来,人们在追踪时间中使用各种精度。 所以当你从一个时代开始就把一些数字解释为一个数字时,你必须确定:
- 什么时代?
许多时代已被用于各种系统。 常用的是POSIX / Unix时间 ,其中时代是UTC的1970年的第一时刻。 但是你不应该假设这个时代。 - 什么精度?
我们是从时代开始说话秒, 毫秒 , 微秒还是纳秒 ? - 什么时区?
通常情况下,自纪元以来的计数在UTC / GMT时区,即根本没有时区偏移量。 但有时候,当涉及没有经验或date的无知的程序员时,可能会有一个隐含的时区。
在你的情况下,正如其他人所指出的那样,自从Unix时代以来,你似乎已经有了几秒钟的时间。 但是你将这些秒传递给一个期望毫秒的构造函数。 所以解决scheme是乘以1,000。
得到教训:
- 确定,不要假设,收到的数据的含义。
- 阅读文档 。
您的数据
你的数据似乎在整个秒钟。 如果我们假设一个1970年初的时代,如果我们假设UTC时区,那么1,220,227,200
是2008年9月第一天的第一个时刻。
乔达时间
与Java捆绑在一起的java.util.Date和.Calendar类是非常麻烦的。 避免他们。 使用Joda-Time库或Java 8中捆绑的新java.time包 (并受Joda-Time的启发)。
请注意,与juDate不同的是,Joda-Time中的DateTime
确实知道自己指定的时区 。 因此,在下面看到的Joda-Time 2.4代码示例中,请注意,我们首先使用UTC的默认假设来parsing毫秒。 然后,其次,我们分配一个巴黎的时区进行调整。 在宇宙时间线上的同一时刻,但不同的钟表时间 。 为了演示,我们再次调整到UTC。 几乎总是更好地明确指定所需的/预期的时区,而不是依赖隐含的默认值(通常是date时间工作中的麻烦原因)。
我们需要毫秒来构造一个DateTime。 所以把你的input秒,乘以一千。 请注意,结果必须是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时代。因此,在构build之后根据需要调整时区。
使用适当的时区名称,大陆和城市/地区的组合。 切勿使用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" ) );
转储到控制台。 请注意,蒙特利尔的date不同,因为新的一天已经开始在欧洲,但还没有在美国。
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中。
Instant
是UTC时间线上的一个时刻,分辨率为纳秒。 它的时代是UTC的1970年的第一个时刻。
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新Date(long)构造函数所需的时间戳。 只要乘以1000,你应该没问题。
只在日历对象上的工厂中设置时间
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());
尝试这个:
Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(1220227200 * 1000); System.out.println(cal.getTime());
很长的值很可能与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);
现在,要正确显示date,可以使用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
新的date(数字)返回的date是1970年1月1日之后的number
毫秒。几率是你的date格式不显示小时,分钟和秒钟,你会发现它只是1970年1月1日之后的一点点。
您需要根据正确的parsing路由来parsingdate。 我不知道1220227200是什么,但是如果是在1970年1月1日之后的几秒钟,那么将其乘以产生毫秒。 如果不是这样,那么在1970年之后以某种方式将其转换为毫秒(如果您想继续使用java.util.Date)。
为我工作。 你可能想把它乘以1000,因为你得到的是从1970年的秒,你必须从1970年1月1日过去毫秒
1220227200对应于1980年1月15日(实际上新date(1220227200).toString()返回“Thu Jan 15 03:57:07 CET 1970”)。 如果您将一个长期的价值传递给一个date,即在01/01/1970之前,它实际上将返回一个01/01/1970的date。 确保你的值不在这种情况下(低于82800000)。