diff --git common/src/java/org/apache/hadoop/hive/common/type/TimestampTZUtil.java common/src/java/org/apache/hadoop/hive/common/type/TimestampTZUtil.java index 213650c2a5..c125247cf2 100644 --- common/src/java/org/apache/hadoop/hive/common/type/TimestampTZUtil.java +++ common/src/java/org/apache/hadoop/hive/common/type/TimestampTZUtil.java @@ -60,6 +60,21 @@ FORMATTER = builder.toFormatter(); } + static final DateTimeFormatter ISOFORMATTER; + static { + DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); + // date/time + builder.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + // offset (hh:mm - "+00:00" when it's zero) + .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() + // offset (hhmm - "+0000" when it's zero) + .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() + // offset (hh - "Z" when it's zero) + .optionalStart().appendOffset("+HH", "Z").optionalEnd(); + // create formatter + ISOFORMATTER = builder.toFormatter(); + } + public static TimestampTZ parse(String s) { return parse(s, null); } @@ -73,25 +88,31 @@ public static TimestampTZ parse(String s, ZoneId defaultTimeZone) { } catch (DateTimeParseException e) { // try to be more tolerant // if the input is invalid instead of incomplete, we'll hit exception here again - TemporalAccessor accessor = FORMATTER.parse(s); - // LocalDate must be present - LocalDate localDate = LocalDate.from(accessor); - LocalTime localTime; - ZoneId zoneId; - try { - localTime = LocalTime.from(accessor); - } catch (DateTimeException e1) { - localTime = DEFAULT_LOCAL_TIME; - } + + // try again with ISO if not working try { - zoneId = ZoneId.from(accessor); - } catch (DateTimeException e2) { - if (defaultTimeZone == null) { - throw new DateTimeException("Time Zone not available"); + TemporalAccessor accessor = FORMATTER.parse(s); + // LocalDate must be present + LocalDate localDate = LocalDate.from(accessor); + LocalTime localTime; + ZoneId zoneId; + try { + localTime = LocalTime.from(accessor); + } catch (DateTimeException e1) { + localTime = DEFAULT_LOCAL_TIME; + } + try { + zoneId = ZoneId.from(accessor); + } catch (DateTimeException e2) { + if (defaultTimeZone == null) { + throw new DateTimeException("Time Zone not available"); + } + zoneId = defaultTimeZone; } - zoneId = defaultTimeZone; + zonedDateTime = ZonedDateTime.of(localDate, localTime, zoneId); + } catch (DateTimeParseException ex) { + zonedDateTime = ZonedDateTime.parse(s,ISOFORMATTER); } - zonedDateTime = ZonedDateTime.of(localDate, localTime, zoneId); } if (defaultTimeZone == null) { diff --git common/src/test/org/apache/hadoop/hive/common/type/TestTimestampTZ.java common/src/test/org/apache/hadoop/hive/common/type/TestTimestampTZ.java index cd23abebfa..891eb140aa 100644 --- common/src/test/org/apache/hadoop/hive/common/type/TestTimestampTZ.java +++ common/src/test/org/apache/hadoop/hive/common/type/TestTimestampTZ.java @@ -102,6 +102,14 @@ public void testInvalidStrings() { } } + @Test + public void testISO() { + TimestampTZUtil.parse("2013-08-31T01:02:33Z"); + TimestampTZUtil.parse("2013-08-31T01:02:33+00"); + TimestampTZUtil.parse("2013-08-31T01:02:33+0000"); + TimestampTZUtil.parse("2013-08-31T01:02:33+00:00"); + } + @Test public void testConvertFromTimestamp() { TimeZone defaultZone = TimeZone.getDefault();