Skip to content

Commit 61c74ba

Browse files
committed
Add support for parsing time zones in DateFormatters and enhance Iso8601Parser
We can now parse ISO date-time such as : 2029-05-15T17:14:56.123456789-08:00[America/Los_Angeles] or 2031-12-03T10:15:30.123456789+01:00:00[Europe/Paris]
1 parent bf2a283 commit 61c74ba

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

docs/changelog/130054.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 130054
2+
summary: Add support for parsing ISO date time with zone-id (RFC 9557)
3+
area: Mapping
4+
type: enhancement
5+
issues: []

server/src/main/java/org/elasticsearch/common/time/Iso8601Parser.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,10 @@ private ZoneId parseZoneId(CharSequence str, int pos) {
477477
if (minutes == null || minutes > 59) return null;
478478
if (len == pos) return ofHoursMinutesSeconds(hours, minutes, 0, positive);
479479

480+
if (str.charAt(pos) == '[' && str.charAt(len - 1) == ']') {
481+
return parseRawZoneId(str, pos);
482+
}
483+
480484
// either both dividers have a colon, or neither do
481485
if ((str.charAt(pos) == ':') != hasColon) return null;
482486
if (hasColon) {
@@ -487,10 +491,29 @@ private ZoneId parseZoneId(CharSequence str, int pos) {
487491
if (seconds == null || seconds > 59) return null;
488492
if (len == pos) return ofHoursMinutesSeconds(hours, minutes, seconds, positive);
489493

494+
if (str.charAt(pos) == '[' && str.charAt(len - 1) == ']') {
495+
return parseRawZoneId(str, pos);
496+
}
497+
490498
// there's some text left over...
491499
return null;
492500
}
493501

502+
/**
503+
* Parses a raw zone id, which is a string of the form [zoneId] (eg [Europe/Paris]).
504+
*
505+
* @param str The string to parse
506+
* @param pos The position in the string where the zone id starts (the first character after the opening [)
507+
* @return The parsed zone id, or {@code null} if the string is not a valid zone id.
508+
*/
509+
private ZoneId parseRawZoneId(CharSequence str, int pos) {
510+
try {
511+
return ZoneId.of(str.subSequence(pos + 1, str.length() - 1).toString());
512+
} catch (DateTimeException e) {
513+
return null;
514+
}
515+
}
516+
494517
/*
495518
* ZoneOffset.ofTotalSeconds has a ConcurrentHashMap cache of offsets. This is fine,
496519
* but it does mean there's an expensive map lookup every time we call ofTotalSeconds.

server/src/test/java/org/elasticsearch/common/time/DateFormattersTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,13 @@ public void testIso8601Parsing() {
608608
formatter.format(formatter.parse("2018-05-15T17:14:56,123456789+01:00"));
609609
}
610610

611+
public void testParsingDateTimeWithZoneId() {
612+
DateFormatter formatter = DateFormatters.forPattern("strict_date_optional_time");
613+
formatter.format(formatter.parse("2018-05-15T17:14:56-08:00[America/Los_Angeles]"));
614+
formatter.format(formatter.parse("2029-05-15T17:14:56.123456789-08:00[America/Los_Angeles]"));
615+
formatter.format(formatter.parse("2031-12-03T10:15:30.123456789+01:00:00[Europe/Paris]"));
616+
}
617+
611618
public void testRoundupFormatterWithEpochDates() {
612619
assertRoundupFormatter("epoch_millis", "1234567890", 1234567890L);
613620
// also check nanos of the epoch_millis formatter if it is rounded up to the nano second

0 commit comments

Comments
 (0)