我有以下日期: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
标记。
答案 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)
输入字符串使用标准ISO 8601格式。
Instant.parse ( "2011-08-12T20:17:46.384Z" )
此格式由合理的实用标准ISO 8601定义。
T
将日期部分与时间部分分开。最后的Z
表示UTC(即,从零小时 - 分钟 - 秒的UTC偏移)。 Z
为pronounced “Zulu”。
与最早版本的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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 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)
let isoDateTimeString = new Date().toISOString();
说明
日期/时间格式如“YYYY-MM-DDThh:mm:ss.SSSZ”是ISO 8601日期/时间格式。
答案 8 :(得分:0)
您不需要 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.time
,Trail: Date Time*。
旧的日期时间 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
下面引用的是 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 desugaring 和 How 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类已经预见到这一点。