这是什么日期格式?2011 - 08 - 12 - t20:17:46.384z

我有以下日期: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在这个字符串中的意思-一些时区相关的东西?这个日期字符串来自文件CMIS下载历史媒体类型上显示的lcmis:downloadedOn标记。

747960 次浏览

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

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的时间,你可以使用ISODateTimeFormat.dateTime()

博士tl;

输入字符串使用标准的< >强ISO 8601 < / >强格式。

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

ISO 8601

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

T将日期部分与时间部分分开。末尾的Z表示UTC(即从utc的0小时-分钟-秒偏移量)。Z读作“祖鲁语”

java.time

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

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

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

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

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

现代和传统Java中的日期-时间类型表


关于# EYZ0

< em > java.time < / em >框架内置于Java 8及更高版本中。这些类取代了麻烦的旧的遗产日期-时间类,如java.util.DateCalendar, &# EYZ7。

要了解更多信息,请参阅< < em >甲骨文教程/ em >。搜索Stack Overflow可以找到很多例子和解释。规格是JSR 310

< em > Joda-Time < / em >项目,现在在维护模式中,建议迁移到java.time类。

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

从哪里获取java。时间类?

表的java。“/></a> . time library with哪个版本的Java或Android</p></div>
                                                                            </div>
                                </div>
                            </div>
                        </div>
                                                <div class=

有其他方法来解析它,而不是第一个答案。解析:

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

您可以使用以下示例。

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

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

@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
< p >问题?图案结尾的Z需要像“T”一样用“Z”来包装。改变 "yyyyMMdd'T'HHmmss.SSSZ""yyyyMMdd'T'HHmmss.SSS'Z'",它工作。< / p >

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

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

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

在JavaScript中

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

描述

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

java.time

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

Java SE 8 Date-Time 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现代日期时间APITrail: Date Time

遗留的Date-time API

遗留的日期-时间API (java.util日期-时间API和它们的格式化API, SimpleDateFormat)已经过时并且容易出错。建议完全停止使用,改用现代日期时间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);
// ...
}
}

注意,java.util.Date对象不是一个真正的Date-Time对象,像现代日期-时间类型;相反,它表示从标准基准时间开始的毫秒数,称为“epoch”,即January 1, 1970, 00:00:00 GMT(或UTC)。因为它不保存任何格式和时区信息,所以它应用格式EEE MMM dd HH:mm:ss z yyyy和JVM的时区来返回由这个毫秒值派生的Date#toString值。如果需要以不同的格式和时区打印Date-Time,则需要使用带有所需格式和适用时区的SimpleDateFormat

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

下面引用的是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,你可以使用< em > < >强ThreeTen-Backport < /强> < / em >,它将java.time的大部分功能向后移植到Java 6 &7. 如果你正在开发一个Android项目,而你的Android API级别仍然不符合Java-8,请检查通过糖化可获得Java 8+ api如何在Android项目中使用ThreeTenABP。 < /一口> < / p >

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