You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2012/06/06 17:10:04 UTC
svn commit: r1346931 - in /jena/Scratch/AFS/Jena-Dev/trunk/src/dev:
JENA247_XSDDatimeTzBoundary.java xsddt/ xsddt/DT.java xsddt/XSDDateTime2.java
Author: andy
Date: Wed Jun 6 15:10:03 2012
New Revision: 1346931
URL: http://svn.apache.org/viewvc?rev=1346931&view=rev
Log: (empty)
Added:
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/DT.java
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/XSDDateTime2.java
Modified:
jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JENA247_XSDDatimeTzBoundary.java
Modified: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JENA247_XSDDatimeTzBoundary.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JENA247_XSDDatimeTzBoundary.java?rev=1346931&r1=1346930&r2=1346931&view=diff
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JENA247_XSDDatimeTzBoundary.java (original)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JENA247_XSDDatimeTzBoundary.java Wed Jun 6 15:10:03 2012
@@ -24,7 +24,11 @@ import java.util.Calendar ;
import java.util.Date ;
import java.util.TimeZone ;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime ;
+import dev.xsddt.DT ;
+import dev.xsddt.XSDDateTime2 ;
+
+import org.junit.Assert ;
+import org.junit.Test ;
/* from
@@ -47,10 +51,43 @@ with:
*/
public class JENA247_XSDDatimeTzBoundary {
+
public static void main(String ... argv) throws Exception
{
new JENA247_XSDDatimeTzBoundary().test() ;
}
+
+
+
+ @Test public void jtest()
+ {
+ // From TestTypeLiterals.testDateTime
+
+// // dateTime
+// Literal l1 = ResourceFactory.createTypedLiteral("1999-05-31T02:09:32Z", XSDDatatype.XSDdateTime);
+// System.out.println(l1.getValue()) ;
+// XSDDateTime xdt = (XSDDateTime)l1.getValue() ;
+//
+// //Calendar x = XSDDateTime2.convertCalendar() ;
+//
+// int x[] = new int[] {1999, 5, 31, 2, 9, 32, 0, 90, 0} ;
+// XSDDateTime2 xdt2 = new XSDDateTime2(x , 15) ;
+
+ XSDDateTime2 xdt = new DT("dateTime").parseValidated("1999-05-31T02:09:32Z") ;
+
+// Assert.assertEquals("dateTime data type", XSDDatatype.XSDdateTime, l1.getDatatype());
+// Assert.assertEquals("dateTime java type", XSDDateTime.class, l1.getValue().getClass());
+ Assert.assertEquals("dateTime value", 1999, xdt.getYears());
+ Assert.assertEquals("dateTime value", 5, xdt.getMonths());
+ Assert.assertEquals("dateTime value", 31, xdt.getDays());
+ Assert.assertEquals("dateTime value", 2, xdt.getHours());
+ Assert.assertEquals("dateTime value", 9, xdt.getMinutes());
+ Assert.assertEquals("dateTime value", 32, xdt.getFullSeconds());
+ //Assert.assertEquals("serialization", "1999-05-31T02:09:32Z", l1.getValue().toString());
+ Assert.assertEquals("serialization", "1999-05-31T02:09:32Z", xdt.toString());
+ }
+
+ /// -------------------------------
public static Date getDateFromPattern(String ts, String format, String timezoneid) throws Exception {
@@ -74,12 +111,12 @@ public class JENA247_XSDDatimeTzBoundary
- //@Test -- not a test (yet)
+ //@Test -- not a test (yet)XSDDateTime2
public void test() throws Exception {
String[] timezonelist = {
-// "GMT",
+ //"GMT",
"America/New_York",
-// "America/Chicago",
+ //"America/Chicago",
};
for (String timezoneid : timezonelist) {
@@ -115,7 +152,10 @@ public class JENA247_XSDDatimeTzBoundary
Calendar cal = Calendar.getInstance();
cal.setTimeZone(tz);
cal.setTime(dt);
- XSDDateTime xdt = new XSDDateTime(cal);
+
+ // ****** XSDDateTime2
+
+ XSDDateTime2 xdt = new XSDDateTime2(cal);
int offset = tz.getOffset(dt.getTime()) /( 60 * 60 * 1000);
int xhr = xdt.getHours();
int dhr = cal.get(Calendar.HOUR_OF_DAY);
@@ -131,6 +171,8 @@ public class JENA247_XSDDatimeTzBoundary
System.out.println();
}
}
+
+
}
Added: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/DT.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/DT.java?rev=1346931&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/DT.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/DT.java Wed Jun 6 15:10:03 2012
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 dev.xsddt;
+
+import com.hp.hpl.jena.datatypes.RDFDatatype;
+import com.hp.hpl.jena.datatypes.xsd.AbstractDateTime ;
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
+import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
+import com.hp.hpl.jena.graph.impl.LiteralLabel;
+
+/**
+ * Base class for all date/time/duration type representations.
+ * Includes support functions for parsing and comparing dates.
+ *
+ * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
+ * @version $Revision: 1.1 $ on $Date: 2009-06-29 08:55:58 $
+ */
+public class DT extends XSDDatatype {
+
+
+ @Override
+ public XSDDateTime2 parseValidated(String str) {
+ int len = str.length();
+ int[] date = new int[TOTAL_SIZE];
+ int[] timeZone = new int[2];
+
+ int end = indexOf (str, 0, len, 'T');
+
+ // both time and date
+ getDate(str, 0, end, date);
+ getTime(str, end+1, len, date, timeZone);
+
+ if ( date[utc]!=0 && date[utc]!='Z') {
+ AbstractDateTime.normalize(date, timeZone);
+ }
+ // XSDDateTime2************
+ return new XSDDateTime2(date, XSDDateTime.FULL_MASK);
+ }
+
+ /**
+ * Constructor
+ */
+ public DT(String typename) {
+ super(typename);
+ }
+
+ /**
+ * Compares two instances of values of the given datatype.
+ * This ignores lang tags and just uses the java.lang.Number
+ * equality.
+ */
+ @Override
+ public boolean isEqual(LiteralLabel value1, LiteralLabel value2) {
+ return value1.getValue().equals(value2.getValue());
+ }
+
+ /** Mask to indicate whether year is present */
+ public static final short YEAR_MASK = 0x1;
+
+ /** Mask to indicate whether month is present */
+ public static final short MONTH_MASK = 0x2;
+
+ /** Mask to indicate whether day is present */
+ public static final short DAY_MASK = 0x4;
+
+ /** Mask to indicate whether time is present */
+ public static final short TIME_MASK = 0x8;
+
+ /** Mask to indicate all date/time are present */
+ public static final short FULL_MASK = 0xf;
+
+
+// --------------------------------------------------------------------
+// This code is adapated from Xerces 2.6.0 AbstractDateTimeDV.
+// Copyright (c) 1999-2003 The Apache Software Foundation. All rights
+// reserved.
+// --------------------------------------------------------------------
+
+ //define constants
+ protected final static int CY = 0, M = 1, D = 2, h = 3,
+ m = 4, s = 5, ms = 6, msscale=8, utc=7, hh=0, mm=1;
+
+ //size for all objects must have the same fields:
+ //CCYY, MM, DD, h, m, s, ms + timeZone
+ protected final static int TOTAL_SIZE = 9;
+
+ //define constants to be used in assigning default values for
+ //all date/time excluding duration
+ protected final static int YEAR=2000;
+ protected final static int MONTH=01;
+ protected final static int DAY = 15;
+
+
+ /**
+ * Parses time hh:mm:ss.sss and time zone if any
+ *
+ * @param start
+ * @param end
+ * @param data
+ * @exception RuntimeException
+ */
+ protected void getTime (String buffer, int start, int end, int[] data, int[] timeZone) throws RuntimeException{
+
+ int stop = start+2;
+
+ //get hours (hh)
+ data[h]=parseInt(buffer, start,stop);
+
+ //get minutes (mm)
+
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+ start = stop;
+ stop = stop+2;
+ data[m]=parseInt(buffer, start,stop);
+
+ //get seconds (ss)
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+ start = stop;
+ stop = stop+2;
+ data[s]=parseInt(buffer, start,stop);
+
+ if (stop == end)
+ return;
+
+ //get miliseconds (ms)
+ start = stop;
+ int milisec = buffer.charAt(start) == '.' ? start : -1;
+
+ //find UTC sign if any
+ int sign = findUTCSign(buffer, start, end);
+
+ //parse miliseconds
+ if ( milisec != -1 ) {
+ // The end of millisecond part is between . and
+ // either the end of the UTC sign
+ start = sign < 0 ? end : sign;
+ int msEnd = start;
+ while (buffer.charAt(msEnd-1) == '0') msEnd--;
+ data[ms]=parseInt(buffer, milisec+1, msEnd);
+ data[msscale] = msEnd - milisec - 1;
+ }
+
+ //parse UTC time zone (hh:mm)
+ if ( sign>0 ) {
+ if (start != sign)
+ throw new RuntimeException("Error in parsing time zone" );
+ getTimeZone(buffer, data, sign, end, timeZone);
+ }
+ else if (start != end) {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+ }
+
+ /**
+ * Parses date CCYY-MM-DD
+ *
+ * @param start
+ * @param end
+ * @param data
+ * @exception RuntimeException
+ */
+ protected int getDate (String buffer, int start, int end, int[] date) throws RuntimeException{
+
+ start = getYearMonth(buffer, start, end, date);
+
+ if (buffer.charAt(start++) !='-') {
+ throw new RuntimeException("CCYY-MM must be followed by '-' sign");
+ }
+ int stop = start + 2;
+ date[D]=parseInt(buffer, start, stop);
+ return stop;
+ }
+
+ /**
+ * Parses date CCYY-MM
+ *
+ * @param start
+ * @param end
+ * @param data
+ * @exception RuntimeException
+ */
+ protected int getYearMonth (String buffer, int start, int end, int[] date) throws RuntimeException{
+
+ if ( buffer.charAt(0)=='-' ) {
+ // REVISIT: date starts with preceding '-' sign
+ // do we have to do anything with it?
+ //
+ start++;
+ }
+ int i = indexOf(buffer, start, end, '-');
+ if ( i==-1 ) throw new RuntimeException("Year separator is missing or misplaced");
+ int length = i-start;
+ if (length<4) {
+ throw new RuntimeException("Year must have 'CCYY' format");
+ }
+ else if (length > 4 && buffer.charAt(start)=='0'){
+ throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
+ }
+ date[CY]= parseIntYear(buffer, i);
+ if (buffer.charAt(i)!='-') {
+ throw new RuntimeException("CCYY must be followed by '-' sign");
+ }
+ start = ++i;
+ i = start +2;
+ date[M]=parseInt(buffer, start, i);
+ return i; //fStart points right after the MONTH
+ }
+
+ /**
+ * Shared code from Date and YearMonth datatypes.
+ * Finds if time zone sign is present
+ *
+ * @param end
+ * @param date
+ * @exception RuntimeException
+ */
+ protected void parseTimeZone (String buffer, int start, int end, int[] date, int[] timeZone) throws RuntimeException{
+
+ //fStart points right after the date
+
+ if ( start<end ) {
+ int sign = findUTCSign(buffer, start, end);
+ if ( sign<0 ) {
+ throw new RuntimeException ("Error in month parsing");
+ }
+ else {
+ getTimeZone(buffer, date, sign, end, timeZone);
+ }
+ }
+ }
+
+ /**
+ * Parses time zone: 'Z' or {+,-} followed by hh:mm
+ *
+ * @param data
+ * @param sign
+ * @exception RuntimeException
+ */
+ protected void getTimeZone (String buffer, int[] data, int sign, int end, int[] timeZone) throws RuntimeException{
+ data[utc]=buffer.charAt(sign);
+
+ if ( buffer.charAt(sign) == 'Z' ) {
+ if (end>(++sign)) {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+ return;
+ }
+ if ( sign<=(end-6) ) {
+
+ //parse [hh]
+ int stop = ++sign+2;
+ timeZone[hh]=parseInt(buffer, sign, stop);
+ if (buffer.charAt(stop++)!=':') {
+ throw new RuntimeException("Error in parsing time zone" );
+ }
+
+ //parse [ss]
+ timeZone[mm]=parseInt(buffer, stop, stop+2);
+
+ if ( stop+2!=end ) {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+
+ }
+ else {
+ throw new RuntimeException("Error in parsing time zone");
+ }
+ }
+
+ /**
+ * Computes index of given char within StringBuffer
+ *
+ * @param start
+ * @param end
+ * @param ch character to look for in StringBuffer
+ * @return index of ch within StringBuffer
+ */
+ protected int indexOf (String buffer, int start, int end, char ch) {
+ for ( int i=start;i<end;i++ ) {
+ if ( buffer.charAt(i) == ch ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // check whether the character is in the range 0x30 ~ 0x39
+ public static final boolean isDigit(char ch) {
+ return ch >= '0' && ch <= '9';
+ }
+
+ // if the character is in the range 0x30 ~ 0x39, return its int value (0~9),
+ // otherwise, return -1
+ public static final int getDigit(char ch) {
+ return isDigit(ch) ? ch - '0' : -1;
+ }
+
+
+ /**
+ * Return index of UTC char: 'Z', '+', '-'
+ *
+ * @param start
+ * @param end
+ * @return index of the UTC character that was found
+ */
+ protected int findUTCSign (String buffer, int start, int end) {
+ int c;
+ for ( int i=start;i<end;i++ ) {
+ c=buffer.charAt(i);
+ if ( c == 'Z' || c=='+' || c=='-' ) {
+ return i;
+ }
+
+ }
+ return -1;
+ }
+
+ /**
+ * Given start and end position, parses string value
+ *
+ * @param value string to parse
+ * @param start Start position
+ * @param end end position
+ * @return return integer representation of characters
+ */
+ protected int parseInt (String buffer, int start, int end)
+ throws NumberFormatException{
+ //REVISIT: more testing on this parsing needs to be done.
+ int radix=10;
+ int result = 0;
+ int digit=0;
+ int limit = -Integer.MAX_VALUE;
+ int multmin = limit / radix;
+ int i = start;
+ do {
+ digit = getDigit(buffer.charAt(i));
+ if ( digit < 0 ) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ if ( result < multmin ) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ result *= radix;
+ if ( result < limit + digit ) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ result -= digit;
+
+ }while ( ++i < end );
+ return -result;
+ }
+
+ // parse Year differently to support negative value.
+ protected int parseIntYear (String buffer, int end){
+ int radix=10;
+ int result = 0;
+ boolean negative = false;
+ int i=0;
+ int limit;
+ int multmin;
+ int digit=0;
+
+ if (buffer.charAt(0) == '-'){
+ negative = true;
+ limit = Integer.MIN_VALUE;
+ i++;
+
+ }
+ else{
+ limit = -Integer.MAX_VALUE;
+ }
+ multmin = limit / radix;
+ while (i < end)
+ {
+ digit = getDigit(buffer.charAt(i++));
+ if (digit < 0) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ if (result < multmin) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ result *= radix;
+ if (result < limit + digit) throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ result -= digit;
+ }
+
+ if (negative)
+ {
+ if (i > 1) return result;
+ else throw new NumberFormatException("'"+buffer.toString()+"' has wrong format");
+ }
+ return -result;
+
+ }
+
+ public String dateToString(int[] date) {
+ StringBuffer message = new StringBuffer(25);
+ append(message, date[CY], 4);
+ message.append('-');
+ append(message, date[M], 2);
+ message.append('-');
+ append(message, date[D], 2);
+ message.append('T');
+ append(message, date[h], 2);
+ message.append(':');
+ append(message, date[m], 2);
+ message.append(':');
+ append(message, date[s], 2);
+ message.append('.');
+ appendFractionalTime(message, date[ms], date[msscale]);
+ append(message, (char)date[utc], 0);
+ return message.toString();
+ }
+
+ /** Append the fraction time part of a date/time vector to
+ * a string buffer.
+ */
+ public static void appendFractionalTime(StringBuffer buff, int fsec, int scale) {
+ String msString = Integer.toString(fsec);
+ int pad = scale - msString.length();
+ while (pad > 0) {
+ buff.append('0');
+ pad--;
+ }
+ int trunc = msString.length();
+ while (trunc > 0 && msString.charAt(trunc-1) == '0') trunc --;
+ buff.append(msString.substring(0, trunc));
+ }
+
+ protected void append(StringBuffer message, int value, int nch) {
+ if (value < 0) {
+ message.append('-');
+ value = -value;
+ }
+ if (nch == 4) {
+ if (value < 10)
+ message.append("000");
+ else if (value < 100)
+ message.append("00");
+ else if (value < 1000)
+ message.append("0");
+ message.append(value);
+ }
+ else if (nch == 2) {
+ if (value < 10)
+ message.append('0');
+ message.append(value);
+ }
+ else {
+ if (value != 0)
+ message.append((char)value);
+ }
+ }
+
+
+// --------------------------------------------------------------------
+// End of code is adapated from Xerces 2.6.0 AbstractDateTimeDV.
+// --------------------------------------------------------------------
+
+ /**
+ * Normalization. If the value is narrower than the current data type
+ * (e.g. value is xsd:date but the time is xsd:datetime) returns
+ * the narrower type for the literal.
+ * If the type is narrower than the value then it may normalize
+ * the value (e.g. set the mask of an XSDDateTime)
+ * Currently only used to narrow gener XSDDateTime objects
+ * to the minimal XSD date/time type.
+ * @param value the current object value
+ * @param dt the currently set data type
+ * @return a narrower version of the datatype based on the actual value range
+ */
+ @Override
+ public RDFDatatype normalizeSubType(Object value, RDFDatatype dt) {
+ if (value instanceof XSDDateTime) {
+ if (dt.equals(XSDDatatype.XSDdateTime)) {
+ return ((XSDDateTime)value).getNarrowedDatatype();
+ } else if (dt instanceof XSDDatatype){
+ // We've externally narrowed the type, push this down to the date time
+ ((XSDDateTime)value).narrowType((XSDDatatype)dt);
+ }
+ }
+ return this;
+ }
+
+}
Added: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/XSDDateTime2.java
URL: http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/XSDDateTime2.java?rev=1346931&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/XSDDateTime2.java (added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/xsddt/XSDDateTime2.java Wed Jun 6 15:10:03 2012
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 dev.xsddt;
+
+import java.util.Calendar ;
+import java.util.GregorianCalendar ;
+import java.util.TimeZone ;
+
+import com.hp.hpl.jena.datatypes.xsd.AbstractDateTime ;
+import com.hp.hpl.jena.datatypes.xsd.IllegalDateTimeFieldException ;
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype ;
+import com.hp.hpl.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
+
+
+/**
+ * Represent an XSD date/time value. Rather than have a separate type for each
+ * legal date/time value combination this is a combination type than does runtime
+ * checks whether a given field is legal in the current circumstances.
+ *
+ * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
+ * @version $Revision: 1.2 $ on $Date: 2009-09-25 09:58:14 $
+ */
+public class XSDDateTime2 extends AbstractDateTime {
+ /** Mask to indicate whether year is present */
+ public static final short YEAR_MASK = 0x1;
+
+ /** Mask to indicate whether month is present */
+ public static final short MONTH_MASK = 0x2;
+
+ /** Mask to indicate whether day is present */
+ public static final short DAY_MASK = 0x4;
+
+ /** Mask to indicate whether time is present */
+ public static final short TIME_MASK = 0x8;
+
+ /** Mask to indicate all date/time are present */
+ public static final short FULL_MASK = 0xf;
+
+ // Unused /** table mapping xs type name to mask of legal values */
+ //public static final HashMap maskMap = new HashMap();
+
+ /** Set of legal fields for the particular date/time instance */
+ protected short mask;
+
+ /**
+ * Constructor - should only be used by the internals but public scope because
+ * the internals spread across multiple packages.
+ *
+ * @param value the date/time value returned by the parsing
+ * @param mask bitmask defining which components are valid in this instance
+ * (e.g. dates don't have valid time fields).
+ */
+ public XSDDateTime2(Object value, int mask) {
+ super(value);
+ this.mask = (short)mask;
+ }
+
+
+ /**
+ * Constructor - create a full DateTime object from a java calendar instance.
+ *
+ * @param date java calendar instance
+ */
+ public XSDDateTime2(Calendar date) {
+ super(convertCalendar(date));
+ this.mask = FULL_MASK;
+ }
+
+ /**
+ * Return the most specific xsd type which can represent
+ * this date/time
+ */
+ public XSDDatatype getNarrowedDatatype() {
+ switch (mask) {
+ case TIME_MASK:
+ return XSDDatatype.XSDtime;
+ case MONTH_MASK:
+ return XSDDatatype.XSDgMonth;
+ case DAY_MASK:
+ return XSDDatatype.XSDgDay;
+ case YEAR_MASK:
+ return XSDDatatype.XSDgYear;
+ case MONTH_MASK | DAY_MASK:
+ return XSDDatatype.XSDgMonthDay;
+ case MONTH_MASK | YEAR_MASK:
+ return XSDDatatype.XSDgYearMonth;
+ case MONTH_MASK | YEAR_MASK | DAY_MASK:
+ return XSDDatatype.XSDdate;
+ default:
+ return XSDDatatype.XSDdateTime;
+ }
+ }
+
+ /**
+ * Set the mask for this date/time to be that appropriate
+ * for the given XSD subtype. If the type is a subtype of XSDdateTime the
+ * mask will be narrowed appropriately, other types will be silently ignored.
+ */
+ public void narrowType(XSDDatatype dt) {
+ if (dt.equals(XSDDatatype.XSDtime)) {
+ mask = TIME_MASK;
+ } else if (dt.equals(XSDDatatype.XSDgMonth)) {
+ mask = MONTH_MASK;
+ } else if (dt.equals(XSDDatatype.XSDgDay)) {
+ mask = DAY_MASK;
+ } else if (dt.equals(XSDDatatype.XSDgYear)) {
+ mask = YEAR_MASK;
+ } else if (dt.equals(XSDDatatype.XSDgMonthDay)) {
+ mask = MONTH_MASK | DAY_MASK;
+ } else if (dt.equals(XSDDatatype.XSDgYearMonth)) {
+ mask = YEAR_MASK | MONTH_MASK;
+ } else if (dt.equals(XSDDatatype.XSDdate)) {
+ mask = MONTH_MASK | YEAR_MASK | DAY_MASK;
+ }
+ }
+
+ /**
+ * Convert a java calendar object to a new int[] in the format used by XSDAbstractDateTime
+ */
+ static int[] convertCalendar(Calendar date) {
+ int[] data = new int[TOTAL_SIZE];
+//
+// int offset = date.get(Calendar.ZONE_OFFSET) + date.get(Calendar.DST_OFFSET);
+// // Thanks to Greg Shueler for pointing out need for DST offset
+// Calendar cal = date;
+// if (offset != 0) {
+// cal = (Calendar)date.clone();
+// cal.add(Calendar.MILLISECOND, -offset);
+// //cal.setTimeZone(TimeZone.getTimeZone("GMT"));
+// }
+
+
+ Calendar cal = (Calendar)date.clone();
+ cal.get(Calendar.ZONE_OFFSET) ;
+ cal.setTimeZone(TimeZone.getTimeZone("GMT")); // Rebase to GMT.
+
+ data[AbstractDateTime.CY] = cal.get(Calendar.YEAR);
+ data[AbstractDateTime.M] = cal.get(Calendar.MONTH) + 1;
+ data[AbstractDateTime.D] = cal.get(Calendar.DAY_OF_MONTH);
+ data[AbstractDateTime.h] = cal.get(Calendar.HOUR_OF_DAY);
+ data[AbstractDateTime.m] = cal.get(Calendar.MINUTE);
+ data[AbstractDateTime.s] = cal.get(Calendar.SECOND);
+ int ms = cal.get(Calendar.MILLISECOND);
+ data[AbstractDateTime.ms] = ms;
+ data[AbstractDateTime.msscale] = (ms == 0) ? 0 : 3;
+ data[AbstractDateTime.utc] = 'Z';
+ return data;
+ }
+
+ /**
+ * Return the date time as a java Calendar object.
+ * If the timezone has been specified then the object is normalized to GMT.
+ * If the zone has not been specified then we use the default timezone.
+ *
+ * @throws IllegalDateTimeFieldException if this is not a full date + time
+ */
+ public Calendar asCalendar () throws IllegalDateTimeFieldException {
+ TimeZone tz = data[utc] == 'Z' ? TimeZone.getTimeZone("GMT") : TimeZone.getDefault();
+ Calendar calendar = new GregorianCalendar(tz);
+ calendar.set(data[CY], data[M] - 1, data[D], data[h], data[m], data[s]);
+ calendar.set(Calendar.MILLISECOND, (int)Math.round(1000.0 * fractionalSeconds));
+ // was this to work around problems with some Linux JDKs
+ // calendar.set(Calendar.MILLISECOND, 0);
+ return calendar;
+ }
+
+ /**
+ * Return the number of years in the dateTime.
+ * @throws IllegalDateTimeFieldException if there is no legal year component
+ */
+ public int getYears() throws IllegalDateTimeFieldException {
+ if ((mask & YEAR_MASK) == 0) throw new IllegalDateTimeFieldException("Year not available");
+ return data[CY];
+ }
+
+ /**
+ * Return the month in the dateTime, this is in ISO8601 format so january = 1
+ * @throws IllegalDateTimeFieldException if there is no legal month component
+ */
+ public int getMonths() throws IllegalDateTimeFieldException {
+ if ((mask & MONTH_MASK) == 0) throw new IllegalDateTimeFieldException("Month not available");
+ return data[M];
+ }
+
+ /**
+ * Return the number of years in the dateTime
+ * @throws IllegalDateTimeFieldException if there is no legal day component
+ */
+ public int getDays() throws IllegalDateTimeFieldException {
+ if ((mask & DAY_MASK) == 0) throw new IllegalDateTimeFieldException("Day not available");
+ return data[D];
+ }
+
+ /**
+ * Return the number of hours in the dateTime
+ * @throws IllegalDateTimeFieldException if there is no legal time component
+ */
+ public int getHours() throws IllegalDateTimeFieldException {
+ if ((mask & TIME_MASK) == 0) throw new IllegalDateTimeFieldException("Time not available");
+ return data[h];
+ }
+
+ /**
+ * Return the number of minutes in the dateTime
+ * @throws IllegalDateTimeFieldException if there is no legal time component
+ */
+ public int getMinutes() throws IllegalDateTimeFieldException {
+ if ((mask & TIME_MASK) == 0) throw new IllegalDateTimeFieldException("Time not available");
+ return data[m];
+ }
+
+ /**
+ * Return the number of full seconds in the dateTime
+ * @throws IllegalDateTimeFieldException if there is no legal time component
+ */
+ public int getFullSeconds() throws IllegalDateTimeFieldException {
+ if ((mask & TIME_MASK) == 0) throw new IllegalDateTimeFieldException("Time not available");
+ return data[s];
+ }
+
+ /**
+ * Return the number of seconds in the dateTime, including fractional part
+ * @throws IllegalDateTimeFieldException if there is no legal time component
+ */
+ public double getSeconds() throws IllegalDateTimeFieldException {
+ if ((mask & TIME_MASK) == 0) throw new IllegalDateTimeFieldException("Time not available");
+ return data[s] + fractionalSeconds;
+ }
+
+ /**
+ * Return the time component of the dateTime - i.e. just the hours/mins/seconds,
+ * and returns the values in seconds.
+ * @throws IllegalDateTimeFieldException if there is no legal time component
+ */
+ public double getTimePart() throws IllegalDateTimeFieldException {
+ if ((mask & TIME_MASK) == 0) throw new IllegalDateTimeFieldException("Time not available");
+ return ((data[h]) * 60l + data[m]) * 60l + getSeconds();
+ }
+
+ /**
+ * Return legal serialized form.
+ */
+ @Override
+ public String toString() {
+ StringBuffer buff = new StringBuffer();
+ if ((mask & YEAR_MASK) != 0) {
+ buff.append(data[CY]);
+ } else {
+ buff.append("-");
+ }
+ if ((mask & (MONTH_MASK | DAY_MASK)) != 0) {
+ buff.append("-");
+ if ((mask & MONTH_MASK) != 0) {
+ if (data[M] <= 9) buff.append("0");
+ buff.append(data[M]);
+ } else {
+ buff.append("-");
+ }
+ if ((mask & DAY_MASK) != 0) {
+ if (mask != DAY_MASK) buff.append("-");
+ if (data[D] <= 9) buff.append("0");
+ buff.append(data[D]);
+ }
+ }
+ if ((mask & TIME_MASK) != 0 ) {
+ buff.append("T");
+ buff.append(timeLexicalForm());
+ }
+
+ if ( data[utc] != 0 )
+ buff.append("Z");
+
+ return buff.toString();
+ }
+
+ /**
+ * Return the lexical form of the time component.
+ */
+ public String timeLexicalForm() {
+ StringBuffer buff = new StringBuffer();
+ if(data[h]<10) buff.append("0");
+ buff.append(data[h]);
+
+ buff.append(":");
+ if(data[m]<10) buff.append("0");
+ buff.append(data[m]);
+
+ buff.append(":");
+ if(data[s]<10) buff.append("0");
+ buff.append(data[s]);
+
+ if (data[ms] != 0) {
+ buff.append(".");
+ XSDAbstractDateTimeType.appendFractionalTime(buff, data[ms], data[msscale]);
+ }
+ return buff.toString();
+ }
+
+}