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

时间:2011-12-06 18:45:57

标签: java date time format simpledateformat

我有以下日期:2011-08-12T20:17:46.384Z。这是什么格式的?我试图通过DateFormat.getDateInstance().parse(dateStr)用Java 1.4解析它,我正在

  

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

我认为我应该使用SimpleDateFormat进行解析,但我必须首先知道格式字符串。到目前为止我所拥有的只有yyyy-MM-dd,因为我不知道T在这个字符串中的含义 - 与时区有关吗?此日期字符串来自Files CMIS download history media type上显示的lcmis:downloadedOn标记。

10 个答案:

答案 0 :(得分:364)

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

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

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

答案 1 :(得分:38)

TL;博士

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

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 

ISO 8601

此格式由合理的实用标准ISO 8601定义。

T将日期部分与时间部分分开。最后的Z表示UTC(即,从零小时 - 分钟 - 秒的UTC偏移)。 Zpronounced “Zulu”

java.time

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

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

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

Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds。该类可以直接解析输入字符串,而无需定义格式化模式。

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;

关于 java.time

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

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

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

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

答案 2 :(得分:24)

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

答案 3 :(得分:4)

还有其他方法可以解析它而不是第一个答案。解析它:

(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);

// '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");

(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");

答案 4 :(得分:0)

您可以使用以下示例。

    String date = "2011-08-12T20:17:46.384Z";

    String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String outputPattern = "yyyy-MM-dd HH:mm:ss";

    LocalDateTime inputDate = null;
    String outputDate = null;


    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);

    inputDate = LocalDateTime.parse(date, inputFormatter);
    outputDate = outputFormatter.format(inputDate);

    System.out.println("inputDate: " + inputDate);
    System.out.println("outputDate: " + outputDate);

答案 5 :(得分:0)

该技术将java.util.Date转换为UTC格式(或任何其他格式),然后再次返回。

这样定义一个类:

import java.util.Date;

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

public class UtcUtility {

public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();


public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
    return dateTimeFormatter.parseDateTime(date).toDate();
}

public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
    return format(dateTimeFormatter, date.getTime());
}

private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
    DateTime dateTime = new DateTime(timeInMillis);
    String formattedString = dateTimeFormatter.print(dateTime);
    return formattedString;
}

}

然后像这样使用它:

Date date = format(UTC, "2020-04-19T00:30:07.000Z")

String date = parse(UTC, new Date())

如果需要,您还可以定义其他日期格式(不仅限于UTC)

答案 6 :(得分:0)

如果您正在寻找适用于Android的解决方案,则可以使用以下代码从时间戳字符串中获取新纪元。

public static long timestampToEpochSeconds(String srcTimestamp) {
    long epoch = 0;

    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Instant instant = Instant.parse(srcTimestamp);
            epoch = instant.getEpochSecond();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = sdf.parse(srcTimestamp);
            if (date != null) {
                epoch = date.getTime() / 1000;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return epoch;
}

样品输入:2019-10-15T05:51:31.537979Z

示例输出:1571128673

答案 7 :(得分:0)

在 JavaScript 中

let isoDateTimeString = new Date().toISOString();

说明

日期/时间格式如“YYYY-MM-DDThh:mm:ss.SSSZ”是ISO 8601日期/时间格式。

答案 8 :(得分:0)

java.time

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

Java SE 8 Date-Time API(java.time API 或现代 Date-Time API)基于 ISO 8601 并且不需要显式使用 DateTimeFormatter 对象,只要日期时间字符串符合 ISO 8601 标准。

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

根据 ISO-8601 标准,字符串中的 T 只是 Date-Time separator

演示:

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);
    }
}

输出:

2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z
2011-08-12T20:17:46.384Z

modern Date-Time API 中详细了解 java.timeTrail: Date Time*

旧的日期时间 API

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

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

请勿在具有日期时间解析/格式化 API 的模式中使用 'Z'

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

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);
        // ...
    }
}

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

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

Joda 日期时间 API

下面引用的是 Home Page of Joda-Time 上的通知:

<块引用>

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

同样,为了完整起见,我编写了一个解决方案来使用 Joda Date-Time API 解析这个 Date-Time 字符串。

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);
    }
}

输出:

2011-08-12T20:17:46.384Z

* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 9 :(得分:-1)

@ John-Skeet提供了解决此问题的线索。作为一个年轻的程序员,这个小问题很容易遗漏并且很难诊断。因此,我希望分享它,希望对您有所帮助。

我的问题是我想解析以下与JSON时间戳相对应的字符串,我对此没有影响,并将其放入更有用的变量中。但是我不断出错。

因此,请执行以下操作(注意Pattern()内的string参数;

String str = "20190927T182730.000Z"

LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );

错误:

Exception in thread "main" java.time.format.DateTimeParseException: Text 
'20190927T182730.000Z' could not be parsed at index 19

有问题吗?就像“ T”一样,模式末尾的Z需要用“ Z”包裹。更改 "yyyyMMdd'T'HHmmss.SSSZ""yyyyMMdd'T'HHmmss.SSS'Z'",它可以正常工作。

从模式中一起删除Z也会导致错误。

坦率地说,我希望Java类已经预见到这一点。