/** * 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); } }
private void cloneDate(DateTimeData finalValue, DateTimeData tempDate) { tempDate.year = finalValue.year; tempDate.month = finalValue.month; tempDate.day = finalValue.day; tempDate.hour = finalValue.hour; tempDate.minute = finalValue.minute; tempDate.second = finalValue.second; tempDate.utc = finalValue.utc; tempDate.timezoneHr = finalValue.timezoneHr; tempDate.timezoneMin = finalValue.timezoneMin; }
/** * Resets object representation of date/time * * @param data date/time object */ protected void resetDateObj(DateTimeData data) { data.year = 0; data.month = 0; data.day = 0; data.hour = 0; data.minute = 0; data.second = 0; data.utc = 0; data.timezoneHr = 0; data.timezoneMin = 0; }
private DateTimeData addDuration(DateTimeData date, DateTimeData addto, DateTimeData duration) { // REVISIT: some code could be shared between normalize() and this method, // however is it worth moving it? The structures are different... // resetDateObj(duration); // add months (may be modified additionaly below) int temp = addto.month + date.month; duration.month = modulo(temp, 1, 13); int carry = fQuotient(temp, 1, 13); // add years (may be modified additionaly below) duration.year = addto.year + date.year + carry; // add seconds double dtemp = addto.second + date.second; carry = (int) Math.floor(dtemp / 60); duration.second = dtemp - carry * 60; // add minutes temp = addto.minute + date.minute + carry; carry = fQuotient(temp, 60); duration.minute = mod(temp, 60, carry); // add hours temp = addto.hour + date.hour + carry; carry = fQuotient(temp, 24); duration.hour = mod(temp, 24, carry); duration.day = addto.day + date.day + carry; while (true) { temp = maxDayInMonthFor(duration.year, duration.month); if (duration.day < 1) { // original duration was negative duration.day = duration.day + maxDayInMonthFor(duration.year, duration.month - 1); carry = -1; } else if (duration.day > temp) { duration.day = duration.day - temp; carry = 1; } else { break; } temp = duration.month + carry; duration.month = modulo(temp, 1, 13); duration.year = duration.year + fQuotient(temp, 1, 13); } duration.utc = 'Z'; return duration; }
/** * If timezone present - normalize dateTime [E Adding durations to dateTimes] * * @param date CCYY-MM-DDThh:mm:ss+03 */ protected void normalize(DateTimeData date) { // REVISIT: we have common code in addDuration() for durations // should consider reorganizing it. // // add minutes (from time zone) int negate = -1; if (DEBUG) { System.out.println("==>date.minute" + date.minute); System.out.println("==>date.timezoneMin" + date.timezoneMin); } int temp = date.minute + negate * date.timezoneMin; int carry = fQuotient(temp, 60); date.minute = mod(temp, 60, carry); if (DEBUG) { System.out.println("==>carry: " + carry); } // add hours temp = date.hour + negate * date.timezoneHr + carry; carry = fQuotient(temp, 24); date.hour = mod(temp, 24, carry); if (DEBUG) { System.out.println("==>date.hour" + date.hour); System.out.println("==>carry: " + carry); } date.day = date.day + carry; while (true) { temp = maxDayInMonthFor(date.year, date.month); if (date.day < 1) { date.day = date.day + maxDayInMonthFor(date.year, date.month - 1); carry = -1; } else if (date.day > temp) { date.day = date.day - temp; carry = 1; } else { break; } temp = date.month + carry; date.month = modulo(temp, 1, 13); date.year = date.year + fQuotient(temp, 1, 13); if (date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) { date.year = (date.timezoneHr < 0 || date.timezoneMin < 0) ? 1 : -1; } } date.utc = 'Z'; }
/** * 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; }
/** * Parses, validates and computes normalized version of duration object * * @param str The lexical representation of duration object PnYn MnDTnH nMnS * @param durationType * @return normalized date representation * @exception SchemaDateTimeException Invalid lexical representation */ protected DateTimeData parse(String str, int durationType) throws SchemaDateTimeException { int len = str.length(); DateTimeData date = new DateTimeData(str, this); int start = 0; char c = str.charAt(start++); if (c != 'P' && c != '-') { throw new SchemaDateTimeException(); } else { date.utc = (c == '-') ? '-' : 0; if (c == '-' && str.charAt(start++) != 'P') { throw new SchemaDateTimeException(); } } int negate = 1; // negative duration if (date.utc == '-') { negate = -1; } // at least one number and designator must be seen after P boolean designator = false; int endDate = indexOf(str, start, len, 'T'); if (endDate == -1) { endDate = len; } else if (durationType == YEARMONTHDURATION_TYPE) { throw new SchemaDateTimeException(); } // find 'Y' int end = indexOf(str, start, endDate, 'Y'); if (end != -1) { if (durationType == DAYTIMEDURATION_TYPE) { throw new SchemaDateTimeException(); } // scan year date.year = negate * parseInt(str, start, end); start = end + 1; designator = true; } end = indexOf(str, start, endDate, 'M'); if (end != -1) { if (durationType == DAYTIMEDURATION_TYPE) { throw new SchemaDateTimeException(); } // scan month date.month = negate * parseInt(str, start, end); start = end + 1; designator = true; } end = indexOf(str, start, endDate, 'D'); if (end != -1) { if (durationType == YEARMONTHDURATION_TYPE) { throw new SchemaDateTimeException(); } // scan day date.day = negate * parseInt(str, start, end); start = end + 1; designator = true; } if (len == endDate && start != len) { throw new SchemaDateTimeException(); } if (len != endDate) { // scan hours, minutes, seconds // REVISIT: can any item include a decimal fraction or only seconds? // end = indexOf(str, ++start, len, 'H'); if (end != -1) { // scan hours date.hour = negate * parseInt(str, start, end); start = end + 1; designator = true; } end = indexOf(str, start, len, 'M'); if (end != -1) { // scan min date.minute = negate * parseInt(str, start, end); start = end + 1; designator = true; } end = indexOf(str, start, len, 'S'); if (end != -1) { // scan seconds date.second = negate * parseSecond(str, start, end); start = end + 1; designator = true; } // no additional data shouls appear after last item // P1Y1M1DT is illigal value as well if (start != len || str.charAt(--start) == 'T') { throw new SchemaDateTimeException(); } } if (!designator) { throw new SchemaDateTimeException(); } return date; }