2 * SchemaCalendarBase.java
4 * This file was generated by XMLSpy 2007sp2 Enterprise Edition.
6 * YOU SHOULD NOT MODIFY THIS FILE, BECAUSE IT WILL BE
7 * OVERWRITTEN WHEN YOU RE-RUN CODE GENERATION.
9 * Refer to the XMLSpy Documentation for further details.
10 * http://www.altova.com/xmlspy
14 package com.jmex.xml.types;
16 import java.text.DecimalFormat;
17 import java.text.SimpleDateFormat;
18 import java.util.Date;
21 public abstract class SchemaCalendarBase implements SchemaTypeCalendar {
22 public static final int TZ_MISSING = 0;
23 public static final int TZ_UTC = 1;
24 public static final int TZ_OFFSET = 2;
32 protected double partsecond; // 0.0 <= partsecond < 1.0
34 protected int offsetTZ; // offset in minutes
35 protected boolean isempty;
37 protected final int DateTimePart_Year = 1 << 0;
38 protected final int DateTimePart_Month = 1 << 1;
39 protected final int DateTimePart_Day = 1 << 2;
40 protected final int DateTimePart_Date = DateTimePart_Year | DateTimePart_Month | DateTimePart_Day;
41 protected final int DateTimePart_Time = 1 << 3;
43 // helper classes - int by reference
46 RefInt(int i) {value = i;}
50 // helper classes - parse context
56 public ParseContext(String source)
62 public boolean isValid()
64 return index < source.length();
67 public boolean check(char expect)
71 return source.charAt(index) == expect;
74 public boolean checkAndAdvance(char expect)
87 public boolean readDigitAndAdvance(RefInt i, int scale, int maxdigit)
89 if (!isValid()) return false;
90 char c = source.charAt(index);
93 int val = (int)c - (int)'0';
96 i.value += (val * scale);
102 public SchemaCalendarBase() {
106 public void setNull() {
110 public void setEmpty() {
111 setInternalValues( 1,1,1, 0,0,0, 0.0, TZ_MISSING ,0 );
115 public boolean equals(Object obj) {
116 if (! (obj instanceof SchemaCalendarBase))
118 SchemaCalendarBase dt = (SchemaCalendarBase)obj;
119 if( !(year == dt.year) )
121 if( !(month == dt.month) )
123 if( !(day == dt.day) )
125 if( !(hour == dt.hour) )
127 if( !(minute == dt.minute) )
129 if( !(second == dt.second) )
131 if( !(partsecond == dt.partsecond) )
133 if( !(hasTZ == dt.hasTZ) )
135 if( !(offsetTZ == dt.offsetTZ) )
140 public int hashCode() {
141 return (int) Double.doubleToLongBits(getApproximatedTotal());
144 public String toDateString() {
145 StringBuffer s = new StringBuffer();
146 s.append( new DecimalFormat("0000").format( (long)year ) );
148 s.append( new DecimalFormat("00").format( (long)month) );
150 s.append( new DecimalFormat("00").format( (long)day) );
154 public String toTimeString() {
155 StringBuffer s = new StringBuffer();
156 s.append( new DecimalFormat("00").format( (long)hour) );
158 s.append( new DecimalFormat("00").format( (long)minute) );
160 s.append( new DecimalFormat("00").format( (long)second) );
161 if( partsecond > 0 && partsecond < 1) {
162 String sPartSecond = new DecimalFormat("0.0###############").format( partsecond );
164 s.append( sPartSecond.substring( 2, sPartSecond.length() ) );
166 if( hasTZ == TZ_UTC ) {
169 else if( hasTZ == TZ_OFFSET ) {
170 int absOffsetTZ = offsetTZ;
173 absOffsetTZ = -offsetTZ;
177 s.append(new DecimalFormat("00").format(absOffsetTZ / 60));
179 s.append(new DecimalFormat("00").format(absOffsetTZ % 60));
184 public int length() {
185 return toString().length();
188 public boolean booleanValue() {
192 public boolean isEmpty() {
196 public boolean isNull() {
200 public int compareTo(Object obj) {
201 return compareTo( (SchemaCalendarBase) obj);
204 public int compareTo(SchemaCalendarBase obj) {
205 return (int)(getApproximatedTotal()-obj.getApproximatedTotal());
208 protected void parseDate(String newvalue) throws StringParseException {
209 if (newvalue.length() == 0 )
211 else if (newvalue.length() < 10)
212 throw new StringParseException("date-part of string is too short", 0);
216 if( newvalue.substring(0,1).equals("-") )
218 year = Integer.parseInt(newvalue.substring(0, nStart+4));
219 if( !newvalue.substring(nStart+4, nStart+5).equals("-"))
220 throw new StringParseException("invalid date format", 2);
221 month = Integer.parseInt(newvalue.substring(nStart+5, nStart+7));
222 if( !newvalue.substring(nStart+7, nStart+8).equals("-"))
223 throw new StringParseException("invalid date format", 2);
224 day = Integer.parseInt(newvalue.substring(nStart+8, newvalue.length()));
226 catch (NumberFormatException e) {
227 throw new StringParseException("invalid date format", 2);
233 protected void parseTime(String newvalue) throws StringParseException {
234 if (newvalue.length() < 8)
235 throw new StringParseException("time-part of string is too short", 0);
238 hour = Integer.parseInt(newvalue.substring(nStart, nStart+2));
239 if( !newvalue.substring(nStart+2, nStart+3).equals(":"))
240 throw new StringParseException("invalid date format", 2);
241 minute = Integer.parseInt(newvalue.substring(nStart+3, nStart+5));
242 if( !newvalue.substring(nStart+5, nStart+6).equals(":"))
243 throw new StringParseException("invalid date format", 2);
244 second = Integer.parseInt(newvalue.substring(nStart+6, nStart+8));
245 int nTZStartPosition = nStart+8;
247 if (newvalue.length()>(nStart+8) ) {
248 nStart = nTZStartPosition;
249 int nEnd = newvalue.length();
250 int nMSecEnd = newvalue.indexOf("Z", nStart);
251 if( nMSecEnd > -1 && nMSecEnd < nEnd )
253 nMSecEnd = newvalue.indexOf("+", nStart);
254 if( nMSecEnd > -1 && nMSecEnd < nEnd )
256 nMSecEnd = newvalue.indexOf("-", nStart);
257 if( nMSecEnd > -1 && nMSecEnd < nEnd )
259 nTZStartPosition = nEnd;
260 partsecond = Double.parseDouble( "0" + newvalue.substring(nStart, nEnd));
264 if (newvalue.length()>nTZStartPosition && newvalue.substring(nTZStartPosition, nTZStartPosition + 1).equals("Z"))
266 else if (newvalue.length() == nTZStartPosition + 6) {
268 offsetTZ = Integer.parseInt(newvalue.substring(nTZStartPosition+1, nTZStartPosition + 3)) * 60 +
269 Integer.parseInt(newvalue.substring(nTZStartPosition+4, nTZStartPosition + 6));
270 if( newvalue.substring(nTZStartPosition, nTZStartPosition+1).equals("-"))
271 offsetTZ = -offsetTZ;
274 catch (NumberFormatException e) {
275 throw new StringParseException("invalid number format", 2);
280 protected boolean parseDateTime(String s, int part)
282 ParseContext context = new ParseContext(s);
284 boolean bDatePart = ( part & DateTimePart_Date ) != 0;
285 boolean bTimePart = ( part & DateTimePart_Time ) != 0;
287 RefInt year = new RefInt(0);
288 RefInt month = new RefInt(0);
289 RefInt day = new RefInt(0);
290 RefInt hour = new RefInt(0);
291 RefInt minute = new RefInt(0);
300 boolean bNegative = context.checkAndAdvance('-');
302 if ((part & DateTimePart_Year) != 0)
305 RefInt temp = new RefInt(0);;
306 while (context.readDigitAndAdvance(temp, 1, 9))
308 year.value = year.value * 10 + temp.value;
311 if (digits >= 8) // overflow
314 if (digits < 4) // inalid
316 if (digits > 4 && year.value < 10000)
319 year.value = -year.value;
322 if ((part & (DateTimePart_Month | DateTimePart_Day)) != 0)
324 if ( !context.checkAndAdvance( '-' ) )
327 if ( ( part & DateTimePart_Month ) != 0 )
329 if ( !context.readDigitAndAdvance(month, 10, 1 ) ) return false;
330 if ( !context.readDigitAndAdvance(month, 1, month.value < 10 ? 9 : 2 ) ) return false;
331 if ( month.value == 0 ) return false;
334 if ( ( part & DateTimePart_Day ) != 0 )
336 if ( !context.checkAndAdvance('-') ) return false;
338 int maxFirstDigit = month.value != 2 ? 3 : 2;
340 // complicate things by making them complicated.
341 if ( !context.readDigitAndAdvance( day, 10, maxFirstDigit ) ) return false;
342 if ( !context.readDigitAndAdvance( day, 1, 9 ) ) return false;
343 if ( day.value == 0 || day.value > 31 ) return false;
345 if ( ( part & DateTimePart_Month ) != 0 )
347 boolean b1 = month.value <= 7;
348 boolean b2 = ( month.value & 1 ) == 0;
350 // month 1, 3, 5, 7, 8, 10, 12
351 if ( b1 == b2 && day.value > 30 )
355 if ( month.value == 2 && day.value > 29 )
359 if (month.value == 2 && (part & DateTimePart_Year) != 0 &&
360 (year.value % 4 != 0 || year.value % 100 == 0) &&
361 year.value % 400 != 0 && day.value > 28)
370 if ( !context.checkAndAdvance('T') ) return false;
379 if ( !context.readDigitAndAdvance( hour, 10, 2 ) ) return false;
380 if ( !context.readDigitAndAdvance( hour, 1, hour.value < 20 ? 9 : 4 ) ) return false;
381 if ( !context.checkAndAdvance( ':' ) ) return false;
382 int maxFirstDigit = hour.value == 24 ? 0 : 5;
383 int maxSecondDigit = hour.value == 24 ? 0 : 9;
384 if ( !context.readDigitAndAdvance( minute, 10, maxFirstDigit ) ) return false;
385 if ( !context.readDigitAndAdvance( minute, 1, maxSecondDigit ) ) return false;
386 if ( !context.checkAndAdvance( ':' ) ) return false;
387 RefInt secondInt = new RefInt (0);
388 if ( !context.readDigitAndAdvance( secondInt, 10, maxFirstDigit ) ) return false;
389 if ( !context.readDigitAndAdvance( secondInt, 1, maxSecondDigit ) ) return false;
391 second = secondInt.value;
393 if ( context.checkAndAdvance( '.' ) )
395 // fraction. do whatever seems fit.
396 RefInt val = new RefInt(0);
398 while ( context.readDigitAndAdvance( val, 1, 9) )
402 if ( digits >= 8 ) // precision loss - ignore
409 second += val.value * Math.pow( 10.0, -digits - 1 );
411 // skip any further digits.
412 while ( context.readDigitAndAdvance( val, 0, 9) )
418 if ( context.checkAndAdvance('Z') )
420 // timezone specified, it is UTC.
424 else if ( context.check('+') || context.check('-' ) )
426 // timezone offset, in hour:minute format
427 boolean bNegative = context.check('-');
430 // do not check the hour part, for those who are obscure.
431 RefInt temp = new RefInt(0);
432 if ( !context.readDigitAndAdvance( temp, 600, 9 ) ) return false;
433 if ( !context.readDigitAndAdvance( temp, 60, 9 ) ) return false;
434 if ( !context.checkAndAdvance( ':' ) ) return false;
435 if ( !context.readDigitAndAdvance( temp, 10, 5 ) ) return false;
436 if ( !context.readDigitAndAdvance( temp, 1, 9 ) ) return false;
439 offsetTZ = bNegative ? -temp.value : temp.value;
442 if ( context.isValid() )
445 setInternalValues(year.value, month.value, day.value, hour.value, minute.value, (int)second, ((second * 1000) % 1000)/1000, hasTZ, offsetTZ);
450 public double getApproximatedTotal() {
451 // approximated because month is approximated to have always 31 days.
452 return (double)second + 60.0*((double)minute + 60.0*((double)hour + 24.0*((double)day + 31.0*((double)month + 12.0*(double)year)))) + partsecond;
455 static int[] monthStart = new int[]
469 365, // 1st of next year
472 static int[] monthStartLeap = new int[]
486 366, // 1st of next year
489 public long getTimeValue()
494 int monthRem = ( month - 1 ) % 12;
495 if ( monthRem < 0 ) monthRem += 12;
496 realYear += ( month - monthRem - 1 ) / 12;
498 int yearRed = realYear - 1;
499 int yearRem = yearRed % 400;
500 if ( yearRem < 0 ) yearRem += 400;
501 value += ( ( yearRed - yearRem ) / 400 ) * (303 * 365 + 97 * 366);
502 value += ( yearRem / 100 ) * (76 * 365 + 24 * 366);
504 value += ( yearRem / 4 ) * (365 * 3 + 366);
506 value += yearRem * 365;
508 if ( ( realYear % 4 == 0 ) && ( ( realYear % 100 != 0 ) || ( realYear % 400 == 0 ) ) )
509 value += monthStartLeap[ monthRem ];
511 value += monthStart[ monthRem ];
515 value = value * 24 + hour;
516 value = value * 60 + minute - offsetTZ;
517 value = ( long )( ( value * 60 + second + partsecond ) * 1000 );
521 public void setTimeFromTimeValue(long tv)
523 tv %= (86400 * 1000);
527 partsecond = (tv % 1000) / 1000.0;
529 second = (int)(tv % 60);
531 minute = (int) (tv % 60);
533 hour = (int) (tv % 24);
536 public void setDateFromTimeValue(long tv)
538 long dayTime = tv % ( 86400 * 1000 );
539 int days = (int)(tv / (86400 * 1000));
544 year = days < 0 ? -1 : +1; // there is no year 0
548 year += 400 * ( days / (303 * 365 + 97 * 366) );
549 days %= (303 * 365 + 97 * 366);
550 if ( days == (303 * 365 + 97 * 366) - 1 )
557 year += 100 * ( days / (76 * 365 + 24 * 366) );
558 days %= (76 * 365 + 24 * 366);
559 year += 4 * ( days / (365 * 3 + 366) );
560 days %= (365 * 3 + 366);
561 if ( days == (365 * 3 + 366) - 1 ) // last day of leap year
577 if ( ( year % 4 == 0 ) && ( ( year % 100 != 0 ) || ( year % 400 == 0 ) ) )
578 monthStarts = monthStartLeap;
580 monthStarts = monthStart;
582 while ( days >= monthStarts[ month ] )
585 day = days - monthStarts[ month - 1 ] + 1;
588 public Date getDate() {
589 String s = toDateString() + " " + toTimeString();
591 return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(s));
592 } catch( java.text.ParseException e ) {
593 throw new StringParseException("Could not convert to date.", 0);
597 protected void setInternalValues(int newyear, int newmonth, int newday, int newhour, int newminute, int newsecond, double newpartsecond, int newhasTZ, int newoffsetTZ) {
604 partsecond = newpartsecond;
606 offsetTZ = newoffsetTZ;
610 // ---------- interface SchemaTypeCalendar ----------
611 public SchemaDuration durationValue() {
612 throw new TypesIncompatibleException(this, new SchemaDuration( "PT" ) );