📄 abstractdatetimedv.java
字号:
/* * Copyright 1999-2005 The Apache Software Foundation. * * 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 com.sun.org.apache.xerces.internal.impl.dv.xs;import javax.xml.datatype.DatatypeFactory;import javax.xml.datatype.Duration;import javax.xml.datatype.XMLGregorianCalendar;import com.sun.org.apache.xerces.internal.impl.Constants;import com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl;import com.sun.org.apache.xerces.internal.xs.datatypes.XSDateTime;/** * This is the base class of all date/time datatype validators. * It implements common code for parsing, validating and comparing datatypes. * Classes that extend this class, must implement parse() method. * * REVISIT: There are many instance variables, which would cause problems * when we support grammar caching. A grammar is possibly used by * two parser instances at the same time, then the same simple type * decl object can be used to validate two strings at the same time. * -SG * * @xerces.internal * * @author Elena Litani * @author Len Berman * @author Gopal Sharma, SUN Microsystems Inc. * * @version $Id: AbstractDateTimeDV.java,v 1.2.6.1 2005/09/06 11:43:00 neerajbj Exp $ */public abstract class AbstractDateTimeDV extends TypeValidator { //debugging private static final boolean DEBUG=false; //define shared variables for date/time //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 = 01; protected DatatypeFactory factory = new DatatypeFactoryImpl(); public short getAllowedFacets(){ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE ); }//getAllowedFacets() // distinguishes between identity and equality for date/time values // ie: two values representing the same "moment in time" but with different // remembered timezones are now equal but not identical. public boolean isIdentical (Object value1, Object value2) { if (!(value1 instanceof DateTimeData) || !(value2 instanceof DateTimeData)) { return false; } DateTimeData v1 = (DateTimeData)value1; DateTimeData v2 = (DateTimeData)value2; // original timezones must be the same in addition to date/time values // being 'equal' if ((v1.timezoneHr == v2.timezoneHr) && (v1.timezoneMin == v2.timezoneMin)) { return v1.equals(v2); } return false; }//isIdentical() // the parameters are in compiled form (from getActualValue) public int compare (Object value1, Object value2) { return compareDates(((DateTimeData)value1), ((DateTimeData)value2), true); }//compare() /** * Compare algorithm described in dateDime (3.2.7). * Duration datatype overwrites this method * * @param date1 normalized date representation of the first value * @param date2 normalized date representation of the second value * @param strict * @return less, greater, less_equal, greater_equal, equal */ protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) { if (date1.utc == date2.utc) { return compareOrder(date1, date2); } short c1, c2; DateTimeData tempDate = new DateTimeData(null, this); if ( date1.utc=='Z' ) { //compare date1<=date1<=(date2 with time zone -14) // cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate tempDate.timezoneHr=14; tempDate.timezoneMin = 0; tempDate.utc='+'; normalize(tempDate); c1 = compareOrder(date1, tempDate); if (c1 == LESS_THAN) return c1; //compare date1>=(date2 with time zone +14) // cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate tempDate.timezoneHr = -14; tempDate.timezoneMin = 0; tempDate.utc='-'; normalize(tempDate); c2 = compareOrder(date1, tempDate); if (c2 == GREATER_THAN) return c2; return INDETERMINATE; } else if ( date2.utc=='Z' ) { //compare (date1 with time zone -14)<=date2 // cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate tempDate.timezoneHr = -14; tempDate.timezoneMin = 0; tempDate.utc='-'; if (DEBUG) { System.out.println("tempDate=" + dateToString(tempDate)); } normalize(tempDate); c1 = compareOrder(tempDate, date2); if (DEBUG) { System.out.println("date=" + dateToString(date2)); System.out.println("tempDate=" + dateToString(tempDate)); } if (c1 == LESS_THAN) return c1; //compare (date1 with time zone +14)<=date2 // cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate tempDate.timezoneHr = 14; tempDate.timezoneMin = 0; tempDate.utc='+'; normalize(tempDate); c2 = compareOrder(tempDate, date2); if (DEBUG) { System.out.println("tempDate=" + dateToString(tempDate)); } if (c2 == GREATER_THAN) return c2; return INDETERMINATE; } return INDETERMINATE; } /** * Given normalized values, determines order-relation * between give date/time objects. * * @param date1 date/time object * @param date2 date/time object * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is less than date2, a value greater than 0 if date1 is greater than date2 */ protected short compareOrder(DateTimeData date1, DateTimeData date2) { if(date1.position < 1) { if (date1.year < date2.year) return -1; if (date1.year > date2.year) return 1; } if(date1.position < 2) { if (date1.month < date2.month) return -1; if (date1.month > date2.month) return 1; } if (date1.day < date2.day) return -1; if (date1.day > date2.day) return 1; if (date1.hour < date2.hour) return -1; if (date1.hour > date2.hour) return 1; if (date1.minute < date2.minute) return -1; if (date1.minute > date2.minute) return 1; if (date1.second < date2.second) return -1; if (date1.second > date2.second) return 1; if (date1.utc < date2.utc) return -1; if (date1.utc > date2.utc) return 1; return 0; } /** * 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, DateTimeData data) throws RuntimeException{ int stop = start+2; //get hours (hh) data.hour=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.minute=parseInt(buffer, start,stop); //get seconds (ss) if (buffer.charAt(stop++)!=':') { throw new RuntimeException("Error in parsing time zone" ); } //find UTC sign if any int sign = findUTCSign(buffer, start, end); //get seconds (ms) start = stop; stop = sign < 0 ? end : sign; data.second = parseSecond(buffer, start, stop); //parse UTC time zone (hh:mm) if (sign > 0) { getTimeZone(buffer, data, sign, end); } } /** * Parses date CCYY-MM-DD * * @param buffer * @param start start position * @param end end position * @param date * @exception RuntimeException */ protected int getDate (String buffer, int start, int end, DateTimeData 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.day=parseInt(buffer, start, stop); return stop; } /** * Parses date CCYY-MM * * @param buffer * @param start start position * @param end end position * @param date * @exception RuntimeException */ protected int getYearMonth (String buffer, int start, int end, DateTimeData 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.year= parseIntYear(buffer, i); if (buffer.charAt(i)!='-') { throw new RuntimeException("CCYY must be followed by '-' sign"); } start = ++i; i = start +2; date.month=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, DateTimeData date) throws RuntimeException{ //fStart points right after the date if ( start < end ) { if (!isNextCharUTCSign(buffer, start, end)) { throw new RuntimeException ("Error in month parsing"); } else { getTimeZone(buffer, date, start, end); } } } /** * Parses time zone: 'Z' or {+,-} followed by hh:mm * * @param data * @param sign * @exception RuntimeException */ protected void getTimeZone (String buffer, DateTimeData data, int sign, int end) 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) ) { int negate = buffer.charAt(sign) == '-'?-1:1; //parse hr int stop = ++sign+2; data.timezoneHr = negate*parseInt(buffer, sign, stop); if (buffer.charAt(stop++)!=':') { throw new RuntimeException("Error in parsing time zone" ); } //parse min data.timezoneMin = negate*parseInt(buffer, stop, stop+2); if ( stop+2!=end ) { throw new RuntimeException("Error in parsing time zone"); } if(data.timezoneHr != 0 || data.timezoneMin != 0) data.normalized = false; } else { throw new RuntimeException("Error in parsing time zone"); } if ( DEBUG ) { System.out.println("time[hh]="+data.timezoneHr + " time[mm]=" +data.timezoneMin); } } /** * 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; } /** * Validates given date/time object accoring to W3C PR Schema * [D.1 ISO 8601 Conventions] * * @param data */ protected void validateDateTime (DateTimeData data) { //REVISIT: should we throw an exception for not valid dates // or reporting an error message should be sufficient? /** * XML Schema 1.1 - RQ-123: Allow year 0000 in date related types. */ if (!Constants.SCHEMA_1_1_SUPPORT && data.year==0 ) { throw new RuntimeException("The year \"0000\" is an illegal year value"); } if ( data.month<1 || data.month>12 ) { throw new RuntimeException("The month must have values 1 to 12"); } //validate days if ( data.day>maxDayInMonthFor(data.year, data.month) || data.day<1 ) { throw new RuntimeException("The day must have values 1 to 31"); } //validate hours if ( data.hour>23 || data.hour<0 ) { if (data.hour == 24 && data.minute == 0 && data.second == 0) { data.hour = 0; if (++data.day > maxDayInMonthFor(data.year, data.month)) { data.day = 1; if (++data.month > 12) { data.month = 1; if (Constants.SCHEMA_1_1_SUPPORT) { ++data.year; } else if (++data.year == 0) { data.year = 1; } } } } else { throw new RuntimeException("Hour must have values 0-23, unless 24:00:00"); } } //validate if ( data.minute>59 || data.minute<0 ) { throw new RuntimeException("Minute must have values 0-59"); } //validate if ( data.second>=60 || data.second<0 ) { throw new RuntimeException("Second must have values 0-59"); } //validate if ( data.timezoneHr>14 || data.timezoneHr<-14 ) { throw new RuntimeException("Time zone should have range -14:00 to +14:00"); } else { if((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0) throw new RuntimeException("Time zone should have range -14:00 to +14:00"); else if(data.timezoneMin > 59 || data.timezoneMin < -59) throw new RuntimeException("Minute must have values 0-59"); } } /** * 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; } /** * Returns <code>true</code> if the character at start is 'Z', '+' or '-'. */ protected final boolean isNextCharUTCSign(String buffer, int start, int end) { if (start < end) { char c = buffer.charAt(start); return (c == 'Z' || c == '+' || c == '-'); } return false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -