diff --git common/src/java/org/apache/hadoop/hive/common/type/TimestampUtils.java common/src/java/org/apache/hadoop/hive/common/type/TimestampUtils.java index ab60db1437..6fb79ad3ca 100644 --- common/src/java/org/apache/hadoop/hive/common/type/TimestampUtils.java +++ common/src/java/org/apache/hadoop/hive/common/type/TimestampUtils.java @@ -22,6 +22,7 @@ import java.math.BigDecimal; import java.time.DateTimeException; +import java.time.format.DateTimeParseException; /** * Utilities for Timestamps and the relevant conversions. @@ -168,4 +169,26 @@ public static long millisToSeconds(long millis) { } } + private final static int DATE_LENGTH = "YYYY-MM-DD".length(); + + public static Timestamp stringToTimestamp(String s) { + s = s.trim(); + // Handle simpler cases directly avoiding exceptions + if (s.length() == DATE_LENGTH) { + // Its a date! + return Timestamp.ofEpochMilli(Date.valueOf(s).toEpochMilli()); + } + try { + return Timestamp.valueOf(s); + } catch (IllegalArgumentException eT) { + // Try zoned timestamp + try { + return Timestamp.valueOf( + TimestampTZUtil.parse(s).getZonedDateTime().toLocalDateTime().toString()); + } catch (IllegalArgumentException | DateTimeParseException eTZ) { + // Last attempt + return Timestamp.ofEpochMilli(Date.valueOf(s).toEpochMilli()); + } + } + } } diff --git ql/src/test/queries/clientpositive/timestamptz_4.q ql/src/test/queries/clientpositive/timestamptz_4.q new file mode 100644 index 0000000000..b7edd2588e --- /dev/null +++ ql/src/test/queries/clientpositive/timestamptz_4.q @@ -0,0 +1,8 @@ +set hive.fetch.task.conversion=more; + +create table tstz3(t timestamp); + +insert into tstz3 VALUES ('2013-06-03 02:01:00.30547 GMT+01:00'), ('2013-06-03 02:01:00.30547 America/Los_Angeles'), ('2013-06-03 02:01:00.30547+01:00'), ('2013-06-03 02:01:00 GMT+01:00'), ('2013-06-03 02:01:00+07:00'), ('2013-06-03 02:01:00 America/Los_Angeles'); + +select * from tstz3; + diff --git ql/src/test/results/clientpositive/timestamptz_4.q.out ql/src/test/results/clientpositive/timestamptz_4.q.out new file mode 100644 index 0000000000..c47da00c40 --- /dev/null +++ ql/src/test/results/clientpositive/timestamptz_4.q.out @@ -0,0 +1,31 @@ +PREHOOK: query: create table tstz3(t timestamp) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@tstz3 +POSTHOOK: query: create table tstz3(t timestamp) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@tstz3 +PREHOOK: query: insert into tstz3 VALUES ('2013-06-03 02:01:00.30547 GMT+01:00'), ('2013-06-03 02:01:00.30547 America/Los_Angeles'), ('2013-06-03 02:01:00.30547+01:00'), ('2013-06-03 02:01:00 GMT+01:00'), ('2013-06-03 02:01:00+07:00'), ('2013-06-03 02:01:00 America/Los_Angeles') +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@tstz3 +POSTHOOK: query: insert into tstz3 VALUES ('2013-06-03 02:01:00.30547 GMT+01:00'), ('2013-06-03 02:01:00.30547 America/Los_Angeles'), ('2013-06-03 02:01:00.30547+01:00'), ('2013-06-03 02:01:00 GMT+01:00'), ('2013-06-03 02:01:00+07:00'), ('2013-06-03 02:01:00 America/Los_Angeles') +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@tstz3 +POSTHOOK: Lineage: tstz3.t SCRIPT [] +PREHOOK: query: select * from tstz3 +PREHOOK: type: QUERY +PREHOOK: Input: default@tstz3 +#### A masked pattern was here #### +POSTHOOK: query: select * from tstz3 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@tstz3 +#### A masked pattern was here #### +2013-06-03 02:01:00.30547 +2013-06-03 02:01:00.30547 +2013-06-03 02:01:00.30547 +2013-06-03 02:01:00 +2013-06-03 02:01:00 +2013-06-03 02:01:00 diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorUtils.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorUtils.java index 56243159db..b04dbba2ce 100644 --- serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorUtils.java +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/primitive/PrimitiveObjectInspectorUtils.java @@ -1255,40 +1255,18 @@ public static Timestamp getTimestamp(Object o, PrimitiveObjectInspector inputOI, return result; } - private final static int DATE_LENGTH = "YYYY-MM-DD".length(); private final static int TS_LENGTH = "yyyy-mm-dd hh:mm:ss".length(); + private final static int DATE_LENGTH = "YYYY-MM-DD".length(); public static Timestamp getTimestampFromString(String s) { - Timestamp result = null; s = s.trim(); s = trimNanoTimestamp(s); - // Handle simpler cases directly avoiding exceptions try { - if (s.length() == DATE_LENGTH) { - // Its a date! - return Timestamp.ofEpochMilli(Date.valueOf(s).toEpochMilli()); - } else if (isValidTimeStamp(s)) { - return Timestamp.valueOf(s); - } - // If a timestamp does not have a space, then it is likely zoned time. - if (s.contains("+") || (s.length() > DATE_LENGTH && s.charAt(DATE_LENGTH) == '-')) { - // Timestamp with timezone - // Let's try to parse it as timestamp with time zone and transform - try { - result = Timestamp.valueOf(TimestampTZUtil.parse(s).getZonedDateTime() - .toLocalDateTime().toString()); - } catch (DateTimeException e2) { - // Do nothing - } - } else { - // Last attempt - result = Timestamp.ofEpochMilli(Date.valueOf(s).toEpochMilli()); - } + return TimestampUtils.stringToTimestamp(s); } catch (IllegalArgumentException e) { - // Do nothing + return null; } - return result; } private static String trimNanoTimestamp(String s) { @@ -1296,8 +1274,9 @@ private static String trimNanoTimestamp(String s) { // Throw away extra if more than 9 decimal places int periodIdx = s.indexOf("."); if (periodIdx != -1) { - int secondSpace = firstSpace < 0 ? -1 : s.indexOf(' ', firstSpace + 1); - int maxLength = secondSpace == -1 ? s.length() : secondSpace; + int secondSpaceOrPlus = firstSpace < 0 ? -1 : s.indexOf(' ', firstSpace + 1); + secondSpaceOrPlus = firstSpace < 0 || secondSpaceOrPlus != -1 ? secondSpaceOrPlus : s.indexOf('+', firstSpace + 1); + int maxLength = secondSpaceOrPlus == -1 ? s.length() : secondSpaceOrPlus; if (maxLength - periodIdx > 9) { s = s.substring(0, periodIdx + 10).concat(s.substring(maxLength, s.length())); }