ASTERIXDB-1635 Fix for overlap-bins start for dates.
Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/d4cbcb2f Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/d4cbcb2f Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/d4cbcb2f Branch: refs/heads/ecarm002/interval_join_merge Commit: d4cbcb2fe05649d02f12a0196eaa508cb5f7c623 Parents: 1df9a9c Author: Preston Carman <prest...@apache.org> Authored: Tue Sep 6 16:10:24 2016 -0700 Committer: Preston Carman <prest...@apache.org> Committed: Tue Sep 6 16:10:24 2016 -0700 ---------------------------------------------------------------------- .../overlap_bins/overlap_bins.1.query.aql | 2 +- .../overlap_bins/overlap_bins.3.query.sqlpp | 2 +- .../temporal/overlap_bins/overlap_bins.1.adm | 2 +- .../temporal/overlap_bins/overlap_bins.3.ast | 2 +- .../src/site/markdown/aql/functions.md | 9 +- .../om/base/temporal/DateTimeFormatUtils.java | 200 ++++++++++--------- .../temporal/DurationArithmeticOperations.java | 32 +-- .../temporal/OverlapBinsDescriptor.java | 25 ++- 8 files changed, 146 insertions(+), 128 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.1.query.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.1.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.1.query.aql index 8011ad6..bfb5527 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.1.query.aql +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/temporal/overlap_bins/overlap_bins.1.query.aql @@ -25,5 +25,5 @@ let $itv1 := interval(time("17:23:37"), time("18:30:21")) 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")) } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/overlap_bins/overlap_bins.3.query.sqlpp ---------------------------------------------------------------------- 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'))}; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/overlap_bins/overlap_bins.1.adm ---------------------------------------------------------------------- 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..14f6aae 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")) ] } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins/overlap_bins.3.ast ---------------------------------------------------------------------- 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 @@ RecordConstructor [ LiteralExpr [STRING] [1990-01-01] ] FunctionCall null.year-month-duration@1[ - LiteralExpr [STRING] [P20Y] + LiteralExpr [STRING] [P10Y] ] ] ) http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-doc/src/site/markdown/aql/functions.md ---------------------------------------------------------------------- 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 @@ See the [Allen's Relations](allens.html). 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 @@ See the [Allen's Relations](allens.html). 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")) ] } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java ---------------------------------------------------------------------- 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 @@ import org.apache.hyracks.api.exceptions.HyracksDataException; */ 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 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 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 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 @@ public class DateTimeFormatUtils { } // 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 @@ public class DateTimeFormatUtils { } }; - 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { } // 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { } // 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { } 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { 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 @@ public class DateTimeFormatUtils { 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 http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DurationArithmeticOperations.java ---------------------------------------------------------------------- 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 @@ package org.apache.asterix.om.base.temporal; */ 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 @@ public class DurationArithmeticOperations { 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 @@ public class DurationArithmeticOperations { 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 @@ public class DurationArithmeticOperations { } } - 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; } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/d4cbcb2f/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/temporal/OverlapBinsDescriptor.java ---------------------------------------------------------------------- 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.base.temporal.GregorianCalendarSystem; 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 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript 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 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript 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 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript + 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 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript 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 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript + type2); } - long binStartChronon, binEndChronon; + long binStartChronon; + long binEndChronon; int binOffset; listBuilder.reset(intListType); @@ -302,9 +308,6 @@ public class OverlapBinsDescriptor extends AbstractScalarFunctionDynamicDescript }; } - /* (non-Javadoc) - * @see org.apache.asterix.om.functions.AbstractFunctionDescriptor#getIdentifier() - */ @Override public FunctionIdentifier getIdentifier() { return AsterixBuiltinFunctions.OVERLAP_BINS;