我有以下日期: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标记。


当前回答

T只是一个将日期与时间分开的文字,Z表示“零时偏移”,也称为“祖鲁时间”(UTC)。如果你的字符串总是有一个“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()。

其他回答

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

除了第一个答案,还有其他方法来分析它。解析方法: (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);

or

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

该技术将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")

or

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

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

博士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….

@John-Skeet给了我解决这个问题的线索。作为一个年轻的程序员,这个小问题很容易被忽略,也很难被诊断出来。所以我分享它,希望它能帮助别人。

我的问题是,我想从一个我没有影响力的JSON中解析以下包含时间戳的字符串,并将其放在更有用的变量中。但是我总是出错。

因此,给定以下条件(注意ofPattern()中的字符串参数;

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

这个问题?图案结尾的Z需要像“T”一样用“Z”来包装。改变 “名称不'HHmmss。SSSZ"到"yyyyMMdd'T'HHmmss。SSS' z '”,它起作用了。

从图案中完全去掉Z也会导致错误。

坦率地说,我希望Java类能够预料到这一点。