You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ku...@apache.org on 2019/11/22 10:25:02 UTC

[hive] branch master updated: HIVE-22511: Fix case of Month token in datetime to string conversion (Karen Coppage via Marta Kuczora)

This is an automated email from the ASF dual-hosted git repository.

kuczoram pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new afd4d60  HIVE-22511: Fix case of Month token in datetime to string conversion (Karen Coppage via Marta Kuczora)
afd4d60 is described below

commit afd4d607e9b72e08b260d76afd2ca796914be628
Author: Karen Coppage <kc...@gmail.com>
AuthorDate: Fri Nov 22 11:23:46 2019 +0100

    HIVE-22511: Fix case of Month token in datetime to string conversion (Karen Coppage via Marta Kuczora)
---
 .../format/datetime/HiveSqlDateTimeFormatter.java  | 33 ++++++++++++----------
 .../datetime/TestHiveSqlDateTimeFormatter.java     | 15 ++++++----
 2 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/common/src/java/org/apache/hadoop/hive/common/format/datetime/HiveSqlDateTimeFormatter.java b/common/src/java/org/apache/hadoop/hive/common/format/datetime/HiveSqlDateTimeFormatter.java
index 168a6f2..f6a52e9 100644
--- a/common/src/java/org/apache/hadoop/hive/common/format/datetime/HiveSqlDateTimeFormatter.java
+++ b/common/src/java/org/apache/hadoop/hive/common/format/datetime/HiveSqlDateTimeFormatter.java
@@ -243,9 +243,14 @@ import java.util.regex.Pattern;
  *
  * A.2. Character temporals
  * Temporal elements, but spelled out.
- * - For datetime to string conversion, the pattern's case must match one of the listed formats
- *   (e.g. mOnTh is not accepted) to avoid ambiguity. Output is right padded with trailing spaces
- *   unless the pattern is marked with the fill mode modifier (FM).
+ * - Output is right padded with trailing spaces unless the pattern is marked with the fill mode
+ *   modifier (FM). Capitalization happens as follows:
+ *   - If the first letter of the pattern is lowercase then the output is lowercase:
+ *     'mONTH' -> 'may'
+ *   - If the first two letters of the pattern are uppercase then the output is uppercase:
+ *     'MOnth' -> 'MAY'
+ *   - If the first letter of the pattern is uppercase and the second is lowercase then the output
+ *     is capitalized: 'Month' -> 'May'.
  * - For string to datetime conversion, the case of the pattern does not matter.
  *
  * MONTH|Month|month
@@ -868,14 +873,6 @@ public class HiveSqlDateTimeFormatter implements Serializable {
         throw new IllegalArgumentException(token.string.toUpperCase() + " not a valid format for "
             + "timestamp or date.");
       }
-      if (token.type == TokenType.CHARACTER_TEMPORAL) {
-        String s = token.string;
-        if (!(s.equals(s.toUpperCase()) || s.equals(capitalize(s)) || s.equals(s.toLowerCase()))) {
-          throw new IllegalArgumentException(
-              "Ambiguous capitalization of token " + s + ". Accepted " + "forms are " + s
-                  .toUpperCase() + ", " + capitalize(s) + ", or " + s.toLowerCase() + ".");
-        }
-      }
     }
   }
 
@@ -965,11 +962,17 @@ public class HiveSqlDateTimeFormatter implements Serializable {
       output = StringUtils.rightPad(output, token.length); //pad to size
     }
 
-    // set case
-    if (Character.isUpperCase(token.string.charAt(1))) {
-      output = output.toUpperCase();
-    } else if (Character.isLowerCase(token.string.charAt(0))) {
+    // Set case.
+    // If the first letter is lowercase then the output is lowercase: 'mONTH' -> 'may'
+    // If the first two letters are uppercase then the output is uppercase: 'MOnth' -> 'MAY'
+    // If the first letter is uppercase and the second is lowercase then the output is capitalized:
+    //     'Month' -> 'May'.
+    if (Character.isLowerCase(token.string.charAt(0))) {
       output = output.toLowerCase();
+    } else if (Character.isUpperCase(token.string.charAt(1))) {
+      output = output.toUpperCase();
+    } else {
+      output = capitalize(output);
     }
     return output;
   }
