如何从日历中获取 UTC 时间戳?
Posted
技术标签:
【中文标题】如何从日历中获取 UTC 时间戳?【英文标题】:How do I get a UTC Timestamp from Calendar? 【发布时间】:2011-05-21 14:35:31 【问题描述】:在 Java 中,当我使用 Calendar.getInstance();
时,我得到了当前时区的 Calendar
对象。但是java.sql.Timestamp
通常存储在UTC 时间而不是本地时间。那么如何从日历实例中获取 UTC 时间呢?
DateFormat df = DateFormat.getTimeInstance();
Calendar cal = Calendar.getInstance();
Timestamp time = new Timestamp(cal.getTimeInMillis());
// Prints local time
System.out.println(df.format(new Date(time.getTime())));
// Printe local time, but I want UTT Time
System.out.println("timestamp: " + time);
【问题讨论】:
【参考方案1】:当您调用 Calendar.getTime()
时,这将为您提供一个没有相关时区的值 - 或者您可以将其视为 UTC - 对于日历的 即时代表。因此,如果是(例如)日历所在时区的上午 9 点,则可能是世界标准时间下午 5 点。
现在java.util.Date
(我想Timestamp
)将在您调用toString()
(无论是隐式还是显式)时在系统默认时区格式化 - 但不要让你误以为时区是对象本身数据的一部分。
您需要非常清楚确切地要达到的目标 - 然后您可能会发现 Joda Time 可以让您在代码中比内置代码更清楚地表达这一点图书馆可以。
【讨论】:
我实际上从 API 获得了一个Calendar
实例,然后我必须从中获得 UTC 时间戳。我喜欢 Joda Time,但我不能在这里使用它。
@Jonas:好的,在这种情况下,您只需要使用getTime()
- 这将为您提供 UTC 时间戳。【参考方案2】:
您的代码已经完全按照您的意愿行事。 Timestamp
(以及 Date
)没有时区信息,并且应该始终包含 GMT 时间戳(这是 Calendar.getTimeInMillis()
返回的内容)。
您看到打印本地时间的原因是 DateFormat
工厂方法以及 Timestamp.toString()
隐式使用系统时区。
【讨论】:
好的,有什么办法可以让DateFormat
在格林威治时间显示?
@Jonas:DateFormat 有一个 setTimeZone() 方法【参考方案3】:
以下 sn-p 应该可以满足您的要求:
df.setTimeZone(TimeZone.getTimeZone("UTC"));
【讨论】:
我刚刚格式化了你的答案,并没有投反对票。【参考方案4】:tl;博士
Instant.now()
避免使用旧的日期时间类
您正在使用麻烦的旧日期时间类,现在已被 java.time 类取代。无需使用DateFormat
、Calendar
或Timestamp
。
如果您必须与尚未更新到 java.time 的旧代码中的 Calendar
进行交互,请使用添加到旧类的新方法进行转换。提取一个过时的java.util.Date
,并转换为Instant
。
Instant instant = myCal.getTime().toInstant() ;
使用 java.time
以Instant
的形式获取当前时刻。 Instant
类代表UTC 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
Instant instant = Instant.now() ;
2017-02-17T03:29:15.725Z
数据库
使用 JDBC 4.2 及更高版本,您可以直接与您的数据库交换 Instant
对象。所以不需要过时的java.sql.Timestamp
。
myPreparedStatement.setObject( … , instant ) ;
及检索:
Instant instant = myResultSet.getObject( … , Instant.class ) ;
从纪元开始计数
显然你想要从1970-01-01T00:00:00Z
的epoch reference date 开始的毫秒数。您可以从Instant
中提取该号码。但请注意数据丢失,因为Instant
的分辨率为纳秒,您将截断为毫秒。
long millis = instant.toEpochMilli() ;
1487302155725
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
Java SE 8 和 SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6 和 SE 7 大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android ThreeTenABP 项目专门针对 android 改编了 ThreeTen-Backport(如上所述)。 见How to use ThreeTenABP…。ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval
、YearWeek
、YearQuarter
和more。
【讨论】:
以上是关于如何从日历中获取 UTC 时间戳?的主要内容,如果未能解决你的问题,请参考以下文章
已更新如何在 JavaScript 中获取 UTC 时间戳?