如何使date.getTime()返回UTC时间?

我有一个表示UTC时间的Date对象。 当我使用方法getTime()来获取此对象的long值时,返回的值对应于我们的本地时间(美国中部)。 获取与原始UTC时间相对应的值的正确方法是什么?

谢谢

DateFormat类有一个设置首选时区的方法 ,并且有一个时区类,它具有UTC时间的设置 。

所以,例如,

 SimpleDateFormat sdf = new SimpleDateFormat(); sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")); Date yourUtcDate = sdf.parse(yourOriginalDate); 

java.util.Date没有时区概念。 它只保留相对于纪元的时间,即1970年1月1日00:00:00 UTC。 日期是一个模型,与视图分开。 显示日期时,将应用时区的概念。 Date的toString()在默认时区中显示人类可读日期。 您可以使用DateFormat以不同的时区(例如UTC)显示日期,也可以更改JVM的默认时区。

TL;博士

 Instant.now() 

…和…

 Instant.ofEpochMilli( n ) 

…和…

 instant.toEpochMilli() 

Date始终为UTC

当我使用方法getTime()来获取此对象的long值时,返回的值对应于我们的本地时间(美国中部)。

不,从Date::getTime()返回的值始终对应于UTC (在此上下文中几乎与GMT相同)。 引用课程文档:

返回自此Date对象表示的1970年1月1日00:00:00 GMT以来的毫秒数。

因此,您的问题是荒谬的,因为Date已经是UTC。 无需“获取与原始UTC时间相对应的值”,

您可能会将getTime的行为与toString方法的行为混淆。 toString方法令人烦恼且容易混淆地在生成String的过程中应用当前的默认时区。 因此字符串输出显示时区,而实际上没有时区可以从Date本身设置或获取。 (实际上在Date有一个区域,但这与这里的讨论无关。这个类是一个混乱的混乱!)

java.time

现代的方法是使用java.time类。

Instant

Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。

获取当前时刻。

 Instant instant = Instant.now(); 

您可以通过调用添加到旧日期时间类的新转换方法之一将Date转换为其现代替换。 只需打电话给toInstant ,很容易。

 Instant instant = myJavaUtilDate.toInstant(); 

我完全不建议使用从纪元开始的数字作为跟踪时间的方法。 坚持使用java.time对象。 在Java之外,序列化为文本使用ISO 8601格式。

但如果必须,您可以提取自1970-01-01T00:00:00Z纪元以来的毫秒数。 请注意,这可能涉及数据丢失! Instant具有更精细的纳秒分辨率。 因此,毫秒可能会减少一小部分时间。

 long millisecondsSinceEpoch = instant.toEpochMilli(); // Caution: Possible data-loss in going from nanoseconds to milliseconds. 

走向另一个方向,从计数到Instant

 Instant instant = Instant.ofEpochMilli( millisecondsSinceEpoch ) ; 

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

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

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

从哪里获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
    • 请参阅如何使用….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

getTime()返回“自1970年1月1日,格林威治标准时间00:00:00以来的毫秒数”,仅此而已,没有更少(显然,您必须正确创建它)。 您可以根据需要对其进行格式化,例如GregorianCalendar(TimeZone)构造函数。

大多数Date类函数都已弃用,因为它们现在已在Calendar类中移位。

以下是从日历获取UTC时间的代码。

 Date date = new Date(timeStamp); Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(TimeZone.getTimeZone("UTC")); calendar.setTime(date); 

以下是获取年,月等的示例代码。

 System.out.println(calendar.get(Calendar.YEAR)); System.out.println(calendar.get(Calendar.MONTH)); 

日历还支持许多其他有用的信息,如TIME,DAY_OF_MONTH等。此处列出所有这些信息的文档请注意,月份为0。 1月是第0个月。

  LocalDateTime now = LocalDateTime.now(Clock.systemUTC()); Instant instant = now.atZone(ZoneId.systemDefault()).toInstant(); Date formattedDate = Date.from(instant); return formattedDate;