我有从Web服务下载的带有长值的列表(例如:1220227200、1220832000、1221436800 ...)。我必须将其转换为日期。不幸的是,这种方式例如:
Date d = new Date(1220227200);
返回1970年1月1日。有人知道另一种正确转换它的方法吗?
java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
现在的遗产,由取代java.time内置到Java 8和更高等级。
我有从Web服务下载的带有长值的列表(例如:1220227200、1220832000、1221436800 ...)。我必须将其转换为日期。不幸的是,这种方式例如:
Date d = new Date(1220227200);
返回1970年1月1日。有人知道另一种正确转换它的方法吗?
java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
现在的遗产,由取代java.time内置到Java 8和更高等级。
Answers:
该Date
构造函数(点击链接!)接受的时间long
在毫秒,不秒。您需要将其乘以1000,并确保将其提供为long
。
Date d = new Date(1220227200L * 1000);
这显示在这里
周日2008年8月31日20:00:00 GMT-04:00
Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));
更干净,更神奇的数字解决方案。
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.
自从一个时代开始,人们就以各种精度来跟踪时间。因此,当您获得一些自某个时期以来被解释为计数的数字时,您必须确定:
正如您所看到的,正如其他人指出的那样,自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不同,DateTime
Joda-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
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 Instant
是UTC时间线上的时刻,分辨率为纳秒。它的时代是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 );
看来您的长数是秒,而不是毫秒。日期构造器将时间作为毫秒,因此
Date d = new Date(timeInSeconds * 1000);
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