问题描述
我从网络服务接收 DateTime
作为 String
。此 DateTime
字符串的示例是:"DateTime":"2021-06-06T04:54:41-04:00"
。
这个 2021-06-06T04:54:41-04:00
或多或少符合 ISO-8601 格式,所以我使用这个模式来解析它:yyyy-MM-dd'T'HH:mm:ssZ
。但是,响应 DateTime 的时区部分中的冒号导致了问题。 2021-06-06T04:54:41-04:00
给出解析异常,但 2021-06-06T04:54:41-0400
解析正常。
下面的代码应该能更好地解释它:
public void stringToDate() {
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ"; //ISO - 8601 Format
TimeZone timeZoneEST = TimeZone.getTimeZone("US/Eastern");
SimpleDateFormat sdf = new SimpleDateFormat(pattern,new Locale("en","US"));
sdf.setLenient(false);
sdf.setTimeZone(timeZoneEST);
String timeFromWebService = "2021-06-06T04:54:41-04:00";
try {
Date parsedDate = sdf.parse(timeFromWebService); // not working because of colon in timezone part
System.out.println(parsedDate);
} catch (ParseException e) {
e.printstacktrace();
}
try {
Thread.sleep(1000); //sleep to avoid interleaving output from stacktrace (above) and syso (below)
} catch (InterruptedException e1) {
// Todo Auto-generated catch block
e1.printstacktrace();
}
String timeFromWebServiceModified = "2021-06-06T04:54:41-0400"; //removed colon from timezone part
try {
Date parsedDate = sdf.parse(timeFromWebServiceModified); // working because colon is removed in timezone part
System.out.println(parsedDate);
} catch (ParseException e) {
e.printstacktrace();
}
}
我想在不修改响应 DateTime
的情况下处理这个解析。关于如何解析原始 DateTime
的任何建议。任何关于使用什么模式的建议都会非常有帮助。
解决方法
java.util
日期时间 API 及其格式化 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*。
使用现代 API java.time
的解决方案:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d'T'H:m:s[XXX][XX][X]",Locale.ENGLISH);
//Test
Stream.of(
"2021-06-06T04:54:41-04:00","2021-06-06T04:54:41-0400","2021-06-06T04:54:41-04","2021-06-06T04:54:41Z"
).forEach(s -> System.out.println(OffsetDateTime.parse(s,dtf)));
}
}
输出:
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41Z
检查How to use OffsetDateTime
in JDBC?。
从 modern Date-Time API 中详细了解 java.time
,Trail: Date Time*。
使用旧 API 的解决方案:
SimpleDateFormat
没有指定可选模式的功能,我们这样做的方式是使用方括号和 DateTimeFormatter
。在这种情况下,您可以创建多个 SimpleDateFormat
实例并尝试使用每个实例。
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) {
SimpleDateFormat sfdArr[] = {
new SimpleDateFormat("y-M-d'T'H:m:sXXX",Locale.ENGLISH),new SimpleDateFormat("y-M-d'T'H:m:sXX",new SimpleDateFormat("y-M-d'T'H:m:sX",Locale.ENGLISH)
};
String []strDateTimeArr = {
"2021-06-06T04:54:41-04:00","2021-06-06T04:54:41Z"
};
for(String s : strDateTimeArr) {
Date date = null;
for(SimpleDateFormat sdf : sfdArr) {
try {
date = sdf.parse(s);
}catch(ParseException e) {
//...
}
}
System.out.println(date);
}
}
}
* 出于任何原因,如果您必须坚持使用 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。