IMPALA-9217: Adjust limits for TZH and TZM datetime tokens

Values for TZH are expected in a range of [-15, 15] and for TZM are
expected in [0, 59]. This patch adjusts the checks for these limits
and adds some tests to verify that out of range values are not
accepted.

Change-Id: I6fe2534d51396bb5652af6301866e2dd0f3282c2
Reviewed-on: http://gerrit.cloudera.org:8080/14848
Reviewed-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
diff --git a/be/src/runtime/datetime-iso-sql-format-parser.cc b/be/src/runtime/datetime-iso-sql-format-parser.cc
index dae2b99..bd7fb5e 100644
--- a/be/src/runtime/datetime-iso-sql-format-parser.cc
+++ b/be/src/runtime/datetime-iso-sql-format-parser.cc
@@ -175,7 +175,7 @@
       case TIMEZONE_HOUR: {
         // Deliberately ignore the timezone offsets.
         int dummy_result;
-        if (!ParseAndValidate(current_pos, token_len, -99, 99, &dummy_result)) {
+        if (!ParseAndValidate(current_pos, token_len, -15, 15, &dummy_result)) {
           return false;
         }
         break;
@@ -183,7 +183,7 @@
       case TIMEZONE_MIN: {
         // Deliberately ignore the timezone offsets.
         int dummy_result;
-        if (!ParseAndValidate(current_pos, token_len, 0, 99, &dummy_result)) {
+        if (!ParseAndValidate(current_pos, token_len, 0, 59, &dummy_result)) {
           return false;
         }
         break;
diff --git a/tests/query_test/test_cast_with_format.py b/tests/query_test/test_cast_with_format.py
index bd1b069..7cbae34 100644
--- a/tests/query_test/test_cast_with_format.py
+++ b/tests/query_test/test_cast_with_format.py
@@ -1097,6 +1097,23 @@
         "timestamp FORMAT 'YYYY-MM-DD HH12:MI A.M.TZH:TZM')")
     assert result.data == ["2018-12-31 08:00:00"]
 
+    # Invalid TZH and TZM
+    result = self.client.execute("select cast('2016-01-01 10:00 AM +16:00' as "
+        "timestamp FORMAT 'YYYY-MM-DD HH12:MI A.M. TZH:TZM')")
+    assert result.data == ["NULL"]
+
+    result = self.client.execute("select cast('2016-01-01 11:00 AM -16:00' as "
+        "timestamp FORMAT 'YYYY-MM-DD HH12:MI A.M. TZH:TZM')")
+    assert result.data == ["NULL"]
+
+    result = self.client.execute("select cast('2016-01-01 10:00 AM 16:00' as "
+        "timestamp FORMAT 'YYYY-MM-DD HH12:MI A.M. TZH:TZM')")
+    assert result.data == ["NULL"]
+
+    result = self.client.execute("select cast('2016-01-01 10:00 AM +15:60' as "
+        "timestamp FORMAT 'YYYY-MM-DD HH12:MI A.M. TZH:TZM')")
+    assert result.data == ["NULL"]
+
     # One digit negative TZH at the end of the input string.
     result = self.client.execute("select cast('2018-12-31 12:01 -1' as timestamp "
         "FORMAT 'YYYY-MM-DD HH24:MI TZH')")