Java:从Unix时间戳获取日期

268

我需要将Unix时间戳转换成日期对象。
我尝试过以下方法:

java.util.Date time = new java.util.Date(timeStamp);

时间戳值为:1280512800

PHP返回的日期应为“2010/07/30 - 22:30:00”,但实际上我得到的是Thu Jan 15 23:11:56 IRST 1970

应该如何处理?


3
如果您使用Java 8或更新版本:请查看此答案:https://dev59.com/_3A75IYBdhLWcg3wS3BA#24703644 - micha
2
FYI,诸如java.util.Date之类的老旧日期时间类现在已经成为遗留系统,被Java.time类所取代。请参阅Oracle教程 - Basil Bourque
11个回答

474

对于1280512800,要乘以1000,因为Java期望的是毫秒:

java.util.Date time=new java.util.Date((long)timeStamp*1000);
如果你已经有毫秒数,只需要使用new java.util.Date((long)timeStamp)
根据文档
分配一个Date对象并将其初始化为表示自“纪元”以来的指定毫秒数,即1970年1月1日00:00:00 GMT作为标准基准时间。

47
进行(long)类型转换非常重要:如果没有它,整数会溢出。 - mneri
2
@TomasK java.util.Date 是该类的完全限定名称。如果您在类上导入了 java.util 包,那么 Date 可能是完全相同的东西 - Pablo Santa Cruz
5
不需要将变量转换成long型。使用time=new java.util.Date(timeStamp*1000L)同样有效(因为1000L是一个long型数值,在乘法运算前,timestamp会自动提升为long型数值)。 - Tony BenBrahim
2
我个人会这么做:Date time = new Date(TimeUnit.MILLISECONDS.convert(unixTimestamp, TimeUnit.SECONDS)); - Ryan Amaral
4
FYI,诸如java.util.Date之类的麻烦的旧日期时间类现在已经被视为遗留系统,已被新的 java.time类所取代。请参阅Oracle的教程 - Basil Bourque
显示剩余2条评论

81

java.time

Java 8引入了一个用于处理日期和时间的新API: java.time包

使用java.time包,您可以解析自1970年第一个时刻(UTC时间1970-01-01T00:00Z)以来的整秒数,结果是一个Instant对象。

Instant instant = Instant.ofEpochSecond( timeStamp );
如果您需要与尚未更新为java.time的旧代码进行交互,且需要使用 java.util.Date,请进行转换。调用已添加到旧类中的新转换方法。
Date date = Date.from( instant );

4
虽然这个答案在技术上是正确的,但请注意,java.time类替代了令人烦恼的旧日期时间类,如java.util.Date。旧的类是遗留问题,应该避免使用。虽然你确实可以转换成旧的和java.time类,但最好尽可能地使用java.time类。 - Basil Bourque

45

这是正确的方式:

Date date = new Date ();
date.setTime((long)unix_time*1000);

37

太长不看

Instant.ofEpochSecond( 1_280_512_800L )

2010年7月30日18:00:00Z

java.time

Java 8及更高版本内置的全新java.time框架是Joda-Time的后继者。

这些新类包括一个便捷的工厂方法,用于将自纪元以来的整秒数转换为时间。您将获得一个Instant,即UTC时间线上的瞬间,分辨率高达纳秒。

Instant instant = Instant.ofEpochSecond( 1_280_512_800L );

instant.toString():2010-07-30T18:00:00Z
请查看在IdeOne.com上实时运行的代码

Table of date-time types in Java, both modern and legacy

Asia/Kabul或者Asia/Tehran时区?

你报告的时间是22:30,而不是这里看到的18:00. 我猜测你的PHP工具隐式地应用了一个默认时区来从UTC调整时间。我这里的值是UTC,由Z(代表Zulu, 表示UTC)表示。你的机器操作系统或PHP是否设置为Asia/KabulAsia/Tehran时区呢?因为你的输出中报告了IRST,显然表示伊朗时间。目前在2017年,这些是唯一的时区使用夏令时比UTC提前四个半小时。

请将以下内容翻译为中文,保留HTML标签:

在格式为大陆/地区的时区名称中指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。永远不要使用3-4个字母的缩写,如ESTISTIRST,因为它们不是真正的时区,也没有标准化,甚至不是唯一的(!)。

