Refactored the ADateTime type:
- Added a new interface for calendar system;
- Added an implementation of the calendar system for the gregorian calendar system;
- Re-implemented the ADateTime type using a millisecond-based internal representation, which fixes issue 107;
- Implemented the comparison between ADateTime values based on the internal millisecond-based representation, so the comparison is processed between two long integers (Int64 eliminates the YEAR2038 problem). This fixes issue 106;
- ADateTime now is ISO8601-compatible;
- Updated test AQLs and their answers to have ISO8601-compatible representation of ADateTime values.
TODO:
- New issue: ADate and ATime should be updated to be ISO8601-compatible;
- More test cases.
git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_temporal_fixes@247 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-app/data/events/tiny/event.adm b/asterix-app/data/events/tiny/event.adm
index 21fd7e7..5e9d4b3 100644
--- a/asterix-app/data/events/tiny/event.adm
+++ b/asterix-app/data/events/tiny/event.adm
@@ -5,8 +5,8 @@
"sponsoring_sigs": [ { "sig_id": 14, "chapter_name": "San Clemente" },
{ "sig_id": 14, "chapter_name": "Laguna Beach" } ],
"interest_keywords": {{ "art", "landscape", "nature", "vernissage" }},
- "start_time": datetime( "2011-02-23T18:00:00:000-08:00" ),
- "end_time": datetime( "2011-02-23T21:00:00:000-08:00" )
+ "start_time": datetime( "2011-02-23T18:00:00.000-08:00" ),
+ "end_time": datetime( "2011-02-23T21:00:00.000-08:00" )
}
{
"event_id": 941,
@@ -16,8 +16,8 @@
"sponsoring_sigs": [ { "sig_id": 31, "chapter_name": "Huntington Beach" } ],
"interest_keywords": {{ "scuba", "diving", "aquatics" }},
"price": 40.00,
- "start_time": datetime( "2010-10-16T09:00:00:000-08:00" ),
- "end_time": datetime( "2010-10-16T12:00:00:000-08:00" )
+ "start_time": datetime( "2010-10-16T09:00:00.000-08:00" ),
+ "end_time": datetime( "2010-10-16T12:00:00.000-08:00" )
}
{
"event_id": 1042,
@@ -26,7 +26,7 @@
"sponsoring_sigs": [ { "sig_id": 14, "chapter_name": "Laguna Beach" } ],
"interest_keywords": {{ "architecture", "photography" }},
"price": 10.00,
- "start_time": datetime( "2011-02-23T17:00:00:000-08:00" ),
- "end_time": datetime( "2011-02-23T19:00:00:000-08:00" )
+ "start_time": datetime( "2011-02-23T17:00:00.000-08:00" ),
+ "end_time": datetime( "2011-02-23T19:00:00.000-08:00" )
}
\ No newline at end of file
diff --git a/asterix-app/data/nontagged/tempData.json b/asterix-app/data/nontagged/tempData.json
index 1fef3ab..dfcfa1e 100644
--- a/asterix-app/data/nontagged/tempData.json
+++ b/asterix-app/data/nontagged/tempData.json
@@ -1,2 +1,2 @@
-{ "id": 10, "date": date("2011-01-27"), "time": time("12:20:30"), "datetime": datetime("1951-12-27T12:20:30"), "duration": duration("D30Y10M15DT10H30M50S"), "date2": date("2011-01-27-05:00"), "time2": time("12:20:30:999-05:00"), "datetime2": datetime("1951-12-27T12:20:30:250-08:45"), "duration2": duration("D10M15DT10H50S"), "date3": date("-2011-01-27-05:00"), "time3": time("12:20:30:999Z"), "datetime3": datetime("-1951-12-27T12:20:30:250-08:15"), "duration3": duration("-DT50S"), "date4": date("-2011-01-27Z"), "time4": time("12:20:30Z"), "datetime4": datetime("-1951-12-27T12:20:30:250Z"), "duration4": duration("-D10M"), "date5": date("2011-01-27"), "time5": time("12:20:30"), "datetime5": datetime("1951-12-27T12:20:30"), "duration5": duration("D30Y10M15DT10H30M50S") }
+{ "id": 10, "date": date("2011-01-27"), "time": time("12:20:30"), "datetime": datetime("1951-12-27T12:20:30"), "duration": duration("D30Y10M15DT10H30M50S"), "date2": date("2011-01-27-05:00"), "time2": time("12:20:30:999-05:00"), "datetime2": datetime("1951-12-27T12:20:30.250-08:45"), "duration2": duration("D10M15DT10H50S"), "date3": date("-2011-01-27-05:00"), "time3": time("12:20:30:999Z"), "datetime3": datetime("-1951-12-27T12:20:30.250-08:15"), "duration3": duration("-DT50S"), "date4": date("-2011-01-27Z"), "time4": time("12:20:30Z"), "datetime4": datetime("-1951-12-27T12:20:30.250Z"), "duration4": duration("-D10M"), "date5": date("2011-01-27"), "time5": time("12:20:30"), "datetime5": datetime("1951-12-27T12:20:30"), "duration5": duration("D30Y10M15DT10H30M50S") }
diff --git a/asterix-app/src/test/resources/aqljts/results/nested_01.adm b/asterix-app/src/test/resources/aqljts/results/nested_01.adm
index 54444c7..27de5c0 100644
--- a/asterix-app/src/test/resources/aqljts/results/nested_01.adm
+++ b/asterix-app/src/test/resources/aqljts/results/nested_01.adm
@@ -30,4 +30,4 @@
ARecordType:
field: t
AbstractCollectionType:
-ADateTime: { 2011-9-16:11:0:0:0:0:0 }
+ADateTime: { 2011-09-16T11:00:00.000Z }
diff --git a/asterix-app/src/test/resources/runtimets/queries/constructor/datetime_01.aql b/asterix-app/src/test/resources/runtimets/queries/constructor/datetime_01.aql
index 611feff..8c29dac 100644
--- a/asterix-app/src/test/resources/runtimets/queries/constructor/datetime_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/constructor/datetime_01.aql
@@ -1,13 +1,15 @@
+drop dataverse test if exists;
+create dataverse test;
use dataverse test;
write output to nc1:"rttest/constructor_datetime_01.adm";
-let $c1 := datetime("2010-10-30T10:50:56:999+05:45")
-let $c2 := datetime("2010-10-30T10:30:56:250-10:00")
-let $c3 := datetime("1987-11-19T09:20:00:200")
+let $c1 := datetime("2010-10-30T10:50:56.999+05:45")
+let $c2 := datetime("2010-10-30T10:30:56.250-10:00")
+let $c3 := datetime("1987-11-19T09:20:00.200Z")
let $c4 := datetime("1987-11-19T10:50:56Z")
-let $c5 := datetime("-1987-11-19T10:50:56:099-05:30")
-let $c6 := datetime("-0001-11-19T10:50:56:719Z")
-let $c7 := datetime("1951-12-27T12:20:15")
+let $c5 := datetime("-1987-11-19T10:50:56.099-05:30")
+let $c6 := datetime("-0001-11-19T10:50:56.719Z")
+let $c7 := datetime("1951-12-27T12:20:15Z")
return {"datetime1": $c1, "datetime2": $c2, "datetime3": $c3, "datetime4": $c4, "datetime5": $c5, "datetime6": $c6, "datetime7": $c7}
diff --git a/asterix-app/src/test/resources/runtimets/results/comparison/datetime_order.adm b/asterix-app/src/test/resources/runtimets/results/comparison/datetime_order.adm
index 14f3ab1..63d22af 100644
--- a/asterix-app/src/test/resources/runtimets/results/comparison/datetime_order.adm
+++ b/asterix-app/src/test/resources/runtimets/results/comparison/datetime_order.adm
@@ -1,5 +1,5 @@
-datetime("2005-01-01T00:00:00:000+04:00")
-datetime("2012-01-01T00:00:00:000+00:00")
-datetime("2011-12-31T14:00:00:000-10:00")
-datetime("2011-12-31T13:00:00:000-11:00")
-datetime("2012-04-06T00:00:00:000+00:00")
+datetime("2004-12-31T20:00:00.000Z")
+datetime("2012-01-01T00:00:00.000Z")
+datetime("2012-01-01T00:00:00.000Z")
+datetime("2012-01-01T00:00:00.000Z")
+datetime("2012-04-06T00:00:00.000Z")
diff --git a/asterix-app/src/test/resources/runtimets/results/constructor/datetime_01.adm b/asterix-app/src/test/resources/runtimets/results/constructor/datetime_01.adm
index 30d2cdb..8f2dff0 100644
--- a/asterix-app/src/test/resources/runtimets/results/constructor/datetime_01.adm
+++ b/asterix-app/src/test/resources/runtimets/results/constructor/datetime_01.adm
@@ -1 +1 @@
-{ "datetime1": datetime("2010-10-30T10:50:56:980+05:45"), "datetime2": datetime("2010-10-30T10:30:56:240-10:00"), "datetime3": datetime("1987-11-19T09:20:00:200+00:00"), "datetime4": datetime("1987-11-19T10:50:56:000+00:00"), "datetime5": datetime("-1987-11-19T10:50:56:080-05:30"), "datetime6": datetime("-0001-11-19T10:50:56:700+00:00"), "datetime7": datetime("1951-12-27T12:20:15:000+00:00") }
+{ "datetime1": datetime("2010-10-30T05:05:56.999Z"), "datetime2": datetime("2010-10-30T20:30:56.250Z"), "datetime3": datetime("1987-11-19T09:20:00.200Z"), "datetime4": datetime("1987-11-19T10:50:56.000Z"), "datetime5": datetime("-1987-11-19T16:20:56.099Z"), "datetime6": datetime("-0001-11-19T10:50:56.719Z"), "datetime7": datetime("1951-12-27T12:20:15.000Z") }
diff --git a/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01.adm b/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01.adm
index 3fad2e3..206461c 100644
--- a/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01.adm
+++ b/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01.adm
@@ -1 +1 @@
-{ "id": 10, "name": "Nancy", "age": 32.5f, "salary": 12.0d, "married": true, "interests": {{ "reading", "writing" }}, "children": [ "Brad", "Scott" ], "address": { "number": 8389, "street": "Hill St.", "city": "Mountain View" }, "dob": date("-2011-01-27+00:00"), "time": time("12:20:30:000+00:00"), "datetime": datetime("-1951-12-27T12:20:30:000+00:00"), "duration": duration("D10Y11M12DT10H50M30S"), "location2d": point("41.0,44.0"), "location3d": point3d("44.0,13.0,41.0"), "line": line("10.1,11.1 10.2,11.2"), "polygon": polygon("1.2,1.3 2.1,2.5 3.5,3.6 4.6,4.8"), "circle": circle("10.1,11.1 10.2") }
+{ "id": 10, "name": "Nancy", "age": 32.5f, "salary": 12.0d, "married": true, "interests": {{ "reading", "writing" }}, "children": [ "Brad", "Scott" ], "address": { "number": 8389, "street": "Hill St.", "city": "Mountain View" }, "dob": date("-2011-01-27+00:00"), "time": time("12:20:30:000+00:00"), "datetime": datetime("-1951-12-27T12:20:30.000Z"), "duration": duration("D10Y11M12DT10H50M30S"), "location2d": point("41.0,44.0"), "location3d": point3d("44.0,13.0,41.0"), "line": line("10.1,11.1 10.2,11.2"), "polygon": polygon("1.2,1.3 2.1,2.5 3.5,3.6 4.6,4.8"), "circle": circle("10.1,11.1 10.2") }
diff --git a/asterix-app/src/test/resources/runtimets/results/scan/temp_types_01.adm b/asterix-app/src/test/resources/runtimets/results/scan/temp_types_01.adm
index 013a0cb..05a81df 100644
--- a/asterix-app/src/test/resources/runtimets/results/scan/temp_types_01.adm
+++ b/asterix-app/src/test/resources/runtimets/results/scan/temp_types_01.adm
@@ -1 +1 @@
-{ "id": 10, "date": date("2011-01-27+00:00"), "time": time("12:20:30:000+00:00"), "datetime": datetime("1951-12-27T12:20:30:000+00:00"), "duration": duration("D30Y10M15DT10H30M50S"), "date2": date("2011-01-27-05:00"), "time2": time("12:20:30:980-05:00"), "datetime2": datetime("1951-12-27T12:20:30:240-08:45"), "duration2": duration("D0Y10M15DT10H0M50S"), "date3": date("-2011-01-27-05:00"), "time3": time("12:20:30:980+00:00"), "datetime3": datetime("-1951-12-27T12:20:30:240-08:15"), "duration3": duration("-D0Y0M0DT0H0M50S"), "date4": date("-2011-01-27+00:00"), "time4": time("12:20:30:000+00:00"), "datetime4": datetime("-1951-12-27T12:20:30:240+00:00"), "duration4": duration("-D0Y10M0DT0H0M0S"), "date5": date("2011-01-27+00:00"), "time5": time("12:20:30:000+00:00"), "datetime5": datetime("1951-12-27T12:20:30:000+00:00"), "duration5": duration("D30Y10M15DT10H30M50S") }
\ No newline at end of file
+{ "id": 10, "date": date("2011-01-27+00:00"), "time": time("12:20:30:000+00:00"), "datetime": datetime("1951-12-27T12:20:30.000Z"), "duration": duration("D30Y10M15DT10H30M50S"), "date2": date("2011-01-27-05:00"), "time2": time("12:20:30:980-05:00"), "datetime2": datetime("1951-12-27T21:05:30.250Z"), "duration2": duration("D0Y10M15DT10H0M50S"), "date3": date("-2011-01-27-05:00"), "time3": time("12:20:30:980+00:00"), "datetime3": datetime("-1951-12-27T20:35:30.250Z"), "duration3": duration("-D0Y0M0DT0H0M50S"), "date4": date("-2011-01-27+00:00"), "time4": time("12:20:30:000+00:00"), "datetime4": datetime("-1951-12-27T12:20:30.250Z"), "duration4": duration("-D0Y10M0DT0H0M0S"), "date5": date("2011-01-27+00:00"), "time5": time("12:20:30:000+00:00"), "datetime5": datetime("1951-12-27T12:20:30.000Z"), "duration5": duration("D30Y10M15DT10H30M50S") }
\ No newline at end of file
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/ADateTimeAscBinaryComparatorFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/ADateTimeAscBinaryComparatorFactory.java
index b62c21a..2dd8785 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/ADateTimeAscBinaryComparatorFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/comparators/ADateTimeAscBinaryComparatorFactory.java
@@ -1,6 +1,5 @@
package edu.uci.ics.asterix.dataflow.data.nontagged.comparators;
-import edu.uci.ics.asterix.om.base.AMutableDateTime;
import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparator;
import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
@@ -15,41 +14,27 @@
@Override
public IBinaryComparator createBinaryComparator() {
return new IBinaryComparator() {
-
- private AMutableDateTime dt1 = new AMutableDateTime(0, 0, 0, 0, 0, 0, 0, 0, 0);
- private AMutableDateTime dt2 = new AMutableDateTime(0, 0, 0, 0, 0, 0, 0, 0, 0);
@Override
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
- short year = (short) (((b1[s1] & 0xff) << 8) | b1[s1 + 1] & 0xff);
- int time = ((b1[s1 + 4] & 0xff) << 24) | ((b1[s1 + 5] & 0xff) << 16) | ((b1[s1 + 6] & 0xff) << 8)
- | (b1[s1 + 7] & 0xff);
- dt1.setValue(year >> 1, // year
- (year & 0x0001) * 8 + ((b1[s1 + 2] >>> 5) & 0x07), // month
- b1[s1 + 2] & 0x1f, // day
- (short) ((time) * 20 % 216000000 / 3600000), // hour
- (short) ((time) * 20 % 3600000 / 60000), // minutes
- (short) ((time) * 20 % 60000 / 1000), // seconds
- (short) ((time) * 20 % 1000), // milliseconds
- 0, // microseconds
- b1[s1 + 3]); // timezone
+ long chrononTime1 = getLong(b1, s1);
+ long chrononTime2 = getLong(b2, s2);
- year = (short) (((b2[s2] & 0xff) << 8) | b2[s2 + 1] & 0xff);
- time = ((b2[s2 + 4] & 0xff) << 24) | ((b2[s2 + 5] & 0xff) << 16) | ((b2[s2 + 6] & 0xff) << 8)
- | (b2[s2 + 7] & 0xff);
+ if (chrononTime1 > chrononTime2) {
+ return 1;
+ } else if (chrononTime1 < chrononTime2) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
- dt2.setValue(year >> 1, // year
- (year & 0x0001) * 8 + ((b2[s2 + 2] >>> 5) & 0x07), // month
- b2[s2 + 2] & 0x1f, // day
- (short) ((time) * 20 % 216000000 / 3600000), // hour
- (short) ((time) * 20 % 3600000 / 60000), // minutes
- (short) ((time) * 20 % 60000 / 1000), // seconds
- (short) ((time) * 20 % 1000), // milliseconds
- 0, // microseconds
- b2[s2 + 3]); // timezone
-
- return dt1.compare(dt2);
+ private long getLong(byte[] bytes, int start) {
+ return (((long) (bytes[start] & 0xff)) << 56) + (((long) (bytes[start + 1] & 0xff)) << 48)
+ + (((long) (bytes[start + 2] & 0xff)) << 40) + (((long) (bytes[start + 3] & 0xff)) << 32)
+ + (((long) (bytes[start + 4] & 0xff)) << 24) + (((long) (bytes[start + 5] & 0xff)) << 16)
+ + (((long) (bytes[start + 6] & 0xff)) << 8) + (((long) (bytes[start + 7] & 0xff)) << 0);
}
};
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
index e3999f1..5fd6905 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/printers/ADateTimePrinter.java
@@ -1,13 +1,11 @@
package edu.uci.ics.asterix.dataflow.data.nontagged.printers;
-import java.io.IOException;
import java.io.PrintStream;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import edu.uci.ics.asterix.om.base.temporal.GregorianCalendarSystem;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.data.IPrinter;
-import edu.uci.ics.hyracks.algebricks.data.utils.WriteValueTools;
public class ADateTimePrinter implements IPrinter {
@@ -21,49 +19,64 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- int year = AInt16SerializerDeserializer.getShort(b, s + 1) >> 1;
- int month = (AInt16SerializerDeserializer.getShort(b, s + 1) & 0x0001) * 8 + ((b[s + 3] >> 5) & 0x07);
+ long chrononTime = AInt64SerializerDeserializer.getLong(b, s + 1);
- int day = b[s + 3] & 0x1f;
- byte timezone = b[s + 4];
+ GregorianCalendarSystem calendar = GregorianCalendarSystem.getInstance();
- int time = AInt32SerializerDeserializer.getInt(b, s + 5);
- // int msec = (time) * 20 % 1000;
- // int sec = (time) * 20 % 60000 / 1000;
- // int min = (time) * 20 % 3600000 / 60000;
- // int hour = (time) * 20 % 216000000 / 3600000;
+ int year = calendar.getYear(chrononTime);
+ int month = calendar.getMonthOfYear(chrononTime, year);
ps.print("datetime(\"");
- if (year < 0) {
- ps.print("-");
- }
- int y = Math.abs(year);
- if (y < 1000) {
- ps.print("0");
- }
- if (y < 100) {
- ps.print("0");
- }
- if (y < 10) {
- ps.print("0");
- }
- try {
- WriteValueTools.writeInt(y, ps);
- ps.print("-");
- if (month < 10) {
- ps.print("0");
- }
- WriteValueTools.writeInt(month, ps);
- ps.print("-");
- if (day < 10) {
- ps.print("0");
- }
- WriteValueTools.writeInt(day, ps);
- ps.print("T");
- } catch (IOException e) {
- throw new AlgebricksException(e);
- }
- ATimePrinter.printTime(time, timezone, ps);
+ ps.append(String.format(year < 0 ? "%05d" : "%04d", year)).append("-").append(String.format("%02d", month))
+ .append("-").append(String.format("%02d", calendar.getDayOfMonthYear(chrononTime, year, month)))
+ .append("T").append(String.format("%02d", calendar.getHourOfDay(chrononTime))).append(":")
+ .append(String.format("%02d", calendar.getMinOfHour(chrononTime))).append(":")
+ .append(String.format("%02d", calendar.getSecOfMin(chrononTime))).append(".")
+ .append(String.format("%03d", calendar.getMillisOfSec(chrononTime))).append("Z");
ps.print("\")");
+ // int year = AInt16SerializerDeserializer.getShort(b, s + 1) >> 1;
+ // int month = (AInt16SerializerDeserializer.getShort(b, s + 1) & 0x0001) * 8 + ((b[s + 3] >> 5) & 0x07);
+ //
+ // int day = b[s + 3] & 0x1f;
+ // byte timezone = b[s + 4];
+ //
+ // int time = AInt32SerializerDeserializer.getInt(b, s + 5);
+ // // int msec = (time) * 20 % 1000;
+ // // int sec = (time) * 20 % 60000 / 1000;
+ // // int min = (time) * 20 % 3600000 / 60000;
+ // // int hour = (time) * 20 % 216000000 / 3600000;
+ //
+ // ps.print("datetime(\"");
+ // if (year < 0) {
+ // ps.print("-");
+ // }
+ // int y = Math.abs(year);
+ // if (y < 1000) {
+ // ps.print("0");
+ // }
+ // if (y < 100) {
+ // ps.print("0");
+ // }
+ // if (y < 10) {
+ // ps.print("0");
+ // }
+ // try {
+ // WriteValueTools.writeInt(y, ps);
+ // ps.print("-");
+ // if (month < 10) {
+ // ps.print("0");
+ // }
+ // WriteValueTools.writeInt(month, ps);
+ // ps.print("-");
+ // if (day < 10) {
+ // ps.print("0");
+ // }
+ // WriteValueTools.writeInt(day, ps);
+ // ps.print("T");
+ // } catch (IOException e) {
+ // throw new AlgebricksException(e);
+ // }
+ // ATimePrinter.printTime(time, timezone, ps);
+ // ps.print("\")");
}
}
\ No newline at end of file
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/ADateTimeSerializerDeserializer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/ADateTimeSerializerDeserializer.java
index c22da77..75194c6 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/ADateTimeSerializerDeserializer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/nontagged/serde/ADateTimeSerializerDeserializer.java
@@ -7,6 +7,7 @@
import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
import edu.uci.ics.asterix.om.base.ADateTime;
import edu.uci.ics.asterix.om.base.AMutableDateTime;
+import edu.uci.ics.asterix.om.base.temporal.GregorianCalendarSystem;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
@@ -19,13 +20,9 @@
@SuppressWarnings("unchecked")
private static ISerializerDeserializer<ADateTime> datetimeSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.ADATETIME);
- private static AMutableDateTime aDateTime = new AMutableDateTime(0, 0, 0, 0, 0, 0, 0, 0, 0);
- private static String errorMessage = " can not be an instance of datetime";
+ private static AMutableDateTime aDateTime = new AMutableDateTime(0L);
- private int time;
- private byte timezone;
- private short year;
- private byte monthAndDay;
+ private long chrononTime;
private ADateTimeSerializerDeserializer() {
}
@@ -33,14 +30,9 @@
@Override
public ADateTime deserialize(DataInput in) throws HyracksDataException {
try {
- year = in.readShort();
- monthAndDay = in.readByte();
- timezone = in.readByte();
- time = in.readInt();
+ chrononTime = in.readLong();
- return new ADateTime(year >> 1, (year & 0x0001) * 8 + ((monthAndDay >> 5) & 0x07), monthAndDay & 0x1f,
- (short) ((time) * 20 % 216000000 / 3600000), (short) ((time) * 20 % 3600000 / 60000),
- (short) ((time) * 20 % 60000 / 1000), (short) ((time) * 20 % 1000), (short) 0, timezone);
+ return new ADateTime(chrononTime);
} catch (IOException e) {
throw new HyracksDataException(e);
}
@@ -49,92 +41,14 @@
@Override
public void serialize(ADateTime instance, DataOutput out) throws HyracksDataException {
try {
- out.writeByte((byte) ((instance.getYear() << 1) >> 8));
- out.writeByte((byte) ((byte) ((instance.getYear() << 1) & 0x00ff) + (byte) (instance.getMonth() >> 3)));
- out.writeByte((byte) ((instance.getMonth() << 5) | (instance.getDay())));
- out.writeByte((byte) instance.getTimeZone());
- out.writeInt((((((instance.getHours() * 60) + instance.getMinutes()) * 60) + instance.getSeconds()) * 1000 + instance
- .getMilliseconds()) / 20);
+ out.writeLong(instance.getChrnonoTime());
} catch (IOException e) {
throw new HyracksDataException(e);
}
}
public static void parse(String datetime, DataOutput out) throws HyracksDataException {
- boolean positive = true;
- int offset = 0;
- byte timezonePart = 0;
-
- if (datetime.charAt(offset) == '-') {
- offset++;
- positive = false;
- }
-
- if (datetime.charAt(offset + 4) != '-' || datetime.charAt(offset + 7) != '-')
- throw new HyracksDataException(datetime + errorMessage);
-
- short year = Short.parseShort(datetime.substring(offset, offset + 4));
- short month = Short.parseShort(datetime.substring(offset + 5, offset + 7));
- short day = Short.parseShort(datetime.substring(offset + 8, offset + 10));
-
- if (year < 0 || year > 9999 || month < 0 || month > 12 || day < 0 || day > 31)
- throw new HyracksDataException(datetime + errorMessage);
-
- if (!positive)
- year *= -1;
-
- if (datetime.charAt(offset + 10) != 'T')
- throw new HyracksDataException(datetime + errorMessage);
-
- offset += 11;
-
- if (datetime.charAt(offset + 2) != ':' || datetime.charAt(offset + 5) != ':')
- throw new HyracksDataException(datetime + errorMessage);
-
- short hour = Short.parseShort(datetime.substring(offset, offset + 2));
- short minute = Short.parseShort(datetime.substring(offset + 3, offset + 5));
- short second = Short.parseShort(datetime.substring(offset + 6, offset + 8));
- short msecond = 0;
-
- if (datetime.length() > offset + 8 && datetime.charAt(offset + 8) == ':') {
- msecond = Short.parseShort(datetime.substring(offset + 9, offset + 12));
- if (hour < 0 || hour > 24 || minute < 0 || minute > 59 || second < 0 || second > 59 || msecond < 0
- || msecond > 999 || (hour == 24 && (minute != 0 || second != 0 || msecond != 0)))
- throw new HyracksDataException(datetime + errorMessage);
- offset += 12;
- } else {
- if (hour < 0 || hour > 24 || minute < 0 || minute > 59 || second < 0 || second > 59
- || (hour == 24 && (minute != 0 || second != 0)))
- throw new HyracksDataException(datetime + errorMessage);
- offset += 8;
- }
-
- short timezoneHour = 0, timezoneMinute = 0;
- if (datetime.length() > offset) {
- if (datetime.charAt(offset) == 'Z')
- timezonePart = 0;
- else {
- if ((datetime.charAt(offset) != '+' && datetime.charAt(offset) != '-')
- || (datetime.charAt(offset + 3) != ':'))
- throw new HyracksDataException(datetime + errorMessage);
-
- timezoneHour = Short.parseShort(datetime.substring(offset + 1, offset + 3));
- timezoneMinute = Short.parseShort(datetime.substring(offset + 4, offset + 6));
-
- if (timezoneHour < 0
- || timezoneHour > 24
- || (timezoneHour == 24 && timezoneMinute != 0)
- || (timezoneMinute != 0 && timezoneMinute != 15 && timezoneMinute != 30 && timezoneMinute != 45))
- throw new HyracksDataException(datetime + errorMessage);
-
- if (datetime.charAt(offset) == '-')
- timezonePart = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
- else
- timezonePart = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
- }
-
- }
- aDateTime.setValue(year, month, day, hour, minute, second, msecond, 0, timezonePart);
+ GregorianCalendarSystem.getInstance().parseStringForADatetime(datetime, aDateTime);
datetimeSerde.serialize(aDateTime, out);
}
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/ADateTime.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/ADateTime.java
index e300d78..47ce492 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/ADateTime.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/ADateTime.java
@@ -1,73 +1,17 @@
package edu.uci.ics.asterix.om.base;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.base.temporal.GregorianCalendarSystem;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.asterix.om.visitors.IOMVisitor;
public class ADateTime implements IAObject {
- private static final int[] NUM_DAYS_IN_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ protected long chrononTime;
- protected int day;
- protected int hour;
- protected int minutes;
- protected int month;
- protected int seconds;
- protected int timezone;
- protected int year;
- protected int milliseconds;
- protected int microseconds;
-
- public ADateTime(int year, int month, int day, int hour, int minutes, int seconds, int timezone) {
- this.year = year;
- this.month = month;
- this.day = day;
- this.hour = hour;
- this.minutes = minutes;
- this.seconds = seconds;
- this.timezone = timezone;
- }
-
- public ADateTime(int year, int month, int day, int hour, int minutes, int seconds, int milliseconds,
- int microseconds, int timezone) {
- this.year = year;
- this.month = month;
- this.day = day;
- this.hour = hour;
- this.minutes = minutes;
- this.seconds = seconds;
- this.milliseconds = milliseconds;
- this.microseconds = microseconds;
- this.timezone = timezone;
- }
-
- public int getDay() {
- return day;
- }
-
- public int getHours() {
- return hour;
- }
-
- public int getMinutes() {
- return minutes;
- }
-
- public int getMonth() {
- return month;
- }
-
- public int getSeconds() {
- return seconds;
- }
-
- public int getTimeZone() {
- return timezone;
- }
-
- public int getYear() {
- return year;
+ public ADateTime(long chrononTime) {
+ this.chrononTime = chrononTime;
}
@Override
@@ -75,125 +19,33 @@
return BuiltinType.ADATETIME;
}
- public int getMicroseconds() {
- return microseconds;
- }
-
- public int getMilliseconds() {
- return milliseconds;
- }
-
public int compare(Object o) {
if (!(o instanceof ADateTime)) {
return -1;
}
ADateTime d = (ADateTime) o;
- if (timezone != d.getTimeZone()) {
- AMutableDateTime dt1 = new AMutableDateTime(year, month, day, hour, minutes, seconds, milliseconds,
- microseconds, timezone);
- AMutableDateTime dt2 = new AMutableDateTime(d.getYear(), d.getMonth(), d.getDay(), d.getHours(),
- d.getMinutes(), d.getSeconds(), d.getMilliseconds(), d.getMicroseconds(), d.getTimeZone());
- dt1.convertToUTC();
- dt2.convertToUTC();
-
- return dt1.tzEqualCompare(dt2);
-
- }
-
- return tzEqualCompare(d);
- }
-
- protected void convertToUTC() {
- short tzMin = (short) ((timezone % 4) * 15);
- short tzHr = (short) (timezone / 4);
- minutes -= tzMin;
- if (minutes >= 60) {
- minutes %= 60;
- hour += 1;
- }
- hour -= tzHr;
- if (hour >= 24) {
- hour %= 24;
- day += 1;
- }
- if (isLeapYear(year) && month == 2) {
- if (day >= 29) {
- day %= 29;
- month += 1;
- }
+ if (this.chrononTime > d.chrononTime) {
+ return 1;
+ } else if (this.chrononTime < d.chrononTime) {
+ return -1;
} else {
- if (day >= NUM_DAYS_IN_MONTH[month - 1]) {
- day %= NUM_DAYS_IN_MONTH[month - 1];
- month += 1;
- }
+ return 0;
}
-
- if (month >= 12) {
- month %= 12;
- year += 1;
- }
- timezone = 0;
-
- }
-
- protected static boolean isLeapYear(int year) {
- if (year % 400 == 0) {
- return true;
- } else if (year % 100 == 0) {
- return false;
- } else if (year % 4 == 0) {
- return true;
- } else {
- return false;
- }
- }
-
- // comparison that assumes the timezones are the same!
- protected int tzEqualCompare(ADateTime d) {
- if (year != d.getYear()) {
- return year - d.getYear();
- }
- if (month != d.getMonth()) {
- return month - d.getMonth();
- }
- if (day != d.getDay()) {
- return day - d.getDay();
- }
- if (hour != d.getHours()) {
- return hour - d.getHours();
- }
- if (minutes != d.getMinutes()) {
- return minutes - d.getMinutes();
- }
- if (seconds != d.getSeconds()) {
- return seconds - d.getSeconds();
- }
- if (milliseconds != d.getMilliseconds()) {
- return milliseconds - d.getMilliseconds();
- }
- if (microseconds != d.getMicroseconds()) {
- return microseconds - d.getMicroseconds();
- }
-
- return 0;
}
public boolean equals(Object o) {
if (!(o instanceof ADateTime)) {
return false;
} else {
- ADateTime d = (ADateTime) o;
- return d.getMicroseconds() == microseconds && d.getMilliseconds() == milliseconds
- && d.getSeconds() == seconds && d.getMinutes() == minutes && d.getHours() == hour
- && d.getDay() == day && d.getMonth() == month && d.getYear() == year && d.getTimeZone() == timezone;
+ ADateTime t = (ADateTime) o;
+ return t.chrononTime == this.chrononTime;
}
}
@Override
public int hashCode() {
- return (((((((year * 31 + month) * 31 + day) * 31 + timezone) * 31 + hour) * 31 + minutes) * 31 + seconds) * 31 + milliseconds)
- * 31 + microseconds;
+ return (int) (chrononTime ^ (chrononTime >>> 32));
}
@Override
@@ -213,8 +65,15 @@
@Override
public String toString() {
- return "ADateTime: { " + year + "-" + month + "-" + day + ":" + hour + ":" + minutes + ":" + seconds + ":"
- + milliseconds + ":" + microseconds + ":" + timezone + " }";
+ StringBuilder sbder = new StringBuilder();
+ sbder.append("ADateTime: { ");
+ GregorianCalendarSystem.getInstance().getStringRep(chrononTime, sbder);
+ sbder.append(" }");
+ return sbder.toString();
+ }
+
+ public long getChrnonoTime() {
+ return chrononTime;
}
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/AMutableDateTime.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/AMutableDateTime.java
index 01e30a2..88553b0 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/AMutableDateTime.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/AMutableDateTime.java
@@ -2,22 +2,12 @@
public class AMutableDateTime extends ADateTime {
- public AMutableDateTime(int year, int month, int day, int hour, int minutes, int seconds, int milliseconds,
- int microseconds, int timezone) {
- super(year, month, day, hour, minutes, seconds, milliseconds, microseconds, timezone);
+ public AMutableDateTime(long chrononTime) {
+ super(chrononTime);
}
- public void setValue(int year, int month, int day, int hour, int minutes, int seconds, int milliseconds,
- int microseconds, int timezone) {
- this.year = year;
- this.month = month;
- this.day = day;
- this.hour = hour;
- this.minutes = minutes;
- this.seconds = seconds;
- this.milliseconds = milliseconds;
- this.microseconds = microseconds;
- this.timezone = timezone;
+ public void setValue(long chrononTime) {
+ this.chrononTime = chrononTime;
}
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/GregorianCalendarSystem.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/GregorianCalendarSystem.java
new file mode 100644
index 0000000..707daaa
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/GregorianCalendarSystem.java
@@ -0,0 +1,783 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Joda API (http://joda-time.sourceforge.net/) is under the protection of:
+ *
+ * Copyright 2001-2005 Stephen Colebourne
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.om.base.temporal;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.om.base.AMutableDateTime;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+
+/**
+ * A simple implementation of the Gregorian calendar system.
+ * <p/>
+ */
+public class GregorianCalendarSystem implements ICalendarSystem {
+
+ private static final int[] DAYS_OF_MONTH_ORDI = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ private static final int[] DAYS_OF_MONTH_LEAP = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ private static final int[] DAYS_SINCE_MONTH_BEGIN_ORDI = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ private static final String ERROR_FORMAT = ": unrecognizable datetime format.";
+
+ private static final int CHRONON_OF_SECOND = 1000;
+ private static final int CHRONON_OF_MINUTE = 60 * CHRONON_OF_SECOND;
+ private static final int CHRONON_OF_HOUR = 60 * CHRONON_OF_MINUTE;
+ private static final long CHRONON_OF_DAY = 24 * CHRONON_OF_HOUR;
+
+ /**
+ * Minimum feasible value of each field
+ */
+ private static final int[] FIELD_MINS = { Integer.MIN_VALUE, // year
+ 1, // month
+ 1, // day
+ 0, // hour
+ 0, // minute
+ 0, // second
+ 0 // millisecond
+ };
+
+ private static final int[] FIELD_MAXS = { Integer.MAX_VALUE, // year
+ 12, // month
+ 31, // day
+ 23, // hour
+ 59, // minute
+ 59, // second
+ 999 // millisecond
+ };
+
+ /**
+ * From Joda API: GregorianChronology.java
+ */
+ private static final long CHRONON_OF_YEAR = (long) (365.2425 * CHRONON_OF_DAY);
+
+ /**
+ * From Joda API: GregorianChronology.java
+ */
+ private static final int DAYS_0000_TO_1970 = 719527;
+
+ private static final GregorianCalendarSystem instance = new GregorianCalendarSystem();
+
+ private GregorianCalendarSystem() {
+ }
+
+ public static GregorianCalendarSystem getInstance() {
+ return instance;
+ }
+
+ /**
+ * Check whether the given date time value is a valid date time following the gregorian calendar system.
+ *
+ * @param fields
+ * @return
+ */
+ public boolean validate(int year, int month, int day, int hour, int min, int sec, int millis) {
+ // Check whether each field is within the value domain
+ if (year < FIELD_MINS[0] || year > FIELD_MAXS[0])
+ return false;
+ if (month < FIELD_MINS[1] || month > FIELD_MAXS[1])
+ return false;
+ if (day < FIELD_MINS[2] || day > FIELD_MAXS[2])
+ return false;
+ if (hour < FIELD_MINS[3] || hour > FIELD_MAXS[3])
+ return false;
+ if (min < FIELD_MINS[4] || min > FIELD_MAXS[4])
+ return false;
+ if (sec < FIELD_MINS[5] || sec > FIELD_MAXS[5])
+ return false;
+ if (millis < FIELD_MINS[6] || millis > FIELD_MAXS[6])
+ return false;
+
+ // Check whether leap month.
+ if (month == 2)
+ if (isLeapYear(year)) {
+ if (month > DAYS_OF_MONTH_LEAP[1])
+ return false;
+ } else {
+ if (month > DAYS_OF_MONTH_ORDI[1])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check whether the given time zone value is a valid time zone following the gregorian calendar system.
+ *
+ * @param timezone
+ * @return
+ */
+ public boolean validateTimeZone(int timezone) {
+ short tzMin = (short) ((timezone % 4) * 15);
+
+ if (tzMin < -60 || tzMin >= 60) {
+ return false;
+ }
+
+ short tzHr = (short) (timezone / 4);
+
+ if (tzHr < -12 && tzHr > 14) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validate the given chronon time and time zone.
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @param hour
+ * @param min
+ * @param sec
+ * @param millis
+ * @param timezone
+ * @return
+ */
+ public boolean validate(int year, int month, int day, int hour, int min, int sec, int millis, int timezone) {
+ return validate(year, month, day, hour, min, sec, millis) && validateTimeZone(timezone);
+ }
+
+ /**
+ * Get the chronon time of the given date time and time zone.
+ *
+ * @param year
+ * @param month
+ * @param day
+ * @param hour
+ * @param min
+ * @param sec
+ * @param millis
+ * @param timezone
+ * @return
+ */
+ public long getChronon(int year, int month, int day, int hour, int min, int sec, int millis, int timezone) {
+ // Added milliseconds for all fields but month and day
+ long chrononTime = chrononizeBeginningOfYear(year) + (hour - timezone / 4) * CHRONON_OF_HOUR
+ + (min - (timezone % 4) * 15) * CHRONON_OF_MINUTE + sec * CHRONON_OF_SECOND + millis;
+
+ // Added milliseconds for days of the month.
+ chrononTime += (day - 1 + DAYS_SINCE_MONTH_BEGIN_ORDI[month - 1]) * CHRONON_OF_DAY;
+
+ // Adjust the leap year
+ if (month > 2 && isLeapYear(year)) {
+ chrononTime += CHRONON_OF_DAY;
+ }
+
+ return chrononTime;
+ }
+
+ /**
+ * Get the ISO8601 compatible representation of the given chronon time, using the extended form as<br/>
+ * [-]YYYY-MM-DDThh:mm:ss.xxx[+|-]hh:mm
+ */
+ @Override
+ public void getStringRep(long chrononTime, StringBuilder sbder) {
+ getExtendStringRepWithTimezone(chrononTime, 0, sbder);
+ }
+
+ public void getStringRep(long chrononTime, DataOutput out) throws IOException {
+ int year = getYear(chrononTime);
+ int month = getMonthOfYear(chrononTime, year);
+
+ out.writeUTF(String.format(year < 0 ? "%05d" : "%04d", year) + "-" + String.format("%02d", month) + "-"
+ + String.format("%02d", getDayOfMonthYear(chrononTime, year, month)) + "T"
+ + String.format("%02d", getHourOfDay(chrononTime)) + ":"
+ + String.format("%02d", getMinOfHour(chrononTime)) + ":"
+ + String.format("%02d", getSecOfMin(chrononTime)) + "."
+ + String.format("%03d", getMillisOfSec(chrononTime)) + "Z");
+ }
+
+ public void getExtendStringRepWithTimezone(long chrononTime, int timezone, StringBuilder sbder) {
+ int year = getYear(chrononTime);
+ int month = getMonthOfYear(chrononTime, year);
+
+ sbder.append(String.format(year < 0 ? "%05d" : "%04d", year)).append("-").append(String.format("%02d", month)).append("-")
+ .append(String.format("%02d", getDayOfMonthYear(chrononTime, year, month))).append("T")
+ .append(String.format("%02d", getHourOfDay(chrononTime))).append(":")
+ .append(String.format("%02d", getMinOfHour(chrononTime))).append(":")
+ .append(String.format("%02d", getSecOfMin(chrononTime))).append(".")
+ .append(String.format("%03d", getMillisOfSec(chrononTime)));
+
+ if (timezone == 0) {
+ sbder.append("Z");
+ } else {
+ short tzMin = (short) ((timezone % 4) * 15);
+ short tzHr = (short) (timezone / 4);
+ sbder.append((tzHr >= 0 ? "+" : "-")).append(String.format("%02d", (tzHr < 0 ? -tzHr : tzHr))).append(":")
+ .append(String.format("%02d", tzMin));
+ }
+ }
+
+ public void getBasicStringRepWithTimezone(long chrononTime, int timezone, StringBuilder sbder) {
+ int year = getYear(chrononTime);
+ int month = getMonthOfYear(chrononTime, year);
+
+ sbder.append(String.format(year < 0 ? "%05d" : "%04d", year)).append(String.format("%02d", month))
+ .append(String.format("%02d", getDayOfMonthYear(chrononTime, year, month))).append("T")
+ .append(String.format("%02d", getHourOfDay(chrononTime)))
+ .append(String.format("%02d", getMinOfHour(chrononTime)))
+ .append(String.format("%02d", getSecOfMin(chrononTime)))
+ .append(String.format("%03d", getMillisOfSec(chrononTime)));
+
+ if (timezone == 0) {
+ sbder.append("Z");
+ } else {
+ short tzMin = (short) ((timezone % 4) * 15);
+ short tzHr = (short) (timezone / 4);
+ sbder.append((tzHr >= 0 ? "+" : "-")).append(String.format("%02d", (tzHr < 0 ? -tzHr : tzHr)))
+ .append(String.format("%02d", tzMin));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see edu.uci.ics.asterix.om.base.temporal.ICalendarSystem#parseStringRep(java.lang.String, java.io.DataOutput)
+ */
+ @Override
+ public void parseStringRep(String datetime, DataOutput out) throws HyracksDataException {
+ int offset = 0;
+ int year, month, day, hour, min, sec, millis = 0;
+ int timezone = 0;
+ boolean positive = true;
+ if (datetime.contains(":")) {
+ // parse extended form
+ if (datetime.charAt(offset) == '-') {
+ offset++;
+ positive = false;
+ }
+
+ if (datetime.charAt(offset + 4) != '-' || datetime.charAt(offset + 7) != '-')
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ year = Short.parseShort(datetime.substring(offset, offset + 4));
+ month = Short.parseShort(datetime.substring(offset + 5, offset + 7));
+ day = Short.parseShort(datetime.substring(offset + 8, offset + 10));
+
+ if (!positive)
+ year *= -1;
+
+ offset += 11;
+
+ if (datetime.charAt(offset + 2) != ':' || datetime.charAt(offset + 5) != ':')
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ hour = Short.parseShort(datetime.substring(offset, offset + 2));
+ min = Short.parseShort(datetime.substring(offset + 3, offset + 5));
+ sec = Short.parseShort(datetime.substring(offset + 6, offset + 8));
+
+ offset += 8;
+ if (datetime.length() > offset && datetime.charAt(offset) == '.') {
+ millis = Short.parseShort(datetime.substring(offset + 1, offset + 4));
+ offset += 4;
+ }
+
+ if (datetime.length() > offset) {
+ if (datetime.charAt(offset) != 'Z') {
+ if ((datetime.charAt(offset) != '+' && datetime.charAt(offset) != '-')
+ || (datetime.charAt(offset + 3) != ':'))
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = Short.parseShort(datetime.substring(offset + 1, offset + 3));
+ short timezoneMinute = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+
+ if (datetime.charAt(offset) == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+
+ } else {
+ // parse basic form
+ if (datetime.charAt(offset) == '-') {
+ offset++;
+ positive = false;
+ }
+
+ year = Short.parseShort(datetime.substring(offset, offset + 4));
+ month = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+ day = Short.parseShort(datetime.substring(offset + 6, offset + 8));
+
+ if (!positive)
+ day *= -1;
+
+ offset += 9;
+
+ hour = Short.parseShort(datetime.substring(offset, offset + 2));
+ min = Short.parseShort(datetime.substring(offset + 2, offset + 4));
+ sec = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+
+ offset += 6;
+ if (datetime.length() > offset && datetime.charAt(offset) == '.') {
+ millis = Short.parseShort(datetime.substring(offset + 1, offset + 4));
+ offset += 4;
+ }
+
+ if (datetime.length() > offset) {
+ if (datetime.charAt(offset) != 'Z') {
+ if ((datetime.charAt(offset) != '+' && datetime.charAt(offset) != '-'))
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = Short.parseShort(datetime.substring(offset + 1, offset + 3));
+ short timezoneMinute = Short.parseShort(datetime.substring(offset + 3, offset + 5));
+
+ if (datetime.charAt(offset) == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+ }
+
+ if (!validate(year, month, day, hour, min, sec, millis, timezone)) {
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+ }
+
+ long chrononTime = getChronon(year, month, day, hour, min, sec, (int) millis, timezone);
+
+ try {
+ out.writeLong(chrononTime);
+ out.writeInt(timezone);
+ } catch (IOException e) {
+ throw new HyracksDataException(e.toString());
+ }
+ }
+
+ public void parseStringForADatetime(String datetime, AMutableDateTime aMutableDatetime) throws HyracksDataException {
+ int offset = 0;
+ int year, month, day, hour, min, sec, millis = 0;
+ int timezone = 0;
+ boolean positive = true;
+ if (datetime.contains(":")) {
+ // parse extended form
+ if (datetime.charAt(offset) == '-') {
+ offset++;
+ positive = false;
+ }
+
+ if (datetime.charAt(offset + 4) != '-' || datetime.charAt(offset + 7) != '-')
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ year = Short.parseShort(datetime.substring(offset, offset + 4));
+ month = Short.parseShort(datetime.substring(offset + 5, offset + 7));
+ day = Short.parseShort(datetime.substring(offset + 8, offset + 10));
+
+ if (!positive)
+ year *= -1;
+
+ offset += 11;
+
+ if (datetime.charAt(offset + 2) != ':' || datetime.charAt(offset + 5) != ':')
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ hour = Short.parseShort(datetime.substring(offset, offset + 2));
+ min = Short.parseShort(datetime.substring(offset + 3, offset + 5));
+ sec = Short.parseShort(datetime.substring(offset + 6, offset + 8));
+
+ offset += 8;
+ if (datetime.length() > offset && datetime.charAt(offset) == '.') {
+ millis = Short.parseShort(datetime.substring(offset + 1, offset + 4));
+ offset += 4;
+ }
+
+ if (datetime.length() > offset) {
+ if (datetime.charAt(offset) != 'Z') {
+ if ((datetime.charAt(offset) != '+' && datetime.charAt(offset) != '-')
+ || (datetime.charAt(offset + 3) != ':'))
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = Short.parseShort(datetime.substring(offset + 1, offset + 3));
+ short timezoneMinute = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+
+ if (datetime.charAt(offset) == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+
+ } else {
+ // parse basic form
+ if (datetime.charAt(offset) == '-') {
+ offset++;
+ positive = false;
+ }
+
+ year = Short.parseShort(datetime.substring(offset, offset + 4));
+ month = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+ day = Short.parseShort(datetime.substring(offset + 6, offset + 8));
+
+ if (!positive)
+ day *= -1;
+
+ offset += 9;
+
+ hour = Short.parseShort(datetime.substring(offset, offset + 2));
+ min = Short.parseShort(datetime.substring(offset + 2, offset + 4));
+ sec = Short.parseShort(datetime.substring(offset + 4, offset + 6));
+
+ offset += 6;
+ if (datetime.length() > offset && datetime.charAt(offset) == '.') {
+ millis = Short.parseShort(datetime.substring(offset + 1, offset + 4));
+ offset += 4;
+ }
+
+ if (datetime.length() > offset) {
+ if (datetime.charAt(offset) != 'Z') {
+ if ((datetime.charAt(offset) != '+' && datetime.charAt(offset) != '-'))
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = Short.parseShort(datetime.substring(offset + 1, offset + 3));
+ short timezoneMinute = Short.parseShort(datetime.substring(offset + 3, offset + 5));
+
+ if (datetime.charAt(offset) == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+ }
+
+ if (!validate(year, month, day, hour, min, sec, millis, timezone)) {
+ throw new HyracksDataException(datetime + ERROR_FORMAT);
+ }
+
+ aMutableDatetime.setValue(getChronon(year, month, day, hour, min, sec, (int) millis, timezone));
+ }
+
+ public void parseStringForADatetime(byte[] datetime, int offset, AMutableDateTime aMutableDatetime)
+ throws AlgebricksException {
+ int year, month, day, hour, min, sec, millis = 0;
+ int timezone = 0;
+ boolean positive = true;
+ boolean isExtendedForm = false;
+ if (datetime[offset + 13] == ':' || datetime[offset + 14] == ':') {
+ isExtendedForm = true;
+ }
+ if (isExtendedForm) {
+ // parse extended form
+ if (datetime[offset] == '-') {
+ offset++;
+ positive = false;
+ }
+
+ if (datetime[offset + 4] != '-' || datetime[offset + 7] != '-')
+ throw new AlgebricksException(datetime + ERROR_FORMAT);
+
+ year = getValue(datetime, offset, 4);
+ month = getValue(datetime, offset + 5, 2);
+ day = getValue(datetime, offset + 8, 2);
+
+ if (!positive)
+ year *= -1;
+
+ offset += 11;
+
+ if (datetime[offset + 2] != ':' || datetime[offset + 5] != ':')
+ throw new AlgebricksException(datetime + ERROR_FORMAT);
+
+ hour = getValue(datetime, offset, 2);
+ min = getValue(datetime, offset + 3, 2);
+ sec = getValue(datetime, offset + 6, 2);
+
+ offset += 8;
+ if (datetime.length > offset && datetime[offset] == '.') {
+ millis = getValue(datetime, offset + 1, 3);
+ offset += 4;
+ }
+
+ if (datetime.length > offset) {
+ if (datetime[offset] != 'Z') {
+ if ((datetime[offset] != '+' && datetime[offset] != '-') || (datetime[offset + 3] != ':'))
+ throw new AlgebricksException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = getValue(datetime, offset + 1, 2);
+ short timezoneMinute = getValue(datetime, offset + 4, 2);
+
+ if (datetime[offset] == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+
+ } else {
+ // parse basic form
+ if (datetime[offset] == '-') {
+ offset++;
+ positive = false;
+ }
+
+ year = getValue(datetime, offset, 4);
+ month = getValue(datetime, offset + 4, 2);
+ day = getValue(datetime, offset + 6, 2);
+
+ if (!positive)
+ day *= -1;
+
+ offset += 9;
+
+ hour = getValue(datetime, offset, 2);
+ min = getValue(datetime, offset + 2, 2);
+ sec = getValue(datetime, offset + 4, 2);
+
+ offset += 6;
+ if (datetime.length > offset && datetime[offset] == '.') {
+ millis = getValue(datetime, offset + 1, 3);
+ offset += 4;
+ }
+
+ if (datetime.length > offset) {
+ if (datetime[offset] != 'Z') {
+ if ((datetime[offset] != '+' && datetime[offset] != '-'))
+ throw new AlgebricksException(datetime + ERROR_FORMAT);
+
+ short timezoneHour = getValue(datetime, offset + 1, 2);
+ short timezoneMinute = getValue(datetime, offset + 3, 2);
+
+ if (datetime[offset] == '-')
+ timezone = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
+ else
+ timezone = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
+ }
+ }
+ }
+
+ if (!validate(year, month, day, hour, min, sec, millis, timezone)) {
+ throw new AlgebricksException(datetime + ERROR_FORMAT);
+ }
+
+ aMutableDatetime.setValue(getChronon(year, month, day, hour, min, sec, (int) millis, timezone));
+ }
+
+ private short getValue(byte[] b, int offset, int numberOfDigits) throws AlgebricksException {
+ short value = 0;
+ for (int i = 0; i < numberOfDigits; i++) {
+ if ((b[offset] >= '0' && b[offset] <= '9'))
+ value = (short) (value * 10 + b[offset++] - '0');
+ else
+ throw new AlgebricksException(ERROR_FORMAT);
+
+ }
+ return value;
+ }
+
+ /**
+ * Check whether a given year is a leap year.
+ *
+ * @param year
+ * @return
+ */
+ protected boolean isLeapYear(int year) {
+ return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
+ }
+
+ /**
+ * From Joda library GregorianChronology class: The basic calculation is
+ * (y / 4) - (y / 100) + (y / 400). <br/>
+ * Use y >> 2 ( (y + 3) >> 2 for negative y value) to replace y / 4 reveals eliminates two divisions.
+ *
+ * @param year
+ * @return
+ */
+ private long chrononizeBeginningOfYear(int year) {
+ int leapYears = year / 100;
+ if (year < 0) {
+ // From Joda library GregorianChronology class
+ // The basic calculation is (y / 4) - (y / 100) + (y / 400)
+ // Use (y + 3) >> 2 to replace y / 4 reveals eliminates two divisions.
+ leapYears = ((year + 3) >> 2) - leapYears + ((leapYears + 3) >> 2) - 1;
+ } else {
+ leapYears = (year >> 2) - leapYears + (leapYears >> 2);
+ if (isLeapYear(year)) {
+ leapYears--;
+ }
+ }
+ return (year * 365L + (leapYears - DAYS_0000_TO_1970)) * CHRONON_OF_DAY;
+ }
+
+ /**
+ * Get the year for the given chronon time.
+ * <p/>
+ * This code is directly from the Joda library BadicChronology.java.<br/>
+ * The original authers are Stephen Colebourne, Brain S O'Neill and Guy Allard, and modified by JArod Wen on May 7th, 2012.
+ *
+ * @param chrononTime
+ * @return
+ */
+ public int getYear(long chrononTime) {
+ // Get an initial estimate of the year, and the millis value that
+ // represents the start of that year. Then verify estimate and fix if
+ // necessary.
+
+ // Initial estimate uses values divided by two to avoid overflow.
+ long unitMillis = CHRONON_OF_YEAR / 2;
+ long i2 = (chrononTime >> 1) + (1970L * CHRONON_OF_YEAR) / 2;
+ if (i2 < 0) {
+ i2 = i2 - unitMillis + 1;
+ }
+ int year = (int) (i2 / unitMillis);
+
+ long yearStart = chrononizeBeginningOfYear(year);
+ long diff = chrononTime - yearStart;
+
+ if (diff < 0) {
+ year--;
+ } else if (diff >= CHRONON_OF_DAY * 365L) {
+ // One year may need to be added to fix estimate.
+ long oneYear;
+ if (isLeapYear(year)) {
+ oneYear = CHRONON_OF_DAY * 366L;
+ } else {
+ oneYear = CHRONON_OF_DAY * 365L;
+ }
+
+ yearStart += oneYear;
+
+ if (yearStart <= chrononTime) {
+ // Didn't go too far, so actually add one year.
+ year++;
+ }
+ }
+
+ return year;
+ }
+
+ /**
+ * Get the month of the year for the given chronon time and the year.
+ * <p/>
+ * This code is directly from the Joda library BasicGJChronology.java.<br/>
+ * The original authers are Stephen Colebourne, Brain S O'Neill and Guy Allard, and modified by JArod Wen on May 7th, 2012.
+ * <p/>
+ *
+ * @param millis
+ * @param year
+ * @return
+ */
+ public int getMonthOfYear(long millis, int year) {
+ // Perform a binary search to get the month. To make it go even faster,
+ // compare using ints instead of longs. The number of milliseconds per
+ // year exceeds the limit of a 32-bit int's capacity, so divide by
+ // 1024. No precision is lost (except time of day) since the number of
+ // milliseconds per day contains 1024 as a factor. After the division,
+ // the instant isn't measured in milliseconds, but in units of
+ // (128/125)seconds.
+
+ int i = (int) ((millis - chrononizeBeginningOfYear(year)) >> 10);
+
+ // There are 86400000 milliseconds per day, but divided by 1024 is
+ // 84375. There are 84375 (128/125)seconds per day.
+
+ return (isLeapYear(year)) ? ((i < 182 * 84375) ? ((i < 91 * 84375) ? ((i < 31 * 84375) ? 1
+ : (i < 60 * 84375) ? 2 : 3) : ((i < 121 * 84375) ? 4 : (i < 152 * 84375) ? 5 : 6))
+ : ((i < 274 * 84375) ? ((i < 213 * 84375) ? 7 : (i < 244 * 84375) ? 8 : 9) : ((i < 305 * 84375) ? 10
+ : (i < 335 * 84375) ? 11 : 12)))
+ : ((i < 181 * 84375) ? ((i < 90 * 84375) ? ((i < 31 * 84375) ? 1 : (i < 59 * 84375) ? 2 : 3)
+ : ((i < 120 * 84375) ? 4 : (i < 151 * 84375) ? 5 : 6))
+ : ((i < 273 * 84375) ? ((i < 212 * 84375) ? 7 : (i < 243 * 84375) ? 8 : 9)
+ : ((i < 304 * 84375) ? 10 : (i < 334 * 84375) ? 11 : 12)));
+ }
+
+ /**
+ * Get the day of the given month and year for the input chronon time.
+ * <p/>
+ * This function is directly from Joda Library BasicChronology.java.<br/>
+ * The original authers are Stephen Colebourne, Brain S O'Neill and Guy Allard, and modified by JArod Wen on May 7th, 2012.
+ * <p/>
+ *
+ * @param millis
+ * @param year
+ * @param month
+ * @return
+ */
+ public int getDayOfMonthYear(long millis, int year, int month) {
+ long dateMillis = chrononizeBeginningOfYear(year);
+ dateMillis += DAYS_SINCE_MONTH_BEGIN_ORDI[month - 1] * CHRONON_OF_DAY;
+ if (isLeapYear(year) && month > 2) {
+ dateMillis += CHRONON_OF_DAY;
+ }
+ return (int) ((millis - dateMillis) / CHRONON_OF_DAY) + 1;
+ }
+
+ public int getHourOfDay(long millis) {
+ int hour = (int) ((millis % CHRONON_OF_DAY) / CHRONON_OF_HOUR);
+
+ if (millis < 0) {
+ if (millis % CHRONON_OF_HOUR == 0) {
+ if (hour < 0) {
+ hour += 24;
+ }
+ } else {
+ hour += 23;
+ }
+ }
+ return hour;
+ }
+
+ public int getMinOfHour(long millis) {
+ int min = (int) ((millis % CHRONON_OF_HOUR) / CHRONON_OF_MINUTE);
+ if (millis < 0) {
+ if (millis % CHRONON_OF_MINUTE == 0) {
+ if (min < 0) {
+ min += 60;
+ }
+ } else {
+ min += 59;
+ }
+ }
+ return min;
+ }
+
+ public int getSecOfMin(long millis) {
+ int sec = (int) ((millis % CHRONON_OF_MINUTE) / CHRONON_OF_SECOND);
+ if (millis < 0) {
+ if (millis % CHRONON_OF_SECOND == 0) {
+ if (sec < 0) {
+ sec += 60;
+ }
+ } else {
+ sec += 59;
+ }
+ }
+ return sec;
+ }
+
+ public int getMillisOfSec(long millis) {
+ int ms = (int) (millis % CHRONON_OF_SECOND);
+ if (millis < 0 && ms < 0) {
+ ms += 1000;
+ }
+ return ms;
+ }
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/ICalendarSystem.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/ICalendarSystem.java
new file mode 100644
index 0000000..c6b7c84
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/base/temporal/ICalendarSystem.java
@@ -0,0 +1,20 @@
+package edu.uci.ics.asterix.om.base.temporal;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+
+public interface ICalendarSystem {
+
+ public boolean validate(int year, int month, int day, int hour, int min, int sec, int millis, int timezone);
+
+ public long getChronon(int year, int month, int day, int hour, int min, int sec, int millis, int timezone);
+
+ public void getStringRep(long chrononTime, StringBuilder sbder);
+
+ public void parseStringRep(String stringRep, DataOutput out) throws HyracksDataException;
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/constructors/ADateTimeConstructorDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/constructors/ADateTimeConstructorDescriptor.java
index a7efb16..f3fcc73 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/constructors/ADateTimeConstructorDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/constructors/ADateTimeConstructorDescriptor.java
@@ -8,6 +8,7 @@
import edu.uci.ics.asterix.om.base.ADateTime;
import edu.uci.ics.asterix.om.base.AMutableDateTime;
import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.base.temporal.GregorianCalendarSystem;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
@@ -42,11 +43,8 @@
private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
private IEvaluator eval = args[0].createEvaluator(outInput);
private int offset;
- private short hour, minute, second, msecond, year, month, day, timezoneHour, timezoneMinute, value;
- private byte timezonePart = 0;
- private boolean positive = true;
private String errorMessage = "This can not be an instance of datetime";
- private AMutableDateTime aDateTime = new AMutableDateTime(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ private AMutableDateTime aDateTime = new AMutableDateTime(0L);
@SuppressWarnings("unchecked")
private ISerializerDeserializer<ADateTime> datetimeSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.ADATETIME);
@@ -64,77 +62,8 @@
if (serString[0] == SER_STRING_TYPE_TAG) {
offset = 3;
- if (serString[offset] == '-') {
- offset++;
- positive = false;
- }
-
- if (serString[offset + 4] != '-' || serString[offset + 7] != '-')
- throw new AlgebricksException(errorMessage);
-
- year = getValue(serString, offset, 4);
- month = getValue(serString, offset + 5, 2);
- day = getValue(serString, offset + 8, 2);
-
- if (year < 0 || year > 9999 || month < 0 || month > 12 || day < 0 || day > 31)
- throw new AlgebricksException(errorMessage);
-
- if (!positive)
- year *= -1;
-
- if (serString[offset + 10] != 'T')
- throw new AlgebricksException(errorMessage);
-
- offset += 11;
-
- if (serString[offset + 2] != ':' || serString[offset + 5] != ':')
- throw new AlgebricksException(errorMessage);
-
- hour = getValue(serString, offset, 2);
- minute = getValue(serString, offset + 3, 2);
- second = getValue(serString, offset + 6, 2);
-
- msecond = 0;
- if (serString[offset + 8] == ':') {
- msecond = getValue(serString, offset + 9, 3);
- if (hour < 0 || hour > 24 || minute < 0 || minute > 59 || second < 0 || second > 59
- || msecond < 0 || msecond > 999
- || (hour == 24 && (minute != 0 || second != 0 || msecond != 0)))
- throw new AlgebricksException(errorMessage);
- offset += 12;
- } else {
- if (hour < 0 || hour > 24 || minute < 0 || minute > 59 || second < 0 || second > 59
- || (hour == 24 && (minute != 0 || second != 0)))
- throw new AlgebricksException(errorMessage);
- offset += 8;
- }
-
- if (outInput.getLength() > offset) {
- if (serString[offset] == 'Z')
- timezonePart = 0;
- else {
- if ((serString[offset] != '+' && serString[offset] != '-')
- || (serString[offset + 3] != ':'))
- throw new AlgebricksException(errorMessage);
-
- timezoneHour = getValue(serString, offset + 1, 2);
- timezoneMinute = getValue(serString, offset + 4, 2);
-
- if (timezoneHour < 0
- || timezoneHour > 24
- || (timezoneHour == 24 && timezoneMinute != 0)
- || (timezoneMinute != 0 && timezoneMinute != 15 && timezoneMinute != 30 && timezoneMinute != 45))
- throw new AlgebricksException(errorMessage);
-
- if (serString[offset] == '-')
- timezonePart = (byte) -((timezoneHour * 4) + timezoneMinute / 15);
- else
- timezonePart = (byte) ((timezoneHour * 4) + timezoneMinute / 15);
- }
-
- }
-
- aDateTime.setValue(year, month, day, hour, minute, second, msecond, 0, timezonePart);
+ GregorianCalendarSystem.getInstance().parseStringForADatetime(serString, offset,
+ aDateTime);
datetimeSerde.serialize(aDateTime, out);
} else if (serString[0] == SER_NULL_TYPE_TAG)
nullSerde.serialize(ANull.NULL, out);
@@ -144,18 +73,6 @@
throw new AlgebricksException(errorMessage);
}
}
-
- private short getValue(byte[] b, int offset, int numberOfDigits) throws AlgebricksException {
- value = 0;
- for (int i = 0; i < numberOfDigits; i++) {
- if ((b[offset] >= '0' && b[offset] <= '9'))
- value = (short) (value * 10 + b[offset++] - '0');
- else
- throw new AlgebricksException(errorMessage);
-
- }
- return value;
- }
};
}
};