ASTERIXDB-1635 Fix for overlap-bins start for dates.

The fix involves two code changes and several sonar fixes.
The code changes are the following:
 - DurationArithmeticOperations line 75:
    When the month was zero, an index out of bound error occured in line 88 or 92.
    The month value should be between 1 and 12.
 - OverlapBinsDescriptor line 170:
    The Gregorian Calendar is expecting a value in ms. When a date value comes in,
    AsterixDB represents the value as the number of days from epoc. So the year
    for a date basically allways translated to 1970. In lines 121, a condition
    was added to check if the interval was a date, if so, convert the date to
    ms.

Change-Id: I24122a84ef9edda4b05260af881c430177f1dc86
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1151
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Steven Jacobs <sjaco002@ucr.edu>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/datetime_functions/datetime_functions.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/datetime_functions/datetime_functions.3.query.aql
index b94b5bf..47831e2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/datetime_functions/datetime_functions.3.query.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/datetime_functions/datetime_functions.3.query.aql
@@ -39,12 +39,16 @@
 let $null6 := null + $dr1
 let $null7 := $dt1 + null
 let $c1 := $dt1 = ($dt1 - $dt3) + $dt3
+let $dt4 := $dt1 - duration("P1MT1S")
+let $dt5 := $dt1 + duration("P1MT1S")
 
 return {
   "datetime1" : $dt1,
   "datetime1secs": $dtsecs1,
   "datetime2" : $dt2,
   "datetime3" : $dt3,
+  "datetime4" : $dt4,
+  "datetime5" : $dt5,
   "unixms1" : $unixms1,
   "unixsecs1": $unixsecs1,
   "duration1" : $dr1,
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.3.query.aql
index 8011ad6..bfb5527 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.3.query.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.3.query.aql
@@ -25,5 +25,5 @@
 let $itv2 := interval(date("1984-03-17"), date("2013-08-22"))
 let $itv3 := interval(datetime("1800-01-01T23:59:48.938"), datetime("2015-07-26T13:28:30.218"))
 return { "timebins": overlap-bins($itv1, time("00:00:00"), day-time-duration("PT30M")),
-         "datebins": overlap-bins($itv2, date("1990-01-01"), year-month-duration("P20Y")),
+         "datebins": overlap-bins($itv2, date("1990-01-01"), year-month-duration("P10Y")),
          "datetimebins": overlap-bins($itv3, datetime("1900-01-01T00:00:00.000"), year-month-duration("P100Y")) }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/datetime_functions/datetime_functions.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/datetime_functions/datetime_functions.3.query.sqlpp
index e28661a..de8398f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/datetime_functions/datetime_functions.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/datetime_functions/datetime_functions.3.query.sqlpp
@@ -26,6 +26,8 @@
 , 'datetime1secs' : test.`datetime-from-unix-time-in-secs`(1356048000)
 , 'datetime2' : test.`datetime-from-date-time`(test.date('1327-12-02'), test.time('15:35:49.938-0800'))
 , 'datetime3' : (test.`datetime-from-unix-time-in-ms`(956007429) + (test.`datetime-from-date-time`(test.date('1327-12-02'),test.time('15:35:49.938-0800')) - test.`datetime-from-unix-time-in-ms`(956007429)))
+, 'datetime4' : test.`datetime-from-unix-time-in-ms`(956007429) - test.duration('P1MT1S')
+, 'datetime5' : test.`datetime-from-unix-time-in-ms`(956007429) + test.duration('P1MT1S')
 , 'unixms1' : test.`unix-time-from-datetime-in-ms`(test.`datetime-from-unix-time-in-ms`(956007429))
 , 'unixsecs1' : test.`unix-time-from-datetime-in-secs`(test.`datetime-from-unix-time-in-secs`(1356048000))
 , 'duration1' : (test.`datetime-from-date-time`(test.date('1327-12-02'),test.time('15:35:49.938-0800')) - test.`datetime-from-unix-time-in-ms`(956007429))
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/overlap_bins/overlap_bins.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/overlap_bins/overlap_bins.3.query.sqlpp
index e42707f..90cd95e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/overlap_bins/overlap_bins.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/overlap_bins/overlap_bins.3.query.sqlpp
@@ -22,6 +22,6 @@
  **/
 
 { 'timebins':`overlap-bins`(interval(time('17:23:37'),time('18:30:21')),time('00:00:00'),`day-time-duration`('PT30M')),
-  'datebins':`overlap-bins`(interval(date('1984-03-17'),date('2013-08-22')),date('1990-01-01'),`year-month-duration`('P20Y')),
+  'datebins':`overlap-bins`(interval(date('1984-03-17'),date('2013-08-22')),date('1990-01-01'),`year-month-duration`('P10Y')),
   'datetimebins':`overlap-bins`(interval(datetime('1800-01-01T23:59:48.938'),datetime('2015-07-26T13:28:30.218')),datetime('1900-01-01T00:00:00.000'),
   `year-month-duration`('P100Y'))};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/datetime_functions/datetime_functions.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/datetime_functions/datetime_functions.1.adm
index 6107bc2..5ed1acf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/datetime_functions/datetime_functions.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/datetime_functions/datetime_functions.1.adm
@@ -1 +1 @@
-{ "datetime1": datetime("1970-01-12T01:33:27.429Z"), "datetime1secs": datetime("2012-12-21T00:00:00.000Z"), "datetime2": datetime("1327-12-02T23:35:49.938Z"), "datetime3": datetime("1327-12-02T23:35:49.938Z"), "unixms1": 956007429, "unixsecs1": 1356048000, "duration1": duration("-P234526DT1H57M37.491S"), "c1": true, "null1": null, "null1secs": null, "nullunixms1": null, "nullunixsecs1": null, "null2": null, "null3": null, "null4": null, "null5": null, "null6": null, "null7": null }
+{ "datetime1": datetime("1970-01-12T01:33:27.429Z"), "datetime1secs": datetime("2012-12-21T00:00:00.000Z"), "datetime2": datetime("1327-12-02T23:35:49.938Z"), "datetime3": datetime("1327-12-02T23:35:49.938Z"), "datetime4": datetime("1969-12-12T01:33:26.429Z"), "datetime5": datetime("1970-02-12T01:33:28.429Z"), "unixms1": 956007429, "unixsecs1": 1356048000, "duration1": duration("-P234526DT1H57M37.491S"), "c1": true, "null1": null, "null1secs": null, "nullunixms1": null, "nullunixsecs1": null, "null2": null, "null3": null, "null4": null, "null5": null, "null6": null, "null7": null }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/overlap_bins/overlap_bins.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/overlap_bins/overlap_bins.1.adm
index 493a1ca..14f6aaea 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/overlap_bins/overlap_bins.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/overlap_bins/overlap_bins.1.adm
@@ -1 +1 @@
-{ "timebins": [ interval(time("17:00:00.000Z"), time("17:30:00.000Z")), interval(time("17:30:00.000Z"), time("18:00:00.000Z")), interval(time("18:00:00.000Z"), time("18:30:00.000Z")), interval(time("18:30:00.000Z"), time("19:00:00.000Z")) ], "datebins": [ interval(date("1970-01-01"), date("1990-01-01")), interval(date("1990-01-01"), date("2010-01-01")), interval(date("2010-01-01"), date("2030-01-01")) ], "datetimebins": [ interval(datetime("1800-01-01T00:00:00.000Z"), datetime("1900-01-01T00:00:00.000Z")), interval(datetime("1900-01-01T00:00:00.000Z"), datetime("2000-01-01T00:00:00.000Z")), interval(datetime("2000-01-01T00:00:00.000Z"), datetime("2100-01-01T00:00:00.000Z")) ] }
+{ "timebins": [ interval(time("17:00:00.000Z"), time("17:30:00.000Z")), interval(time("17:30:00.000Z"), time("18:00:00.000Z")), interval(time("18:00:00.000Z"), time("18:30:00.000Z")), interval(time("18:30:00.000Z"), time("19:00:00.000Z")) ], "datebins": [ interval(date("1980-01-01"), date("1990-01-01")), interval(date("1990-01-01"), date("2000-01-01")), interval(date("2000-01-01"), date("2010-01-01")), interval(date("2010-01-01"), date("2020-01-01")) ], "datetimebins": [ interval(datetime("1800-01-01T00:00:00.000Z"), datetime("1900-01-01T00:00:00.000Z")), interval(datetime("1900-01-01T00:00:00.000Z"), datetime("2000-01-01T00:00:00.000Z")), interval(datetime("2000-01-01T00:00:00.000Z"), datetime("2100-01-01T00:00:00.000Z")) ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/datetime_functions/datetime_functions.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/datetime_functions/datetime_functions.3.ast
index 1a36e5a..c9d1ded 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/datetime_functions/datetime_functions.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/datetime_functions/datetime_functions.3.ast
@@ -53,6 +53,32 @@
     ]
   )
   (
+    LiteralExpr [STRING] [datetime4]
+    :
+    OperatorExpr [
+      FunctionCall test.datetime-from-unix-time-in-ms@1[
+        LiteralExpr [LONG] [956007429]
+      ]
+      -
+      FunctionCall test.duration@1[
+        LiteralExpr [STRING] [P1MT1S]
+      ]
+    ]
+  )
+  (
+    LiteralExpr [STRING] [datetime5]
+    :
+    OperatorExpr [
+      FunctionCall test.datetime-from-unix-time-in-ms@1[
+        LiteralExpr [LONG] [956007429]
+      ]
+      +
+      FunctionCall test.duration@1[
+        LiteralExpr [STRING] [P1MT1S]
+      ]
+    ]
+  )
+  (
     LiteralExpr [STRING] [unixms1]
     :
     FunctionCall test.unix-time-from-datetime-in-ms@1[
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins/overlap_bins.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins/overlap_bins.3.ast
index 962d9ff..01cd805 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins/overlap_bins.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins/overlap_bins.3.ast
@@ -36,7 +36,7 @@
         LiteralExpr [STRING] [1990-01-01]
       ]
       FunctionCall null.year-month-duration@1[
-        LiteralExpr [STRING] [P20Y]
+        LiteralExpr [STRING] [P10Y]
       ]
     ]
   )
