如何将 ISO8601 格式转换为毫秒?

Posted

技术标签:

【中文标题】如何将 ISO8601 格式转换为毫秒?【英文标题】:How to convert ISO8601 format into milliseconds? 【发布时间】:2014-12-18 15:15:30 【问题描述】:

考虑到 ISO8601 在 JSON 中的使用频率,我还没有找到一种真正简单的方法,这让我感到非常惊讶。

基本上,我会采用如下所示的字符串:2014-10-23T00:35:14.800Z 并将其转换为类似50 minutes ago 的字符串。

首先我要把2014-10-23T00:35:14.800Z改成2014-10-23'T'00:35:14.800Z,然后再转换成毫秒,就很简单了。

我当前的代码:

private void setTimestamp(String timeCreated) 
    int indexOfT = timeCreated.indexOf('T');

    String properFormat = new StringBuilder(timeCreated).insert(indexOfT + 1, "'")
                                                        .insert(indexOfT, "'")
                                                        .toString();

    timeStamp = (String) DateUtils.getRelativeTimeSpanString(Long.parseLong(properFormat),
                                  System.currentTimeMillis(), 
                                  DateUtils.SECONDS_IN_MILLIS);

罪魁祸首是Long.parseLong(properFormat)。我需要将properFormat 转换为毫秒。

【问题讨论】:

见Joda Time。 如果您使用 Java 8,您可能会发现 this discussion 很有趣。 请告诉我你为什么不赞成这个。 @David 我不是反对者。但我怀疑投票否决可能是由于 *** 上数百个问题和答案处理了这个主题。 @PM77-1 android 中没有 Java 8 和 java.time。 【参考方案1】:

tl;博士

Instant.parse( "2014-10-23T00:35:14.800Z" )
       .toEpochMilli()

java.time 中的单行器

java.time 框架内置于 Java 8 及更高版本中。这些新类取代了与 Java 的最早版本(如 java.util.Date/.Calendar)捆绑在一起的旧日期时间类。见Tutorial。 java.time 类也取代了非常成功的Joda-Time 库,由一些相同的人构建,包括由相同的Stephen Colbourne 领导。

Instant 是UTC 时间线上的一个时刻,分辨率为nanoseconds。您可以从其epoch 中ask it for a count of milliseconds(UTC 中的 1970 年第一刻)。但请记住,Instant 可能有额外的数据,纳秒比毫秒更精细。因此,您可能会在几分之一秒内丢失数据

java.time 类在解析/生成字符串时使用标准 ISO 8601 格式。无需指定格式模式。 Instant 类可以directly parse 一个字符串。

Instant.parse( "2014-10-23T00:35:14.800Z" )

您可以通过调用 toEpochMilli 将其转换为自 1970 年第一刻 UTC 纪元以来的毫秒数

请注意可能的数据丢失,因为Instant 类可以保存纳秒。因此,提取毫秒将在任何小数秒内截断任何微秒或纳秒。您的示例字符串在小数秒中只有三位数字,因此只有毫秒。但是当转换为毫秒数时,六位或九位小数会被截断为三位。

long millisFromEpoch = Instant.parse( "2014-10-23T00:35:14.800Z" ).toEpochMilli();

要以小时-分钟-秒为单位获取经过的时间,请使用 Duration 类。及时为其between 方法提供一对时刻。

Duration duration = Duration.between( Instant.parse( "2014-10-23T00:35:14.800Z" ) , Instant.now() );

关于java.time

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

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

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

从哪里获得 java.time 类?

Java SE 8Java SE 9Java SE 10 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 Android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…


Joda-Time 单线

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

使用Joda-Time 2.5 库:

long millisSinceEpoch = new DateTime( "2014-10-23T00:35:14.800Z" ).getMillis();

Joda-Time 默认解析并生成ISO 8601 字符串。 Joda-Time 适用于 Android。 java.util.Date/.Calendar 类是出了名的麻烦、混乱和缺陷。避开他们。

【讨论】:

我想我肯定会用这个。似乎是为我的约会量身定做的单线。 投反对票:请在投票的同时留下批评意见,尤其是在已接受的答案上。 Instant 仅在 API 26 后在 Android 上可用 @rightaway717 Java 8 中内置的 java.time 的大部分功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7项目,并在 ThreeTenABP 中进一步适应早期的 Android。【参考方案2】:

所以,答案比我想象的要简单。

private void setTimestamp(String timeCreated) 
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    try 
        Date timeCreatedDate = dateFormat.parse(timeCreated);
        timeStamp = (String) DateUtils.getRelativeTimeSpanString(timeCreatedDate.getTime(),
                                  System.currentTimeMillis(), 
                                  DateUtils.SECONDS_IN_MILLIS);
     catch ( ParseException e) 

这会起作用的。

【讨论】:

以上是关于如何将 ISO8601 格式转换为毫秒?的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 web api 的 json 序列化器将日期时间转换为 ISO 8601 格式?

如何在php中将ISO8601转换为日期格式

一种将当前日期时间转换为 ISO 8601 格式的优雅方法 [重复]

如何在 Pandas 数据框中将日期转换为 ISO-8601 DateTime 格式

在Java中将ISO 8601时间戳字符串转换为纪元秒[重复]

将 ISO8601 字符串转换为自纪元以来的毫秒数