diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFFromUtcTimestamp.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFFromUtcTimestamp.java index 33fe507..0b7850a 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFFromUtcTimestamp.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFFromUtcTimestamp.java @@ -20,6 +20,8 @@ import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.HashSet; import java.util.TimeZone; import org.slf4j.Logger; @@ -47,6 +49,8 @@ private transient TextConverter textConverter; private transient SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private transient TimeZone tzUTC = TimeZone.getTimeZone("UTC"); + private transient HashSet tzSet = + new HashSet(Arrays.asList(TimeZone.getAvailableIDs())); @Override public ObjectInspector initialize(ObjectInspector[] arguments) @@ -110,6 +114,12 @@ public Object evaluate(DeferredObject[] arguments) throws HiveException { String tzStr = textConverter.convert(o1).toString(); TimeZone timezone = TimeZone.getTimeZone(tzStr); + if (!tzSet.contains(tzStr) && + timezone.getDisplayName(false, TimeZone.SHORT).equals("GMT")) { + // Unsupported timezone + throw new HiveException( + "Unsupported timezone : " + tzStr); + } TimeZone fromTz; TimeZone toTz; diff --git ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFFromUtcTimestamp.java ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFFromUtcTimestamp.java index ae4785a..61fd3ee 100644 --- ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFFromUtcTimestamp.java +++ ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFFromUtcTimestamp.java @@ -62,10 +62,34 @@ public void testFromUtcTimestamp() throws Exception { new Text("2015-03-28 19:00:00"), new Text("Europe/London"), Timestamp.valueOf("2015-03-28 19:00:00")); + runAndVerify(udf, + new Text("2015-03-28 19:00:00"), new Text("GMT-1"), + Timestamp.valueOf("2015-03-28 18:00:00")); + + runAndVerify(udf, + null, new Text("Europe/London"), + null); + // Make sure nanos are preserved runAndVerify(udf, new Text("2015-03-28 18:00:00.123456789"), new Text("Europe/London"), Timestamp.valueOf("2015-03-28 18:00:00.123456789")); + + try { + runAndVerify(udf, + new Text("2015-03-28 17:00:00"), new Text("XXX"), null); + fail(); + } catch (HiveException e) { + assertEquals("Unsupported timezone : XXX", e.getMessage()); + } + + try { + runAndVerify(udf, + new Text("2015-03-28 17:00:00"), new Text(""), null); + fail(); + } catch (HiveException e) { + assertEquals("Unsupported timezone : ", e.getMessage()); + } } public void testToUtcTimestamp() throws Exception { @@ -84,9 +108,33 @@ public void testToUtcTimestamp() throws Exception { new Text("2015-03-28 19:00:00"), new Text("Europe/London"), Timestamp.valueOf("2015-03-28 19:00:00")); + runAndVerify(udf, + new Text("2015-03-28 19:00:00"), new Text("GMT-1"), + Timestamp.valueOf("2015-03-28 20:00:00")); + + runAndVerify(udf, + null, new Text("Europe/London"), + null); + // Make sure nanos are preserved runAndVerify(udf, new Text("2015-03-28 18:00:00.123456789"), new Text("Europe/London"), Timestamp.valueOf("2015-03-28 18:00:00.123456789")); + + try { + runAndVerify(udf, + new Text("2015-03-28 17:00:00"), new Text("XXX"), null); + fail(); + } catch (HiveException e) { + assertEquals("Unsupported timezone : XXX", e.getMessage()); + } + + try { + runAndVerify(udf, + new Text("2015-03-28 17:00:00"), new Text(""), null); + fail(); + } catch (HiveException e) { + assertEquals("Unsupported timezone : ", e.getMessage()); + } } } diff --git ql/src/test/queries/clientpositive/udf_from_utc_timestamp.q ql/src/test/queries/clientpositive/udf_from_utc_timestamp.q index ca0a6a8..345e3d7 100644 --- ql/src/test/queries/clientpositive/udf_from_utc_timestamp.q +++ ql/src/test/queries/clientpositive/udf_from_utc_timestamp.q @@ -8,8 +8,6 @@ from_utc_timestamp('2012-02-11 04:30:00', 'PST'), from_utc_timestamp('2012-02-11 04:30:00', 'Europe/Moscow'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT+8'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -from_utc_timestamp('2012-02-11 04:30:00', ''), -from_utc_timestamp('2012-02-11 04:30:00', '---'), from_utc_timestamp(cast(null as string), 'PST'), from_utc_timestamp('2012-02-11 04:30:00', cast(null as string)); @@ -18,8 +16,6 @@ from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'Europe/Moscow'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT+8'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), from_utc_timestamp(cast(null as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)); diff --git ql/src/test/queries/clientpositive/udf_to_utc_timestamp.q ql/src/test/queries/clientpositive/udf_to_utc_timestamp.q index cca6d7d..584e97f 100644 --- ql/src/test/queries/clientpositive/udf_to_utc_timestamp.q +++ ql/src/test/queries/clientpositive/udf_to_utc_timestamp.q @@ -8,8 +8,6 @@ to_utc_timestamp('2012-02-10 20:30:00', 'PST'), to_utc_timestamp('2012-02-11 08:30:00', 'Europe/Moscow'), to_utc_timestamp('2012-02-11 12:30:00', 'GMT+8'), to_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -to_utc_timestamp('2012-02-11 04:30:00', ''), -to_utc_timestamp('2012-02-11 04:30:00', '---'), to_utc_timestamp(cast(null as string), 'PST'), to_utc_timestamp('2012-02-11 04:30:00', cast(null as string)); @@ -18,7 +16,5 @@ to_utc_timestamp(cast('2012-02-10 20:30:00' as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 08:30:00' as timestamp), 'Europe/Moscow'), to_utc_timestamp(cast('2012-02-11 12:30:00' as timestamp), 'GMT+8'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), to_utc_timestamp(cast(null as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)); diff --git ql/src/test/results/clientpositive/udf_from_utc_timestamp.q.out ql/src/test/results/clientpositive/udf_from_utc_timestamp.q.out index be2cb1a..b8af3b7 100644 --- ql/src/test/results/clientpositive/udf_from_utc_timestamp.q.out +++ ql/src/test/results/clientpositive/udf_from_utc_timestamp.q.out @@ -35,8 +35,6 @@ from_utc_timestamp('2012-02-11 04:30:00', 'PST'), from_utc_timestamp('2012-02-11 04:30:00', 'Europe/Moscow'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT+8'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -from_utc_timestamp('2012-02-11 04:30:00', ''), -from_utc_timestamp('2012-02-11 04:30:00', '---'), from_utc_timestamp(cast(null as string), 'PST'), from_utc_timestamp('2012-02-11 04:30:00', cast(null as string)) PREHOOK: type: QUERY @@ -47,21 +45,17 @@ from_utc_timestamp('2012-02-11 04:30:00', 'PST'), from_utc_timestamp('2012-02-11 04:30:00', 'Europe/Moscow'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT+8'), from_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -from_utc_timestamp('2012-02-11 04:30:00', ''), -from_utc_timestamp('2012-02-11 04:30:00', '---'), from_utc_timestamp(cast(null as string), 'PST'), from_utc_timestamp('2012-02-11 04:30:00', cast(null as string)) POSTHOOK: type: QUERY POSTHOOK: Input: _dummy_database@_dummy_table #### A masked pattern was here #### -2012-02-10 20:30:00 2012-02-11 08:30:00 2012-02-11 12:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL +2012-02-10 20:30:00 2012-02-11 08:30:00 2012-02-11 12:30:00 2012-02-11 04:30:00 NULL NULL PREHOOK: query: select from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'Europe/Moscow'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT+8'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), from_utc_timestamp(cast(null as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)) PREHOOK: type: QUERY @@ -72,14 +66,12 @@ from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'Europe/Moscow'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT+8'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), from_utc_timestamp(cast(null as timestamp), 'PST'), from_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)) POSTHOOK: type: QUERY POSTHOOK: Input: _dummy_database@_dummy_table #### A masked pattern was here #### -2012-02-10 20:30:00 2012-02-11 08:30:00 2012-02-11 12:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL +2012-02-10 20:30:00 2012-02-11 08:30:00 2012-02-11 12:30:00 2012-02-11 04:30:00 NULL NULL PREHOOK: query: select from_utc_timestamp('2012-02-11-04:30:00', 'UTC'), from_utc_timestamp('2012-02-11-04:30:00', 'PST') diff --git ql/src/test/results/clientpositive/udf_to_utc_timestamp.q.out ql/src/test/results/clientpositive/udf_to_utc_timestamp.q.out index 1730f8c..ff00578 100644 --- ql/src/test/results/clientpositive/udf_to_utc_timestamp.q.out +++ ql/src/test/results/clientpositive/udf_to_utc_timestamp.q.out @@ -35,8 +35,6 @@ to_utc_timestamp('2012-02-10 20:30:00', 'PST'), to_utc_timestamp('2012-02-11 08:30:00', 'Europe/Moscow'), to_utc_timestamp('2012-02-11 12:30:00', 'GMT+8'), to_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -to_utc_timestamp('2012-02-11 04:30:00', ''), -to_utc_timestamp('2012-02-11 04:30:00', '---'), to_utc_timestamp(cast(null as string), 'PST'), to_utc_timestamp('2012-02-11 04:30:00', cast(null as string)) PREHOOK: type: QUERY @@ -47,21 +45,17 @@ to_utc_timestamp('2012-02-10 20:30:00', 'PST'), to_utc_timestamp('2012-02-11 08:30:00', 'Europe/Moscow'), to_utc_timestamp('2012-02-11 12:30:00', 'GMT+8'), to_utc_timestamp('2012-02-11 04:30:00', 'GMT'), -to_utc_timestamp('2012-02-11 04:30:00', ''), -to_utc_timestamp('2012-02-11 04:30:00', '---'), to_utc_timestamp(cast(null as string), 'PST'), to_utc_timestamp('2012-02-11 04:30:00', cast(null as string)) POSTHOOK: type: QUERY POSTHOOK: Input: _dummy_database@_dummy_table #### A masked pattern was here #### -2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL +2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL PREHOOK: query: select to_utc_timestamp(cast('2012-02-10 20:30:00' as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 08:30:00' as timestamp), 'Europe/Moscow'), to_utc_timestamp(cast('2012-02-11 12:30:00' as timestamp), 'GMT+8'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), to_utc_timestamp(cast(null as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)) PREHOOK: type: QUERY @@ -72,11 +66,9 @@ to_utc_timestamp(cast('2012-02-10 20:30:00' as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 08:30:00' as timestamp), 'Europe/Moscow'), to_utc_timestamp(cast('2012-02-11 12:30:00' as timestamp), 'GMT+8'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), 'GMT'), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), ''), -to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), '---'), to_utc_timestamp(cast(null as timestamp), 'PST'), to_utc_timestamp(cast('2012-02-11 04:30:00' as timestamp), cast(null as string)) POSTHOOK: type: QUERY POSTHOOK: Input: _dummy_database@_dummy_table #### A masked pattern was here #### -2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL +2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 2012-02-11 04:30:00 NULL NULL