diff --git a/asterixdb/asterix-doc/src/site/markdown/aql/functions.md b/asterixdb/asterix-doc/src/site/markdown/aql/functions.md
index b6f5538..81ef9c7 100644
--- a/asterixdb/asterix-doc/src/site/markdown/aql/functions.md
+++ b/asterixdb/asterix-doc/src/site/markdown/aql/functions.md
@@ -2310,7 +2310,7 @@
         let $itv2 := interval(date("1984-03-17"), date("2013-08-22"))
         let $itv3 := interval(datetime("1800-01-01T23:59:48.938"), datetime("2015-07-26T13:28:30.218"))
         return { "timebins": overlap-bins($itv1, time("00:00:00"), day-time-duration("PT30M")),
-          "datebins": overlap-bins($itv2, date("1990-01-01"), year-month-duration("P20Y")),
+          "datebins": overlap-bins($itv2, date("1990-01-01"), year-month-duration("P10Y")),
           "datetimebins": overlap-bins($itv3, datetime("1900-01-01T00:00:00.000"), year-month-duration("P100Y")) }
 
    * The expected result is:
@@ -2319,9 +2319,10 @@
               interval(time("17:30:00.000Z"), time("18:00:00.000Z")),
               interval(time("18:00:00.000Z"), time("18:30:00.000Z")),
               interval(time("18:30:00.000Z"), time("19:00:00.000Z")) ],
