这个日期格式是什么?2011-08-12T20:17:46.384Z

Sar*_*els 319 java format time date simpledateformat

我有以下日期: 2011-08-12T20:17:46.384Z.这是什么格式的?我正在尝试使用Java 1.4解析它DateFormat.getDateInstance().parse(dateStr)并且我得到了

java.text.ParseException:Unparseable date:"2011-08-12T20:17:46.384Z"

我想我应该使用SimpleDateFormat进行解析,但我必须首先知道格式字符串.到目前为止yyyy-MM-dd,我所拥有的只是,因为我不知道T这个字符串中的含义是什么 - 与时区有关?此日期字符串来自文件CMIS下载历史记录媒体类型lcmis:downloadedOn上显示的标记.

Jon*_*eet 447

T只是将日期与时间分开的文字,Z表示"零小时偏移",也称为"祖鲁时间"(UTC).如果你的字符串总是有一个"Z",你可以使用:

SimpleDateFormat format = new SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Run Code Online (Sandbox Code Playgroud)

或者使用Joda Time,你可以使用ISODateTimeFormat.dateTime().

  • @JonSkeet:这可能引发不必要的辩论; 没有争议你的答案,但旨在引起注意***Z***,其字母从"零UTC偏移"开始.字母Z在**北约语音字母**中被称为"祖鲁语".反过来,用于引用零UTC偏移的军事方法锚定在字母Z上,它们标识为Zulu,为其赢得编码名称:Zulu时区.重要的是要注意Z并没有失去其意义,仍然是零UTC偏移的区域指示符,因为Zulu时区(来自Z)只是一个继承的编码语言来引用它. (8认同)
  • 为什么我们需要`T`和`Z`周围的单引号? (7认同)
  • @MarounMaroun:基本上我们想要那些*literal*字符.对于`T`可能没有必要(我不记得SimpleDateFormat如何处理未知的说明符)但是对于`Z`我们希望它是字符'Z'而不是"UTC偏移值"(例如"00") . (7认同)
  • @nyedidikeke:在你链接的维基百科页面中,它显示了UTC的"Zulu时区".我不确定你认为你在纠正什么. (2认同)
  • @nyedidikeke:关于我的回答,我仍然不同意是否有人会关心这个区别,但是我已经对其进行了更新。不过,由于历史与答案大致无关,因此我将不做所有详细说明。 (2认同)

Bas*_*que 60

TL;博士

输入字符串使用标准ISO 8601格式.

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 
Run Code Online (Sandbox Code Playgroud)

ISO 8601

这种格式由合理的实用标准ISO 8601定义.

T日期部分与时间部分分开.该Z对端装置UTC(即,偏移从-UTC零小时-分钟-秒).将Z明显的"祖鲁".

java.time

与最早版本的Java捆绑在一起的旧日期时间类已被证明设计糟糕,令人困惑且麻烦.避免他们.

相反,请使用Java 8及更高版本中内置的java.time框架.java.time类取代了旧的日期时间类和非常成功的Joda-Time库.

在解析/生成日期时间值的文本表示时,java.time类默认使用ISO 8601.

Instant级表示时间轴上的时刻UTC,分辨率为纳秒.该类可以直接解析输入字符串,而无需定义格式化模式.

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;
Run Code Online (Sandbox Code Playgroud)

