You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by jd...@apache.org on 2014/10/15 04:17:12 UTC

svn commit: r1631935 - in /hive/trunk/serde/src: java/org/apache/hadoop/hive/serde2/io/DateWritable.java test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java

Author: jdere
Date: Wed Oct 15 02:17:11 2014
New Revision: 1631935

URL: http://svn.apache.org/r1631935
Log:
HIVE-8102: Partitions of type 'date' behave incorrectly with daylight saving time (Jason Dere, reviewed by Thejas Nair)

Modified:
    hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/DateWritable.java
    hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java

Modified: hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/DateWritable.java
URL: http://svn.apache.org/viewvc/hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/DateWritable.java?rev=1631935&r1=1631934&r2=1631935&view=diff
==============================================================================
--- hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/DateWritable.java (original)
+++ hive/trunk/serde/src/java/org/apache/hadoop/hive/serde2/io/DateWritable.java Wed Oct 15 02:17:11 2014
@@ -128,7 +128,10 @@ public class DateWritable implements Wri
   public static long daysToMillis(int d) {
     // Convert from day offset to ms in UTC, then apply local timezone offset.
     long millisUtc = d * MILLIS_PER_DAY;
-    return millisUtc - LOCAL_TIMEZONE.get().getOffset(millisUtc);
+    long tmp =  millisUtc - LOCAL_TIMEZONE.get().getOffset(millisUtc);
+    // Between millisUtc and tmp, the time zone offset may have changed due to DST.
+    // Look up the offset again.
+    return millisUtc - LOCAL_TIMEZONE.get().getOffset(tmp);
   }
 
   public static int dateToDays(Date d) {

Modified: hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java
URL: http://svn.apache.org/viewvc/hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java?rev=1631935&r1=1631934&r2=1631935&view=diff
==============================================================================
--- hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java (original)
+++ hive/trunk/serde/src/test/org/apache/hadoop/hive/serde2/io/TestDateWritable.java Wed Oct 15 02:17:11 2014
@@ -10,6 +10,12 @@ import java.sql.Date;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 public class TestDateWritable {
 
@@ -135,4 +141,61 @@ public class TestDateWritable {
   private static String getRandomDateString() {
     return dateStrings[(int) (Math.random() * 365)];
   }
+
+  public static class DateTestCallable implements Callable<String> {
+    public DateTestCallable() {
+    }
+
+    @Override
+    public String call() throws Exception {
+      // Iterate through each day of the year, make sure Date/DateWritable match
+      Date originalDate = Date.valueOf("2014-01-01");
+      Calendar cal = Calendar.getInstance();
+      cal.setTimeInMillis(originalDate.getTime());
+      for (int idx = 0; idx < 365; ++idx) {
+        originalDate = new Date(cal.getTimeInMillis());
+        // Make sure originalDate is at midnight in the local time zone,
+        // since DateWritable will generate dates at that time.
+        originalDate = Date.valueOf(originalDate.toString());
+        DateWritable dateWritable = new DateWritable(originalDate);
+        if (!originalDate.equals(dateWritable.get())) {
+          return originalDate.toString();
+        }
+        cal.add(Calendar.DAY_OF_YEAR, 1);
+      }
+      // Success!
+      return null;
+    }
+  }
+
+  @Test
+  public void testDaylightSavingsTime() throws InterruptedException, ExecutionException {
+    String[] timeZones = {
+        "GMT",
+        "UTC",
+        "America/Godthab",
+        "America/Los_Angeles",
+        "Asia/Jerusalem",
+        "Australia/Melbourne",
+        "Europe/London",
+        // time zones with half hour boundaries
+        "America/St_Johns",
+        "Asia/Tehran",
+    };
+
+    for (String timeZone: timeZones) {
+      TimeZone previousDefault = TimeZone.getDefault();
+      TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
+      assertEquals("Default timezone should now be " + timeZone,
+          timeZone, TimeZone.getDefault().getID());
+      ExecutorService threadPool = Executors.newFixedThreadPool(1);
+      try {
+        Future<String> future = threadPool.submit(new DateTestCallable());
+        String result = future.get();
+        assertNull("Failed at timezone " + timeZone + ", date " + result, result);
+      } finally {
+        threadPool.shutdown(); TimeZone.setDefault(previousDefault);
+      }
+    }
+  }
 }