001: // Copyright (c) 2006 Per M.A. Bothner.
002: // This is free software; for specifics see ../../../COPYING.
003:
004: package gnu.kawa.xml;
005:
006: import java.util.Calendar;
007: import gnu.bytecode.*;
008: import gnu.math.*;
009: import java.util.GregorianCalendar;
010: import java.util.TimeZone;
011:
012: public class XTimeType extends XDataType {
013: static ClassType typeDateTime = ClassType.make("gnu.math.DateTime");
014:
015: public static final XTimeType dateTimeType = new XTimeType(
016: "dateTime", DATE_TIME_TYPE_CODE);
017:
018: public static final XTimeType dateType = new XTimeType("date",
019: DATE_TYPE_CODE);
020: public static final XTimeType timeType = new XTimeType("time",
021: TIME_TYPE_CODE);
022: public static final XTimeType gYearMonthType = new XTimeType(
023: "gYearMonth", G_YEAR_MONTH_TYPE_CODE);
024: public static final XTimeType gYearType = new XTimeType("gYear",
025: G_YEAR_TYPE_CODE);
026: public static final XTimeType gMonthType = new XTimeType("gMonth",
027: G_MONTH_TYPE_CODE);
028: public static final XTimeType gMonthDayType = new XTimeType(
029: "gMonthDay", G_MONTH_DAY_TYPE_CODE);
030: public static final XTimeType gDayType = new XTimeType("gDay",
031: G_DAY_TYPE_CODE);
032:
033: XTimeType(String name, int code) {
034: super ((Object) name/*FIXME*/, typeDateTime, code);
035: }
036:
037: static int components(int typeCode) {
038: switch (typeCode) {
039: case DATE_TIME_TYPE_CODE:
040: return DateTime.DATE_MASK | DateTime.TIME_MASK;
041: case DATE_TYPE_CODE:
042: return DateTime.DATE_MASK;
043: case TIME_TYPE_CODE:
044: return DateTime.TIME_MASK;
045: case G_YEAR_MONTH_TYPE_CODE:
046: return DateTime.YEAR_MASK | DateTime.MONTH_MASK;
047: case G_YEAR_TYPE_CODE:
048: return DateTime.YEAR_MASK;
049: case G_MONTH_DAY_TYPE_CODE:
050: return DateTime.MONTH_MASK | DateTime.DAY_MASK;
051: case G_DAY_TYPE_CODE:
052: return DateTime.DAY_MASK;
053: case G_MONTH_TYPE_CODE:
054: return DateTime.MONTH_MASK;
055: case DURATION_TYPE_CODE:
056: return DateTime.DATE_MASK | DateTime.TIME_MASK;
057: case YEAR_MONTH_DURATION_TYPE_CODE:
058: return DateTime.YEAR_MASK | DateTime.MONTH_MASK;
059: case DAY_TIME_DURATION_TYPE_CODE:
060: return DateTime.DAY_MASK | DateTime.TIME_MASK;
061: default:
062: return 0;
063: }
064: }
065:
066: /*
067: RuntimeException badFormat(String str)
068: {
069: return new NumberFormatException("Unrecognized "+name+": '"+str+'\'');
070: }
071: */
072:
073: /** Return the current date or time in this type. */
074: public DateTime now() {
075: return new DateTime(XTimeType.components(typeCode)
076: | DateTime.TIMEZONE_MASK, (GregorianCalendar) Calendar
077: .getInstance(fixedTimeZone()));
078:
079: }
080:
081: private static TimeZone fixedTimeZone;
082:
083: private static synchronized TimeZone fixedTimeZone() {
084: if (fixedTimeZone == null) {
085: int offset = TimeZone.getDefault().getRawOffset() / 60000;
086: fixedTimeZone = DateTime.minutesToTimeZone(offset);
087: }
088: return fixedTimeZone;
089: }
090:
091: public static DateTime parseDateTime(String value, int mask) {
092: DateTime time = DateTime.parse(value, mask);
093: // Replace an implicit timezone by by one that is fixed wrt DST.
094: // I.e. TimeZone.getDefault() may be a timezone whose offset varies
095: // depending upon whether Daylight Savings Time is in effect.
096: // Replace it by one with a fixed offset. This is required for
097: // XQuery semantics, though I believe it is wrong.
098: if (time.isZoneUnspecified())
099: time.setTimeZone(fixedTimeZone());
100: return time;
101: }
102:
103: public Object valueOf(String value) {
104: return parseDateTime(value, XTimeType.components(typeCode));
105: }
106:
107: public boolean isInstance(Object obj) {
108: if (!(obj instanceof DateTime))
109: return false;
110: int this Mask = components(this .typeCode);
111: int objMask = ((DateTime) obj).components();
112: //return (thisMask & ~objMask) == 0;
113: return thisMask == objMask;
114: }
115: }
|