关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

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

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

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.

  • @star"Zulu"来自军事和航空传统,其中25个字母AZ(无"J")字母,每个字母具有可发音的名称,代表[他们的时区版本](https://en.wikipedia.组织/维基/ List_of_military_time_zones)."Zulu"区域与UTC的零小时偏移.见[this](https://www.timeanddate.com/time/zones/z)和[this](https://en.wikipedia.org/w/index.php?title=Coordinated_Universal_Time&mobileaction=toggle_view_desktop#Time_zones) . (3认同)

smp*_*kes 26

不确定Java解析,但那是ISO8601:http://en.wikipedia.org/wiki/ISO_8601


Arv*_*ash 10

java.time

您不需要DateTimeFormatter解析给定的日期时间字符串。

Java SE 8 Date-Time API(java.timeAPI 或现代 Date-Time API)基于ISO 8601,不需要DateTimeFormatter显式使用对象,只要 Date-Time 字符串符合 ISO 8601 标准即可。

字符串Z中的 是零时区偏移的时区指示符。它代表祖鲁语并指定Etc/UTC时区(具有+00:00小时的时区偏移量)。

字符串T中的 仅仅是符合 ISO-8601 标准的日期时间分隔符。

演示:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-08-12T20:17:46.384Z";

        Instant instant = Instant.parse(strDateTime);
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime);
        
        System.out.println(instant);
        System.out.println(odt);
        System.out.println(zdt);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-08-12T20:17:46.384Z";

        Instant instant = Instant.parse(strDateTime);
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime);
        
        System.out.println(instant);
        System.out.println(odt);
        System.out.println(zdt);
    }
}
Run Code Online (Sandbox Code Playgroud)

Trail: Date Time中了解有关java.time现代日期时间 API *的更多信息。

旧版日期时间 API

旧版日期时间 API(java.util日期时间 API 及其格式化 API SimpleDateFormat)已过时且容易出错。建议完全停止使用它们并切换到现代 Date-Time API *

为了完整起见,我编写了一个使用旧版 API 解析此日期时间字符串的解决方案。

不要'Z'在模式中与日期时间解析/格式化 API 一起使用。

如上所述,Z(不带引号)是零时区偏移的时区指示符,而'Z'只是一个字符文字,它不具有任何含义。使用格式,y-M-d'T'H:m:s.SSSXXX. 查看文档以了解有关这些符号的更多信息。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        String strDateTime = "2011-08-12T20:17:46.384Z";

        SimpleDateFormat sdf = new SimpleDateFormat("y-M-d'T'H:m:s.SSSXXX", Locale.ENGLISH);
        Date date = sdf.parse(strDateTime);
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,对象不是像现代日期时间类型那样java.util.Date的真正的日期时间对象;相反,它表示自称为“纪元”的标准基准时间(或 UTC)以来的毫秒数。由于它不保存任何格式和时区信息,因此它应用该格式和 JVM 的时区来返回从此毫秒值派生的值。如果您需要以不同的格式和时区打印日期时间,则需要使用具有所需格式和适用时区的 a ,例如January 1, 1970, 00:00:00 GMTEEE MMM dd HH:mm:ss z yyyyDate#toStringSimpleDateFormat

sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String formatted = sdf.format(date);
System.out.println(formatted); // 2011-8-12T20:17:46.384Z
Run Code Online (Sandbox Code Playgroud)

Joda 日期时间 API

以下引用的是Joda-Time 主页上的通知:

请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了该项目。

同样,为了完整起见,我编写了一个使用 Joda 日期时间 API 解析此日期时间字符串的解决方案。

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String dateTimeStr = "2011-08-12T20:17:46.384Z";
        DateTimeFormatter dtf = DateTimeFormat.forPattern("y-M-d'T'H:m:s.SSSZ").withOffsetParsed();
        DateTime dateTime = dtf.parseDateTime(dateTimeStr);
        System.out.println(dateTime);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z
Run Code Online (Sandbox Code Playgroud)

* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大多数java.time功能向后移植到 Java 6 和 7。如果您正在处理 Android 项目和 Android API level 仍然不符合 Java-8,请检查通过脱糖可用的 Java 8+ API以及如何在 Android 项目中使用 ThreeTenABP


小智 7

还有其他解析方法,而不是第一个答案。要对其进行解析,请执行以下操作:

(1)如果要获取有关日期和时间的信息,可以将其解析为ZonedDatetime(自Java 8以来)或Date(旧)对象:

// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);
Run Code Online (Sandbox Code Playgroud)

要么

// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);

Date myDate = df.parse("2011-08-12T20:17:46.384Z");
Run Code Online (Sandbox Code Playgroud)

(2)如果您不在乎日期和时间,而只想将信息视为纳秒级的时间,则可以使用Instant

// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");
Run Code Online (Sandbox Code Playgroud)