我有以下日期: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下载历史媒体类型上显示的lccmis: downloaddon标记。


当前回答

java.time

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

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

字符串中的Z是零时区偏移的时区指示符。它代表Zulu,并指定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);
    }
}

输出:

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

了解更多关于java的知识。time,来自Trail: Date time的现代Date- time API*。

遗留的Date-time API

遗留的Date-time API (java。util Date-Time API和它们的格式化API SimpleDateFormat)已经过时并且容易出错。建议完全停止使用它们,并切换到现代的Date-Time API*。

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

不要在带有日期-时间解析/格式化API的模式中使用'Z'。

如上所述,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);
        // ...
    }
}

Note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any format and timezone information, it applies the format, EEE MMM dd HH:mm:ss z yyyy and the JVM's timezone to return the value of Date#toString derived from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the applicable timezone e.g.

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

Joda Date-Time API

以下为约达时代官网公告:

注意,从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。Java 6和7的时间功能。如果你正在为一个Android项目工作,你的Android API级别仍然不兼容Java-8,检查Java 8+ API通过desugaring和如何使用ThreeTenABP在Android项目。

其他回答

如果你正在寻找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

Z代表UTC时区。对于java8+,您可以简单地使用Instant。

    public static void main(String[] args) {
    String time = "2022-06-08T04:55:01.000Z";
    System.out.println(Instant.parse(time).toEpochMilli());
}

博士tl;

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

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

ISO 8601

这种格式是由实用标准ISO 8601定义的。

T分隔日期部分和时间部分。末尾的Z表示UTC(即0小时-分钟-秒的UTC偏移量)。Z发音为“Zulu”。

java.time

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

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

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

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

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


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

Joda-Time项目现在处于维护模式,建议迁移到java。时间类。

你可以交换java。Time对象直接使用数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java。sql。*类。Hibernate 5和JPA 2.2支持java.time。

从哪里获取java。时间类?

Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation. Java 9 brought some minor features and fixes. Java SE 6 and Java SE 7 Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport. Android Later versions of Android (26+) bundle implementations of the java.time classes. For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android. If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….

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

java.time

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

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

字符串中的Z是零时区偏移的时区指示符。它代表Zulu,并指定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);
    }
}

输出:

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

了解更多关于java的知识。time,来自Trail: Date time的现代Date- time API*。

遗留的Date-time API

遗留的Date-time API (java。util Date-Time API和它们的格式化API SimpleDateFormat)已经过时并且容易出错。建议完全停止使用它们,并切换到现代的Date-Time API*。

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

不要在带有日期-时间解析/格式化API的模式中使用'Z'。

如上所述,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);
        // ...
    }
}

Note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any format and timezone information, it applies the format, EEE MMM dd HH:mm:ss z yyyy and the JVM's timezone to return the value of Date#toString derived from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the applicable timezone e.g.

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

Joda Date-Time API

以下为约达时代官网公告:

注意,从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。Java 6和7的时间功能。如果你正在为一个Android项目工作,你的Android API级别仍然不兼容Java-8,检查Java 8+ API通过desugaring和如何使用ThreeTenABP在Android项目。