如果你想要通过某个特定地区的时区来查看你的时刻,请应用ZoneId以获得ZonedDateTime。仍然是相同的同时刻,但被视为不同的wall-clock time

ZoneId z = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = instant.atZone( z );  // Same moment, same point on timeline, but seen as different wall-clock time.

2010-07-30T22:30+04:30[亚洲/德黑兰]

从java.time转换到旧版类

您应该坚持使用新的java.time类。但如果需要,可以进行转换为旧版类。

java.util.Date date = java.util.Date.from( instant );

Joda-Time

更新:Joda-Time 项目现已进入 维护模式,团队建议迁移到 java.time 类。

顺便提一下,Joda-TimeDateTime 构造函数类似:将结果乘以一千以产生一个 long(而不是一个 int!)。

DateTime dateTime = new DateTime( ( 1_280_512_800L * 1000_L ), DateTimeZone.forID( "Europe/Paris" ) );

最好避免使用声名狼藉的 java.util.Date 和 .Calendar 类。但如果必须使用 Date,可以从 Joda-Time 进行转换。
java.util.Date date = dateTime.toDate();

关于 java.time

java.time 框架内置于 Java 8 及以上版本。这些类取代了老旧的 legacy 日期时间类,如 java.util.DateCalendarSimpleDateFormat,使日期时间处理更加便捷。

Joda-Time项目现在处于维护模式,建议迁移到java.time类。

想要了解更多,请参阅Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范为JSR 310

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*类。

在哪里获取java.time类?

这个ThreeTen-Extra项目为java.time添加了额外的类。此项目是java.time可能未来添加的东西的试验场。您可以在此处找到一些有用的类,例如Interval, YearWeek, YearQuartermore

26

看起来Calendar是新的解决方案:

Calendar mydate = Calendar.getInstance();
mydate.setTimeInMillis(timestamp*1000);
out.println(mydate.get(Calendar.DAY_OF_MONTH)+"."+mydate.get(Calendar.MONTH)+"."+mydate.get(Calendar.YEAR));

最后一行只是一个示例,展示如何使用它,例如这个将输出“14.06.2012”。

如果您已经使用System.currentTimeMillis()保存了时间戳,则不需要 "*1000" 部分。

如果您的时间戳是一个字符串,您需要先将其解析为一个long类型:Long.parseLong(timestamp)。

https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html


8
警告:如果timestamp是一个整数,你需要先将其强制转换为(long),否则你将得到错误的日期。mydate.setTimeInMillis((long) timestamp*1000); - svenkapudija
请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的老旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque

15

Date构造函数需要时间戳值以毫秒为单位。将您的时间戳的值乘以1000,然后传递给构造函数。


7
如果您正在转换来自不同机器的时间戳值,则还应检查该机器的时区。例如;
如果您在EST或UTC时区运行,则上述说明将导致不同的日期值。
要设置时区;即为UTC, 您只需简单地重写;
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    java.util.Date time= new java.util.Date((Long.parseLong(timestamp)*1000));

7
我不建议这样做,因为这会设置整个 JVM 的时区而不仅仅是解析过程的时区! - user1563700

3

对于Kotlin

fun unixToDate(timeStamp: Long) : String? {
    val time = java.util.Date(timeStamp as Long * 1000)
    val sdf = SimpleDateFormat("yyyy-MM-dd")
    return sdf.format(time)

}

0

LocalDateTime是另一个选择,例如:

LocalDateTime.ofInstant(Instant.ofEpochSecond(unixtime), ZoneId.systemDefault())

0
有时你需要使用调整功能。
不要使用强制转换为长整型!使用nanoadjustment。
例如,使用Oanda Java API进行交易,您可以将日期时间获取为UNIX格式。
例如:1592523410.590566943。
    System.out.println("instant with nano = " + Instant.ofEpochSecond(1592523410, 590566943));
    System.out.println("instant = " + Instant.ofEpochSecond(1592523410));

你得到:

instant with nano = 2020-06-18T23:36:50.590566943Z
instant = 2020-06-18T23:36:50Z

此外,使用:

 Date date = Date.from( Instant.ofEpochSecond(1592523410, 590566943) );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接