diff --git a/common/src/test/org/apache/hadoop/hive/common/format/datetime/TestHiveSqlDateTimeFormatter.java b/common/src/test/org/apache/hadoop/hive/common/format/datetime/TestHiveSqlDateTimeFormatter.java
index ea60a31..3abf28b 100644
--- a/common/src/test/org/apache/hadoop/hive/common/format/datetime/TestHiveSqlDateTimeFormatter.java
+++ b/common/src/test/org/apache/hadoop/hive/common/format/datetime/TestHiveSqlDateTimeFormatter.java
@@ -103,12 +103,6 @@ public class TestHiveSqlDateTimeFormatter {
     verifyBadPattern("tzm", false);
     verifyBadPattern("tzh", false);
 
-    //ambiguous case for formatting
-    verifyBadPattern("MOnth", false);
-    verifyBadPattern("DaY", false);
-    verifyBadPattern("dAy", false);
-    verifyBadPattern("dY", false);
-
     //illegal for parsing
     verifyBadPattern("yyyy-mm-dd q", true);
     verifyBadPattern("yyyy-mm-dd d", true);
@@ -130,15 +124,24 @@ public class TestHiveSqlDateTimeFormatter {
     checkFormatTs("YYYY-MM-DD HH12PM", "2017-05-05 00:00:00", "2017-05-05 12AM");
 
     checkFormatTs("YYYY-MONTH-DD", "2019-01-01 00:00:00", "2019-JANUARY  -01"); //fill to length 9
+    checkFormatTs("YYYY-MOnth-DD", "2019-01-01 00:00:00", "2019-JANUARY  -01");
     checkFormatTs("YYYY-Month-DD", "2019-01-01 00:00:00", "2019-January  -01");
+    checkFormatTs("YYYY-MoNTH-DD", "2019-01-01 00:00:00", "2019-January  -01");
     checkFormatTs("YYYY-month-DD", "2019-01-01 00:00:00", "2019-january  -01");
+    checkFormatTs("YYYY-mONTH-DD", "2019-01-01 00:00:00", "2019-january  -01");
     checkFormatTs("YYYY-MON-DD", "2019-01-01 00:00:00", "2019-JAN-01");
+    checkFormatTs("YYYY-MOn-DD", "2019-01-01 00:00:00", "2019-JAN-01");
     checkFormatTs("YYYY-Mon-DD", "2019-01-01 00:00:00", "2019-Jan-01");
+    checkFormatTs("YYYY-MoN-DD", "2019-01-01 00:00:00", "2019-Jan-01");
     checkFormatTs("YYYY-mon-DD", "2019-01-01 00:00:00", "2019-jan-01");
+    checkFormatTs("YYYY-mON-DD", "2019-01-01 00:00:00", "2019-jan-01");
 
     checkFormatTs("D: DAY", "2019-01-01 00:00:00", "3: TUESDAY  "); //fill to length 9
+    checkFormatTs("D: DAy", "2019-01-01 00:00:00", "3: TUESDAY  ");
     checkFormatTs("D: Day", "2019-01-02 00:00:00", "4: Wednesday");
+    checkFormatTs("D: DaY", "2019-01-02 00:00:00", "4: Wednesday");
     checkFormatTs("D: day", "2019-01-03 00:00:00", "5: thursday ");
+    checkFormatTs("D: dAY", "2019-01-03 00:00:00", "5: thursday ");
     checkFormatTs("D: DY", "2019-01-04 00:00:00", "6: FRI");
     checkFormatTs("D: Dy", "2019-01-05 00:00:00", "7: Sat");
     checkFormatTs("D: dy", "2019-01-06 00:00:00", "1: sun");