-          "datebins": [ interval(date("1970-01-01"), date("1990-01-01")),
-              interval(date("1990-01-01"), date("2010-01-01")),
-              interval(date("2010-01-01"), date("2030-01-01")) ],
+          "datebins": [ interval(date("1980-01-01"), date("1990-01-01")),
+              interval(date("1990-01-01"), date("2000-01-01")),
+              interval(date("2000-01-01"), date("2010-01-01")),
+              interval(date("2010-01-01"), date("2020-01-01")) ],
           "datetimebins": [ interval(datetime("1800-01-01T00:00:00.000Z"), datetime("1900-01-01T00:00:00.000Z")),
               interval(datetime("1900-01-01T00:00:00.000Z"), datetime("2000-01-01T00:00:00.000Z")),
               interval(datetime("2000-01-01T00:00:00.000Z"), datetime("2100-01-01T00:00:00.000Z")) ] }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
index 8e33d44..1051458 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
@@ -51,24 +51,24 @@
  */
 public class DateTimeFormatUtils {
 
-    private final GregorianCalendarSystem CAL = GregorianCalendarSystem.getInstance();
+    private static final GregorianCalendarSystem CAL = GregorianCalendarSystem.getInstance();
 
-    private final Charset ENCODING = Charset.forName("UTF-8");
+    private static final Charset ENCODING = Charset.forName("UTF-8");
 
     // For time
-    private final char HOUR_CHAR = 'h';
-    private final char MINUTE_CHAR = 'm';
-    private final char SECOND_CHAR = 's';
-    private final char MILLISECOND_CHAR = 'n';
-    private final char AMPM_CHAR = 'a';
-    private final char TIMEZONE_CHAR = 'z';
+    private static final char HOUR_CHAR = 'h';
+    private static final char MINUTE_CHAR = 'm';
+    private static final char SECOND_CHAR = 's';
+    private static final char MILLISECOND_CHAR = 'n';
+    private static final char AMPM_CHAR = 'a';
+    private static final char TIMEZONE_CHAR = 'z';
 
-    private final int MAX_HOUR_CHARS = 2;
-    private final int MAX_MINUTE_CHARS = 2;
-    private final int MAX_SECOND_CHARS = 2;
-    private final int MAX_MILLISECOND_CHARS = 3;
-    private final int MAX_AMPM_CHARS = 1;
-    private final int MAX_TIMEZONE_CHARS = 1;
+    private static final int MAX_HOUR_CHARS = 2;
+    private static final int MAX_MINUTE_CHARS = 2;
+    private static final int MAX_SECOND_CHARS = 2;
+    private static final int MAX_MILLISECOND_CHARS = 3;
+    private static final int MAX_AMPM_CHARS = 1;
+    private static final int MAX_TIMEZONE_CHARS = 1;
 
     private enum DateTimeProcessState {
         INIT,
@@ -87,52 +87,51 @@
     }
 
     // For date
-    private final char YEAR_CHAR = 'Y';
-    private final char MONTH_CHAR = 'M';
-    private final char DAY_CHAR = 'D';
-    private final char WEEKDAY_CHAR = 'W';
+    private static final char YEAR_CHAR = 'Y';
+    private static final char MONTH_CHAR = 'M';
+    private static final char DAY_CHAR = 'D';
+    private static final char WEEKDAY_CHAR = 'W';
 
-    private final int MAX_YEAR_CHARS = 4;
-    private final int MAX_MONTH_CHARS = 3;
-    private final int MAX_DAY_CHARS = 2;
-    private final int MAX_WEEKDAY_CHAR = 1;
+    private static final int MAX_YEAR_CHARS = 4;
+    private static final int MAX_MONTH_CHARS = 3;
+    private static final int MAX_DAY_CHARS = 2;
+    private static final int MAX_WEEKDAY_CHAR = 1;
 
-    private final byte[][] MONTH_NAMES = new byte[][] { "jan".getBytes(ENCODING), "feb".getBytes(ENCODING),
+    private static 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(ENCODING),
+    private static 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(ENCODING);
-    private final byte[] GMT_BYTEARRAY = "gmt".getBytes(ENCODING);
+    private static final byte[] UTC_BYTEARRAY = "utc".getBytes(ENCODING);
+    private static final byte[] GMT_BYTEARRAY = "gmt".getBytes(ENCODING);
 
-    private final byte[] AM_BYTEARRAY = "am".getBytes(ENCODING);
-    private final byte[] PM_BYTEARRAY = "pm".getBytes(ENCODING);
+    private static final byte[] AM_BYTEARRAY = "am".getBytes(ENCODING);
+    private static final byte[] PM_BYTEARRAY = "pm".getBytes(ENCODING);
 
     // Separators, for both time and date
-    private final char HYPHEN_CHAR = '-';
-    private final char COLON_CHAR = ':';
-    private final char SOLIDUS_CHAR = '/';
-    private final char PERIOD_CHAR = '.';
-    private final char COMMA_CHAR = ',';
-    private final char T_CHAR = 'T';
+    private static final char HYPHEN_CHAR = '-';
+    private static final char COLON_CHAR = ':';
+    private static final char SOLIDUS_CHAR = '/';
+    private static final char PERIOD_CHAR = '.';
+    private static final char COMMA_CHAR = ',';
+    private static final char T_CHAR = 'T';
 
     // Skipper, representing a field with characters and numbers that to be skipped
-    private final char SKIPPER_CHAR = 'O';
-    private final int MAX_SKIPPER_CHAR = 1;
+    private static final char SKIPPER_CHAR = 'O';
+    private static final int MAX_SKIPPER_CHAR = 1;
 
-    private final int MS_PER_MINUTE = 60 * 1000;
-    private final int MS_PER_HOUR = 60 * MS_PER_MINUTE;
+    private static final int MS_PER_MINUTE = 60 * 1000;
+    private static final int MS_PER_HOUR = 60 * MS_PER_MINUTE;
 
-    private final byte TO_LOWER_OFFSET = 'A' - 'a';
+    private static final byte TO_LOWER_OFFSET = 'A' - 'a';
 
-    private final String[] TZ_IDS = TimeZone.getAvailableIDs();
+    private static final String[] TZ_IDS = TimeZone.getAvailableIDs();
 
-
-    private Comparator<byte[]> byteArrayComparator = new Comparator<byte[]>() {
+    private static Comparator<byte[]> byteArrayComparator = new Comparator<byte[]>() {
         @Override
         public int compare(byte[] o1, byte[] o2) {
             int i = 0;
@@ -150,32 +149,35 @@
         }
     };
 
-    private final byte[][] TIMEZONE_IDS = new byte[TZ_IDS.length][];
-    {
+    private static final byte[][] TIMEZONE_IDS = new byte[TZ_IDS.length][];
+    static {
         for (int i = 0; i < TIMEZONE_IDS.length; i++) {
             TIMEZONE_IDS[i] = TZ_IDS[i].getBytes(ENCODING);
         }
         Arrays.sort(TIMEZONE_IDS, byteArrayComparator);
     }
 
-    private final int[] TIMEZONE_OFFSETS = new int[TIMEZONE_IDS.length];
-    {
+    private static final int[] TIMEZONE_OFFSETS = new int[TIMEZONE_IDS.length];
+    static {
         for (int i = 0; i < TIMEZONE_IDS.length; i++) {
             TIMEZONE_OFFSETS[i] = TimeZone.getTimeZone(new String(TIMEZONE_IDS[i], ENCODING)).getRawOffset();
         }
     }
 
+    private DateTimeFormatUtils() {
+    }
+
     private static class DateTimeFormatUtilsHolder {
         private static final DateTimeFormatUtils INSTANCE = new DateTimeFormatUtils();
+
+        private DateTimeFormatUtilsHolder() {
+        }
     }
 
     public static DateTimeFormatUtils getInstance() {
         return DateTimeFormatUtilsHolder.INSTANCE;
     }
 
-    private DateTimeFormatUtils() {
-    }
-
     private int parseFormatField(byte[] format, int formatStart, int formatLength, int formatPointer, char formatChar,
             int maxAllowedFormatCharCopied) {
 
@@ -188,9 +190,9 @@
             formatCharCopies++;
         }
         if (formatCharCopies > maxAllowedFormatCharCopied) {
-            throw new IllegalStateException("The format string for " + formatChar
-                    + " is too long: expected no more than " + maxAllowedFormatCharCopied + " but got "
-                    + formatCharCopies);
+            throw new IllegalStateException(
+                    "The format string for " + formatChar + " is too long: expected no more than "
+                            + maxAllowedFormatCharCopied + " but got " + formatCharCopies);
         }
 
         return formatCharCopies;
@@ -442,7 +444,8 @@
                     }
                     // for more digits
                     while (processedFieldsCount < maxAllowedFormatCharCopies && dataStringPointer < dataLength
-                            && data[dataStart + dataStringPointer] >= '0' && data[dataStart + dataStringPointer] <= '9') {
+                            && data[dataStart + dataStringPointer] >= '0'
+                            && data[dataStart + dataStringPointer] <= '9') {
                         parsedValue = parsedValue * 10 + (data[dataStart + dataStringPointer] - '0');
                         dataStringPointer++;
                         processedFieldsCount++;
@@ -464,15 +467,16 @@
                             month = monthNameMatch + 1;
                             dataStringPointer += 3;
                         } else {
-                            throw new AsterixTemporalTypeParseException("Unrecognizable month string "
-                                    + (char) data[dataStart + dataStringPointer] + " "
-                                    + (char) data[dataStart + dataStringPointer + 1] + " "
-                                    + (char) data[dataStart + dataStringPointer + 2]);
+                            throw new AsterixTemporalTypeParseException(
+                                    "Unrecognizable month string " + (char) data[dataStart + dataStringPointer] + " "
+                                            + (char) data[dataStart + dataStringPointer + 1] + " "
+                                            + (char) data[dataStart + dataStringPointer + 2]);
                         }
                     } else {
                         int processedMonthFieldsCount = 0;
                         for (int i = 0; i < formatCharCopies; i++) {
-                            if (data[dataStart + dataStringPointer] < '0' || data[dataStart + dataStringPointer] > '9') {
+                            if (data[dataStart + dataStringPointer] < '0'
+                                    || data[dataStart + dataStringPointer] > '9') {
                                 throw new AsterixTemporalTypeParseException("Unexpected char for month field at "
                                         + (dataStart + dataStringPointer) + ": " + data[dataStart + dataStringPointer]);
                             }
@@ -495,17 +499,17 @@
                     break;
                 case WEEKDAY:
                     int processedWeekdayFieldsCount = 0;
-                    while ((data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'a' && data[dataStart
-                            + dataStringPointer + processedWeekdayFieldsCount] <= 'z')
-                            || (data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'A' && data[dataStart
-                                    + dataStringPointer + processedWeekdayFieldsCount] <= 'Z')) {
+                    while ((data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'a'
+                            && data[dataStart + dataStringPointer + processedWeekdayFieldsCount] <= 'z')
+                            || (data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'A'
+                                    && data[dataStart + dataStringPointer + processedWeekdayFieldsCount] <= 'Z')) {
                         processedWeekdayFieldsCount++;
                     }
                     // match the weekday name
                     if (weekdayIDSearch(data, dataStart + dataStringPointer, processedWeekdayFieldsCount) < 0) {
                         throw new AsterixTemporalTypeParseException("Unexpected string for day-of-week: "
-                                + (new String(Arrays.copyOfRange(data, dataStart + dataStringPointer, dataStart
-                                        + dataStringPointer + processedWeekdayFieldsCount))));
+                                + (new String(Arrays.copyOfRange(data, dataStart + dataStringPointer,
+                                        dataStart + dataStringPointer + processedWeekdayFieldsCount))));
                     }
                     dataStringPointer += processedWeekdayFieldsCount;
                     break;
@@ -531,7 +535,8 @@
                     }
                     // if there are more than formatCharCopies digits for the hour string
                     while (processFieldsCount < expectedMaxCount && dataStringPointer < dataLength
-                            && data[dataStart + dataStringPointer] >= '0' && data[dataStart + dataStringPointer] <= '9') {
+                            && data[dataStart + dataStringPointer] >= '0'
+                            && data[dataStart + dataStringPointer] <= '9') {
                         parsedValue = parsedValue * 10 + (data[dataStart + dataStringPointer] - '0');
                         dataStringPointer++;
                         processFieldsCount++;
@@ -553,18 +558,19 @@
                     if (data[dataStart + dataStringPointer] == 'Z'
                             && ((dataStringPointer + 1 >= dataLength) || (data[dataStart + dataStringPointer + 1] < 'A'
                                     && data[dataStart + dataStringPointer + 1] > 'Z'
-                                    && data[dataStart + dataStringPointer + 1] < 'a' && data[dataStart
-                                    + dataStringPointer + 1] > 'z'))) {
+                                    && data[dataStart + dataStringPointer + 1] < 'a'
+                                    && data[dataStart + dataStringPointer + 1] > 'z'))) {
                         // UTC as Z
                         timezone = 0;
                         dataStringPointer++;
-                    } else if ((data[dataStart + dataStringPointer] == '+' || data[dataStart + dataStringPointer] == '-')
-                            || (dataStringPointer + 3 < dataLength && (data[dataStart + dataStringPointer + 3] == '+' || data[dataStart
-                                    + dataStringPointer + 3] == '-'))) {
+                    } else if ((data[dataStart + dataStringPointer] == '+'
+                            || data[dataStart + dataStringPointer] == '-')
+                            || (dataStringPointer + 3 < dataLength && (data[dataStart + dataStringPointer + 3] == '+'
+                                    || data[dataStart + dataStringPointer + 3] == '-'))) {
                         // UTC+ or GMT+ format
-                        if (dataStringPointer + 3 < dataLength
-                                && (byteArrayEqualToString(data, dataStart + dataStringPointer, 3, UTC_BYTEARRAY) || byteArrayEqualToString(
-                                        data, dataStart + dataStringPointer, 3, GMT_BYTEARRAY))) {
+                        if (dataStringPointer + 3 < dataLength && (byteArrayEqualToString(data,
+                                dataStart + dataStringPointer, 3, UTC_BYTEARRAY)
+                                || byteArrayEqualToString(data, dataStart + dataStringPointer, 3, GMT_BYTEARRAY))) {
                             dataStringPointer += 3;
                         }
                         // parse timezone as +zz:zz or +zzzz
@@ -615,24 +621,24 @@
                     } else {
                         // do lookup from the zoneinfor database
                         int timezoneEndField = dataStringPointer;
-                        while (timezoneEndField < dataLength
-                                && ((data[dataStart + timezoneEndField] >= '0' && data[dataStart + timezoneEndField] <= '9')
-                                        || (data[dataStart + timezoneEndField] >= 'a' && data[dataStart
-                                                + timezoneEndField] <= 'z')
-                                        || (data[dataStart + timezoneEndField] >= 'A' && data[dataStart
-                                                + timezoneEndField] <= 'Z')
-                                        || data[dataStart + timezoneEndField] == '/' || data[dataStart
-                                        + timezoneEndField] == '_')) {
+                        while (timezoneEndField < dataLength && ((data[dataStart + timezoneEndField] >= '0'
+                                && data[dataStart + timezoneEndField] <= '9')
+                                || (data[dataStart + timezoneEndField] >= 'a'
+                                        && data[dataStart + timezoneEndField] <= 'z')
+                                || (data[dataStart + timezoneEndField] >= 'A'
+                                        && data[dataStart + timezoneEndField] <= 'Z')
+                                || data[dataStart + timezoneEndField] == '/'
+                                || data[dataStart + timezoneEndField] == '_')) {
                             timezoneEndField++;
                         }
-                        int searchIdx = binaryTimezoneIDSearch(data, dataStart + dataStringPointer, timezoneEndField
-                                - dataStringPointer);
+                        int searchIdx = binaryTimezoneIDSearch(data, dataStart + dataStringPointer,
+                                timezoneEndField - dataStringPointer);
                         if (searchIdx >= 0) {
                             timezone = TIMEZONE_OFFSETS[searchIdx];
                         } else {
-                            throw new AsterixTemporalTypeParseException("Unexpected timezone string: "
-                                    + new String(Arrays.copyOfRange(data, dataStart + dataStringPointer, dataStart
-                                            + timezoneEndField)));
+                            throw new AsterixTemporalTypeParseException(
+                                    "Unexpected timezone string: " + new String(Arrays.copyOfRange(data,
+                                            dataStart + dataStringPointer, dataStart + timezoneEndField)));
                         }
                         dataStringPointer = timezoneEndField;
                     }
@@ -650,9 +656,9 @@
                                 hour = 0;
                             }
                         } else {
-                            throw new AsterixTemporalTypeParseException("Unexpected string for AM/PM marker "
-                                    + new String(Arrays.copyOfRange(data, dataStart + dataStringPointer, dataStart
-                                            + dataStringPointer + 2)));
+                            throw new AsterixTemporalTypeParseException(
+                                    "Unexpected string for AM/PM marker " + new String(Arrays.copyOfRange(data,
+                                            dataStart + dataStringPointer, dataStart + dataStringPointer + 2)));
                         }
                         dataStringPointer += 2;
                     } else {
@@ -662,15 +668,17 @@
                 case SKIPPER:
                     // just skip all continuous character and numbers
                     while ((data[dataStart + dataStringPointer] >= 'a' && data[dataStart + dataStringPointer] <= 'z')
-                            || (data[dataStart + dataStringPointer] >= 'A' && data[dataStart + dataStringPointer] <= 'Z')
-                            || (data[dataStart + dataStringPointer] >= '0' && data[dataStart + dataStringPointer] <= '9')) {
+                            || (data[dataStart + dataStringPointer] >= 'A'
+                                    && data[dataStart + dataStringPointer] <= 'Z')
+                            || (data[dataStart + dataStringPointer] >= '0'
+                                    && data[dataStart + dataStringPointer] <= '9')) {
                         dataStringPointer++;
                     }
                     break;
                 case SEPARATOR:
                     if (separatorChar == '\0') {
-                        throw new AsterixTemporalTypeParseException("Incorrect separator char in date string as "
-                                + data[dataStart + dataStringPointer]);
+                        throw new AsterixTemporalTypeParseException(
+                                "Incorrect separator char in date string as " + data[dataStart + dataStringPointer]);
                     }
                     for (int i = 0; i < formatCharCopies; i++) {
                         if (data[dataStart + dataStringPointer] != separatorChar) {
@@ -822,8 +830,8 @@
                     break;
 
                 default:
-                    throw new HyracksDataException("Unexpected format string at " + (formatStart + formatPointer)
-                            + ": " + format[formatStart + formatPointer]);
+                    throw new HyracksDataException("Unexpected format string at " + (formatStart + formatPointer) + ": "
+                            + format[formatStart + formatPointer]);
             }
 
             // check whether the process state is valid for the parse mode
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DurationArithmeticOperations.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DurationArithmeticOperations.java
index 404bf42..2e32378 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DurationArithmeticOperations.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DurationArithmeticOperations.java
@@ -23,18 +23,24 @@
  */
 public class DurationArithmeticOperations {
 
-    private final static GregorianCalendarSystem calSystem = GregorianCalendarSystem.getInstance();
+    private static final GregorianCalendarSystem GREG_CAL = GregorianCalendarSystem.getInstance();
+
+    private DurationArithmeticOperations() {
+    }
 
     /**
      * Add a duration (with yearMonth and dayTime) onto a time point. The algorithm works as described in
      * <a
      * href="http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes">"XML: adding durations to dateTimes"</a>.
      * <p/>
-     * The basic algorithm is like this: duration is applied to the time point as two separated fields: year-month field and day-time field. Year-month field is applied firstly by reserving the correct day within the month's range (for example add 1M to 03-31 will return 04-30). Then day-time field is applied.
+     * The basic algorithm is like this: duration is applied to the time point as two separated fields: year-month
+     * field and day-time field. Year-month field is applied firstly by reserving the correct day within the month's
+     * range (for example add 1M to 03-31 will return 04-30). Then day-time field is applied.
      * <p/>
      *
      * @param pointChronon
-     *            The time instance where the duration will be added, represented as the milliseconds since the anchored time (00:00:00 for time type, 1970-01-01T00:00:00Z for datetime and date types).
+     *            The time instance where the duration will be added, represented as the milliseconds since the
+     *            anchored time (00:00:00 for time type, 1970-01-01T00:00:00Z for datetime and date types).
      * @param yearMonthDuration
      *            The year-month-duration to be added
      * @param dayTimeDuration
@@ -54,19 +60,19 @@
             return rtnChronon;
         }
 
-        int year = calSystem.getYear(pointChronon);
-        int month = calSystem.getMonthOfYear(pointChronon, year);
-        int day = calSystem.getDayOfMonthYear(pointChronon, year, month);
-        int hour = calSystem.getHourOfDay(pointChronon);
-        int min = calSystem.getMinOfHour(pointChronon);
-        int sec = calSystem.getSecOfMin(pointChronon);
-        int ms = calSystem.getMillisOfSec(pointChronon);
+        int year = GREG_CAL.getYear(pointChronon);
+        int month = GREG_CAL.getMonthOfYear(pointChronon, year);
+        int day = GREG_CAL.getDayOfMonthYear(pointChronon, year, month);
+        int hour = GREG_CAL.getHourOfDay(pointChronon);
+        int min = GREG_CAL.getMinOfHour(pointChronon);
+        int sec = GREG_CAL.getSecOfMin(pointChronon);
+        int ms = GREG_CAL.getMillisOfSec(pointChronon);
 
         // Apply the year-month duration
         int carry = yearMonthDuration / 12;
         month += (yearMonthDuration % 12);
 
-        if (month < 0) {
+        if (month < 1) {
             month += 12;
             carry -= 1;
         } else if (month > 12) {
@@ -76,7 +82,7 @@
 
         year += carry;
 
-        boolean isLeapYear = calSystem.isLeapYear(year);
+        boolean isLeapYear = GREG_CAL.isLeapYear(year);
 
         if (isLeapYear) {
             if (day > GregorianCalendarSystem.DAYS_OF_MONTH_ORDI[month - 1]) {
@@ -88,7 +94,7 @@
             }
         }
 
-        return calSystem.getChronon(year, month, day, hour, min, sec, ms, 0) + dayTimeDuration;
+        return GREG_CAL.getChronon(year, month, day, hour, min, sec, ms, 0) + dayTimeDuration;
     }
 
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/temporal/OverlapBinsDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/temporal/OverlapBinsDescriptor.java
index 836408d..15229e2 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/temporal/OverlapBinsDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/temporal/OverlapBinsDescriptor.java
@@ -36,6 +36,7 @@
 import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
 import org.apache.asterix.om.functions.IFunctionDescriptor;
 import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.typecomputer.impl.ADateTypeComputer;
 import org.apache.asterix.om.types.AOrderedListType;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
@@ -95,7 +96,7 @@
                     private final ISerializerDeserializer<AInterval> intervalSerde = AqlSerializerDeserializerProvider.INSTANCE
                             .getSerializerDeserializer(BuiltinType.AINTERVAL);
 
-                    private final GregorianCalendarSystem GREG_CAL = GregorianCalendarSystem.getInstance();
+                    private final GregorianCalendarSystem gregCalSys = GregorianCalendarSystem.getInstance();
 
                     @Override
                     public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException {
@@ -109,13 +110,17 @@
 
                         ATypeTag type0 = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes0[offset0]);
 
-                        long intervalStart = 0, intervalEnd = 0;
+                        long intervalStart;
+                        long intervalEnd;
                         byte intervalTypeTag;
 
                         if (type0 == ATypeTag.INTERVAL) {
                             intervalStart = AIntervalSerializerDeserializer.getIntervalStart(bytes0, offset0 + 1);
                             intervalEnd = AIntervalSerializerDeserializer.getIntervalEnd(bytes0, offset0 + 1);
                             intervalTypeTag = AIntervalSerializerDeserializer.getIntervalTimeType(bytes0, offset0 + 1);
+                            if (intervalTypeTag == ATypeTag.SERIALIZED_DATE_TYPE_TAG) {
+                                intervalStart = intervalStart * GregorianCalendarSystem.CHRONON_OF_DAY;
+                            }
                         } else {
                             throw new AlgebricksException(getIdentifier().getName()
                                     + ": the first argument should be INTERVAL/NULL/MISSING but got " + type0);
@@ -130,7 +135,7 @@
                                     + type0 + "(" + intervalTypeTag + ") for the second argument but got " + type1);
                         }
 
-                        long anchorTime = 0;
+                        long anchorTime;
                         switch (type1) {
                             case DATE:
                                 anchorTime = ADateSerializerDeserializer.getChronon(bytes1, offset1 + 1)
@@ -160,10 +165,10 @@
                             case YEARMONTHDURATION:
                                 yearMonth = AYearMonthDurationSerializerDeserializer.getYearMonth(bytes2, offset2 + 1);
 
-                                int yearStart = GREG_CAL.getYear(anchorTime);
-                                int monthStart = GREG_CAL.getMonthOfYear(anchorTime, yearStart);
-                                int yearToBin = GREG_CAL.getYear(intervalStart);
-                                int monthToBin = GREG_CAL.getMonthOfYear(intervalStart, yearToBin);
+                                int yearStart = gregCalSys.getYear(anchorTime);
+                                int monthStart = gregCalSys.getMonthOfYear(anchorTime, yearStart);
+                                int yearToBin = gregCalSys.getYear(intervalStart);
+                                int monthToBin = gregCalSys.getMonthOfYear(intervalStart, yearToBin);
 
                                 int totalMonths = (yearToBin - yearStart) * 12 + (monthToBin - monthStart);
 
@@ -195,7 +200,8 @@
                                         + type2);
                         }
 
-                        long binStartChronon, binEndChronon;
+                        long binStartChronon;
+                        long binEndChronon;
                         int binOffset;
 
                         listBuilder.reset(intListType);
@@ -302,9 +308,6 @@
         };
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.asterix.om.functions.AbstractFunctionDescriptor#getIdentifier()
-     */
     @Override
     public FunctionIdentifier getIdentifier() {
         return AsterixBuiltinFunctions.OVERLAP_BINS;