如何在一个 DateTimeFormater 中处理所有区域偏移 Java 8
How to handle all Zone Offset in one DateTimeFormater Java 8
我需要为以下有效日期创建 DateTimeFormatter
。
String date1 = "2017-06-20T17:25:28";
String date2 = "2017-06-20T17:25:28.477777";
String date3 = "2017-06-20T17:25:28.477777Z";
String date4 = "2017-06-20T17:25:28.477777UTC";
String date5 = "2017-06-20T17:25:28.477777-05";
String date6 = "2017-06-20T17:25:28.477777+05";
String date7 = "2017-06-20T17:25:28.477777+05:30";
String date8 = "2017-06-20T17:25:28.477777-05:30";
String date9 = "2017-06-20T17:25:28.477777+0530";
String date10 = "2017-06-20T17:25:28.477777-0530";
我尝试了以下日期时间格式化程序,但最后两个日期都失败了(date9
、date10
)。
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
.optionalStart().appendZoneId().optionalEnd()
.optionalStart().appendOffset("+HH", "+00").optionalEnd()
.optionalStart().appendOffset("+HH:mm", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHmm", "+0000").optionalEnd().toFormatter();
从 date1
到 date8
的所有日期都工作正常,但我在尝试解析最后两个日期时得到 DateTimeParseException
:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2017-06-20T17:25:28.477777+0530' could not be parsed, unparsed text found at index 29
为了解析我正在使用的日期。
LocalDateTime.parse(date1, DATE_TIME_FORMATTER);
偏移的有效模式 OffsetIdPrinterParser
:
static final class OffsetIdPrinterParser implements DateTimePrinterParser {
static final String[] PATTERNS = new String[] {
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS",
}; // order used in pattern builder
我在使用有效的 ZoneOffset 模式时无法理解为什么最后两个日期失败。
只需反转可选部分的顺序即可:
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
.optionalStart().appendZoneId().optionalEnd()
.optionalStart().appendOffset("+HHmm", "+0000").optionalEnd()
.optionalStart().appendOffset("+HH:mm", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HH", "+00").optionalEnd()
.toFormatter();
这会解析您所有的 10 个示例日期时间字符串。
我不太清楚为什么会这样。我想它现在正在 +HH
之前尝试 +HHmm
,这确保它在有四个数字时得到所有四个数字,而不是让最后两个未解析。
另一种选择是使用由 []
分隔的可选部分,以及相应的 offset patterns(VV
和 x
):
DATE_TIME_FORMATTER = DateTimeFormatter
// pattern with optional sections: fraction of seconds and offsets
.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][VV][x][xx][xxx]");
每一对[]
相当于一个optionalStart
和optionalEnd
部分。请注意,我还必须包括大写字母 S
(秒的小数部分)作为可选,以解析该字段不存在的情况。
其他模式(VV
和 x
)对应于您需要的各种偏移量。来自 javadoc:
Pattern Count Equivalent builder methods
------- ----- --------------------------
VV 2 appendZoneId()
x 1 appendOffset("+HHmm","+00")
xx 2 appendOffset("+HHMM","+0000")
xxx 3 appendOffset("+HH:MM","+00:00")
这适用于您输入的所有日期。
唯一的区别是 [.SSSSSS]
在 fraction-of-seconds 字段中接受 exactly 6 位数字(或零数字,因为它是一个可选部分),而 appendFraction
接受 任何数量 从 0 到 6 位数字。要获得完全相同的行为,您必须使用 DateTimeFormatterBuilder
:
DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
// date and time
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
// fraction of seconds, from 0 to 6 digits
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
// optional offset patterns
.appendPattern("[VV][x][xx][xxx]")
.toFormatter();
我需要为以下有效日期创建 DateTimeFormatter
。
String date1 = "2017-06-20T17:25:28";
String date2 = "2017-06-20T17:25:28.477777";
String date3 = "2017-06-20T17:25:28.477777Z";
String date4 = "2017-06-20T17:25:28.477777UTC";
String date5 = "2017-06-20T17:25:28.477777-05";
String date6 = "2017-06-20T17:25:28.477777+05";
String date7 = "2017-06-20T17:25:28.477777+05:30";
String date8 = "2017-06-20T17:25:28.477777-05:30";
String date9 = "2017-06-20T17:25:28.477777+0530";
String date10 = "2017-06-20T17:25:28.477777-0530";
我尝试了以下日期时间格式化程序,但最后两个日期都失败了(date9
、date10
)。
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
.optionalStart().appendZoneId().optionalEnd()
.optionalStart().appendOffset("+HH", "+00").optionalEnd()
.optionalStart().appendOffset("+HH:mm", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHmm", "+0000").optionalEnd().toFormatter();
从 date1
到 date8
的所有日期都工作正常,但我在尝试解析最后两个日期时得到 DateTimeParseException
:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2017-06-20T17:25:28.477777+0530' could not be parsed, unparsed text found at index 29
为了解析我正在使用的日期。
LocalDateTime.parse(date1, DATE_TIME_FORMATTER);
偏移的有效模式 OffsetIdPrinterParser
:
static final class OffsetIdPrinterParser implements DateTimePrinterParser {
static final String[] PATTERNS = new String[] {
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS",
}; // order used in pattern builder
我在使用有效的 ZoneOffset 模式时无法理解为什么最后两个日期失败。
只需反转可选部分的顺序即可:
private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
.optionalStart().appendZoneId().optionalEnd()
.optionalStart().appendOffset("+HHmm", "+0000").optionalEnd()
.optionalStart().appendOffset("+HH:mm", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HH", "+00").optionalEnd()
.toFormatter();
这会解析您所有的 10 个示例日期时间字符串。
我不太清楚为什么会这样。我想它现在正在 +HH
之前尝试 +HHmm
,这确保它在有四个数字时得到所有四个数字,而不是让最后两个未解析。
另一种选择是使用由 []
分隔的可选部分,以及相应的 offset patterns(VV
和 x
):
DATE_TIME_FORMATTER = DateTimeFormatter
// pattern with optional sections: fraction of seconds and offsets
.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][VV][x][xx][xxx]");
每一对[]
相当于一个optionalStart
和optionalEnd
部分。请注意,我还必须包括大写字母 S
(秒的小数部分)作为可选,以解析该字段不存在的情况。
其他模式(VV
和 x
)对应于您需要的各种偏移量。来自 javadoc:
Pattern Count Equivalent builder methods
------- ----- --------------------------
VV 2 appendZoneId()
x 1 appendOffset("+HHmm","+00")
xx 2 appendOffset("+HHMM","+0000")
xxx 3 appendOffset("+HH:MM","+00:00")
这适用于您输入的所有日期。
唯一的区别是 [.SSSSSS]
在 fraction-of-seconds 字段中接受 exactly 6 位数字(或零数字,因为它是一个可选部分),而 appendFraction
接受 任何数量 从 0 到 6 位数字。要获得完全相同的行为,您必须使用 DateTimeFormatterBuilder
:
DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
// date and time
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
// fraction of seconds, from 0 to 6 digits
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
// optional offset patterns
.appendPattern("[VV][x][xx][xxx]")
.toFormatter();