Skip to content

Commit cce1a88

Browse files
authored
Make ISO8601 date parser accept timezone when time does not have seconds (#41896)
Prior to this change the ISO8601 date parser would only parse an optional timezone if seconds were specified. This change moves the timezone to the same level of optional components as hour, so that timestamps without minutes or seconds may optionally contain a timezone. It also adds a unit test to cover all the supported formats.
1 parent cfc12b4 commit cce1a88

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public class DateFormatters {
178178
/**
179179
* Returns a ISO 8601 compatible date time formatter and parser.
180180
* This is not fully compatible to the existing spec, which would require far more edge cases, but merely compatible with the
181-
* existing joda time ISO data formater
181+
* existing joda time ISO date formatter
182182
*/
183183
private static final DateFormatter ISO_8601 = new JavaDateFormatter("iso8601", STRICT_DATE_OPTIONAL_TIME_PRINTER,
184184
new DateTimeFormatterBuilder()
@@ -201,15 +201,15 @@ public class DateFormatters {
201201
.appendFraction(NANO_OF_SECOND, 1, 9, false)
202202
.optionalEnd()
203203
.optionalEnd()
204+
.optionalEnd()
205+
.optionalEnd()
204206
.optionalStart()
205207
.appendZoneOrOffsetId()
206208
.optionalEnd()
207209
.optionalStart()
208210
.append(TIME_ZONE_FORMATTER_NO_COLON)
209211
.optionalEnd()
210212
.optionalEnd()
211-
.optionalEnd()
212-
.optionalEnd()
213213
.toFormatter(Locale.ROOT));
214214

215215
/////////////////////////////////////////

server/src/test/java/org/elasticsearch/common/joda/JavaJodaTimeDuellingTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,14 +733,21 @@ public void testIso8601Parsers() {
733733
JodaDateFormatter jodaFormatter = new JodaDateFormatter(format, isoFormatter, isoFormatter);
734734
DateFormatter javaFormatter = DateFormatter.forPattern(format);
735735

736+
assertSameDate("2018-10-10", format, jodaFormatter, javaFormatter);
736737
assertSameDate("2018-10-10T", format, jodaFormatter, javaFormatter);
737738
assertSameDate("2018-10-10T10", format, jodaFormatter, javaFormatter);
739+
assertSameDate("2018-10-10T10+0430", format, jodaFormatter, javaFormatter);
738740
assertSameDate("2018-10-10T10:11", format, jodaFormatter, javaFormatter);
741+
assertSameDate("2018-10-10T10:11-08:00", format, jodaFormatter, javaFormatter);
742+
assertSameDate("2018-10-10T10:11Z", format, jodaFormatter, javaFormatter);
739743
assertSameDate("2018-10-10T10:11:12", format, jodaFormatter, javaFormatter);
744+
assertSameDate("2018-10-10T10:11:12+0100", format, jodaFormatter, javaFormatter);
740745
assertSameDate("2018-10-10T10:11:12.123", format, jodaFormatter, javaFormatter);
741746
assertSameDate("2018-10-10T10:11:12.123Z", format, jodaFormatter, javaFormatter);
747+
assertSameDate("2018-10-10T10:11:12.123+0000", format, jodaFormatter, javaFormatter);
742748
assertSameDate("2018-10-10T10:11:12,123", format, jodaFormatter, javaFormatter);
743749
assertSameDate("2018-10-10T10:11:12,123Z", format, jodaFormatter, javaFormatter);
750+
assertSameDate("2018-10-10T10:11:12,123+05:30", format, jodaFormatter, javaFormatter);
744751
}
745752

746753
public void testParsingMissingTimezone() {

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,58 @@ public void testParsingStrictNanoDates() {
198198
formatter.format(formatter.parse("2018-05-15T17:14:56.123456789+01:00"));
199199
}
200200

201+
public void testIso8601Parsing() {
202+
DateFormatter formatter = DateFormatters.forPattern("iso8601");
203+
204+
// timezone not allowed with just date
205+
formatter.format(formatter.parse("2018-05-15"));
206+
207+
formatter.format(formatter.parse("2018-05-15T17"));
208+
formatter.format(formatter.parse("2018-05-15T17Z"));
209+
formatter.format(formatter.parse("2018-05-15T17+0100"));
210+
formatter.format(formatter.parse("2018-05-15T17+01:00"));
211+
212+
formatter.format(formatter.parse("2018-05-15T17:14"));
213+
formatter.format(formatter.parse("2018-05-15T17:14Z"));
214+
formatter.format(formatter.parse("2018-05-15T17:14-0100"));
215+
formatter.format(formatter.parse("2018-05-15T17:14-01:00"));
216+
217+
formatter.format(formatter.parse("2018-05-15T17:14:56"));
218+
formatter.format(formatter.parse("2018-05-15T17:14:56Z"));
219+
formatter.format(formatter.parse("2018-05-15T17:14:56+0100"));
220+
formatter.format(formatter.parse("2018-05-15T17:14:56+01:00"));
221+
222+
// milliseconds can be separated using comma or decimal point
223+
formatter.format(formatter.parse("2018-05-15T17:14:56.123"));
224+
formatter.format(formatter.parse("2018-05-15T17:14:56.123Z"));
225+
formatter.format(formatter.parse("2018-05-15T17:14:56.123-0100"));
226+
formatter.format(formatter.parse("2018-05-15T17:14:56.123-01:00"));
227+
formatter.format(formatter.parse("2018-05-15T17:14:56,123"));
228+
formatter.format(formatter.parse("2018-05-15T17:14:56,123Z"));
229+
formatter.format(formatter.parse("2018-05-15T17:14:56,123+0100"));
230+
formatter.format(formatter.parse("2018-05-15T17:14:56,123+01:00"));
231+
232+
// microseconds can be separated using comma or decimal point
233+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456"));
234+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456Z"));
235+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456+0100"));
236+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456+01:00"));
237+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456"));
238+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456Z"));
239+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456-0100"));
240+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456-01:00"));
241+
242+
// nanoseconds can be separated using comma or decimal point
243+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456789"));
244+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456789Z"));
245+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456789-0100"));
246+
formatter.format(formatter.parse("2018-05-15T17:14:56.123456789-01:00"));
247+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456789"));
248+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456789Z"));
249+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456789+0100"));
250+
formatter.format(formatter.parse("2018-05-15T17:14:56,123456789+01:00"));
251+
}
252+
201253
public void testRoundupFormatterWithEpochDates() {
202254
assertRoundupFormatter("epoch_millis", "1234567890", 1234567890L);
203255
// also check nanos of the epoch_millis formatter if it is rounded up to the nano second

0 commit comments

Comments
 (0)