Fix for issue 795

In some cases the time zone array can be sorted in a different order than it is assumed to be. This patch ensures it
sorted in the order that binary search expects.

Change-Id: I9ea38559f3f3a2c771aea69d02ab04d0af552c5c
Reviewed-on: http://fulliautomatix.ics.uci.edu:8443/127
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <westmann@gmail.com>
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/DateTimeFormatUtils.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/DateTimeFormatUtils.java
index f0ee739..cb5d899 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/DateTimeFormatUtils.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/DateTimeFormatUtils.java
@@ -15,6 +15,7 @@
 package edu.uci.ics.asterix.om.base.temporal;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.TimeZone;
@@ -48,6 +49,8 @@
 
     private final GregorianCalendarSystem CAL = GregorianCalendarSystem.getInstance();
 
+    private final Charset ENCODING = Charset.forName("UTF-8");
+
     // For time
     private final char HOUR_CHAR = 'h';
     private final char MINUTE_CHAR = 'm';
@@ -90,19 +93,20 @@
     private final int MAX_DAY_CHARS = 2;
     private final int MAX_WEEKDAY_CHAR = 1;
 
-    private final byte[][] MONTH_NAMES = new byte[][] { "jan".getBytes(), "feb".getBytes(), "mar".getBytes(),
-            "apr".getBytes(), "may".getBytes(), "jun".getBytes(), "jul".getBytes(), "aug".getBytes(), "sep".getBytes(),
-            "oct".getBytes(), "nov".getBytes(), "dec".getBytes() };
+    private final byte[][] MONTH_NAMES = new byte[][] { "jan".getBytes(ENCODING), "feb".getBytes(ENCODING),
+            "mar".getBytes(ENCODING), "apr".getBytes(ENCODING), "may".getBytes(ENCODING), "jun".getBytes(ENCODING),
+            "jul".getBytes(ENCODING), "aug".getBytes(ENCODING), "sep".getBytes(ENCODING), "oct".getBytes(ENCODING),
+            "nov".getBytes(ENCODING), "dec".getBytes(ENCODING) };
 
-    private final byte[][] WEEKDAY_FULL_NAMES = new byte[][] { "monday".getBytes(), "tuesday".getBytes(),
-            "wednesday".getBytes(), "thursday".getBytes(), "friday".getBytes(), "saturday".getBytes(),
-            "sunday".getBytes() };
+    private final byte[][] WEEKDAY_FULL_NAMES = new byte[][] { "monday".getBytes(ENCODING),
+            "tuesday".getBytes(ENCODING), "wednesday".getBytes(ENCODING), "thursday".getBytes(ENCODING),
+            "friday".getBytes(ENCODING), "saturday".getBytes(ENCODING), "sunday".getBytes(ENCODING) };
 
-    private final byte[] UTC_BYTEARRAY = "utc".getBytes();
-    private final byte[] GMT_BYTEARRAY = "gmt".getBytes();
+    private final byte[] UTC_BYTEARRAY = "utc".getBytes(ENCODING);
+    private final byte[] GMT_BYTEARRAY = "gmt".getBytes(ENCODING);
 
-    private final byte[] AM_BYTEARRAY = "am".getBytes();
-    private final byte[] PM_BYTEARRAY = "pm".getBytes();
+    private final byte[] AM_BYTEARRAY = "am".getBytes(ENCODING);
+    private final byte[] PM_BYTEARRAY = "pm".getBytes(ENCODING);
 
     // Separators, for both time and date
     private final char HYPHEN_CHAR = '-';
@@ -122,18 +126,38 @@
     private final byte TO_LOWER_OFFSET = 'A' - 'a';
 
     private final String[] TZ_IDS = TimeZone.getAvailableIDs();
+
+
+    private Comparator<byte[]> byteArrayComparator = new Comparator<byte[]>() {
+        @Override
+        public int compare(byte[] o1, byte[] o2) {
+            int i = 0;
+            for (; i < o1.length && i < o2.length; i++) {
+                if (o1[i] != o2[i]) {
+                    return o1[i] - o2[i];
+                }
+            }
+            if (i < o1.length) {
+                return -1;
+            } else if (i < o2.length) {
+                return 1;
+            }
+            return 0;
+        }
+    };
+
     private final byte[][] TIMEZONE_IDS = new byte[TZ_IDS.length][];
     {
-        Arrays.sort(TZ_IDS);
         for (int i = 0; i < TIMEZONE_IDS.length; i++) {
-            TIMEZONE_IDS[i] = TZ_IDS[i].getBytes();
+            TIMEZONE_IDS[i] = TZ_IDS[i].getBytes(ENCODING);
         }
+        Arrays.sort(TIMEZONE_IDS, byteArrayComparator);
     }
 
     private final int[] TIMEZONE_OFFSETS = new int[TIMEZONE_IDS.length];
     {
         for (int i = 0; i < TIMEZONE_IDS.length; i++) {
-            TIMEZONE_OFFSETS[i] = TimeZone.getTimeZone(TZ_IDS[i]).getRawOffset();
+            TIMEZONE_OFFSETS[i] = TimeZone.getTimeZone(new String(TIMEZONE_IDS[i], ENCODING)).getRawOffset();
         }
     }
 
@@ -197,24 +221,6 @@
         return beginWith;
     }
 
-    private Comparator<byte[]> byteArrayComparator = new Comparator<byte[]>() {
-        @Override
-        public int compare(byte[] o1, byte[] o2) {
-            int i = 0;
-            for (; i < o1.length && i < o2.length; i++) {
-                if (o1[i] != o2[i]) {
-                    return o1[i] - o2[i];
-                }
-            }
-            if (i < o1.length) {
-                return -1;
-            } else if (i < o2.length) {
-                return 1;
-            }
-            return 0;
-        }
-    };
-
     private int monthIDSearch(byte[] barray, int start, int length) {
         for (int i = 0; i < MONTH_NAMES.length; i++) {
             if (byteArrayEqualToString(barray, start, length, MONTH_NAMES[i])) {
@@ -622,7 +628,7 @@
                         } else {
                             throw new AsterixTemporalTypeParseException("Unexpected timezone string: "
                                     + new String(Arrays.copyOfRange(data, dataStart + dataStringPointer, dataStart
-                                            + dataStringPointer)));
+                                            + timezoneEndField)));
                         }
                         dataStringPointer = timezoneEndField;
                     }