alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (AbstractDateTimeDV.java)

This example Java source code file (AbstractDateTimeDV.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractdatetimedv, bigdecimal, datetimedata, debug, durationdv, error, indeterminate, math, numberformatexception, override, runtimeexception, string, stringbuffer, year

The AbstractDateTimeDV.java Java example source code

/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * 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 java.math.BigDecimal;

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.7 2010-11-01 04:39:46 joehw 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 static final DatatypeFactory datatypeFactory = new DatatypeFactoryImpl();

    @Override
    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.
    @Override
    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)
    @Override
    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 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;
    }

    /**
     * Given start and end position, parses string value
     *
     * @param buffer 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 + "' has wrong format");
            }
            if (result < multmin) {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
            result *= radix;
            if (result < limit + digit) {
                throw new NumberFormatException("'" + buffer + "' 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 + "' has wrong format");
            }
            if (result < multmin) {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
            result *= radix;
            if (result < limit + digit) {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
            result -= digit;
        }

        if (negative) {
            if (i > 1) {
                return result;
            } else {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
        }
        return -result;

    }

    /**
     * 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';
    }

    /**
     * @param date
     */
    protected void saveUnnormalized(DateTimeData date) {
        date.unNormYear = date.year;
        date.unNormMonth = date.month;
        date.unNormDay = date.day;
        date.unNormHour = date.hour;
        date.unNormMinute = date.minute;
        date.unNormSecond = date.second;
    }

    /**
     * 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;
    }

    /**
     * Given {year,month} computes maximum number of days for given month
     *
     * @param year
     * @param month
     * @return integer containg the number of days in a given month
     */
    protected int maxDayInMonthFor(int year, int month) {
        //validate days
        if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        } else if (month == 2) {
            if (isLeapYear(year)) {
                return 29;
            } else {
                return 28;
            }
        } else {
            return 31;
        }
    }

    private boolean isLeapYear(int year) {

        //REVISIT: should we take care about Julian calendar?
        return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
    }

    //
    // help function described in W3C PR Schema [E Adding durations to dateTimes]
    //
    protected int mod(int a, int b, int quotient) {
        //modulo(a, b) = a - fQuotient(a,b)*b
        return (a - quotient * b);
    }

    //
    // help function described in W3C PR Schema [E Adding durations to dateTimes]
    //
    protected int fQuotient(int a, int b) {

        //fQuotient(a, b) = the greatest integer less than or equal to a/b
        return (int) Math.floor((float) a / b);
    }

    //
    // help function described in W3C PR Schema [E Adding durations to dateTimes]
    //
    protected int modulo(int temp, int low, int high) {
        //modulo(a - low, high - low) + low
        int a = temp - low;
        int b = high - low;
        return (mod(a, b, fQuotient(a, b)) + low);
    }

    //
    // help function described in W3C PR Schema [E Adding durations to dateTimes]
    //
    protected int fQuotient(int temp, int low, int high) {
        //fQuotient(a - low, high - low)

        return fQuotient(temp - low, high - low);
    }

    protected String dateToString(DateTimeData date) {
        StringBuffer message = new StringBuffer(25);
        append(message, date.year, 4);
        message.append('-');
        append(message, date.month, 2);
        message.append('-');
        append(message, date.day, 2);
        message.append('T');
        append(message, date.hour, 2);
        message.append(':');
        append(message, date.minute, 2);
        message.append(':');
        append(message, date.second);
        append(message, (char) date.utc, 0);
        return message.toString();
    }

    protected final void append(StringBuffer message, int value, int nch) {
        if (value == Integer.MIN_VALUE) {
            message.append(value);
            return;
        }
        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);
            }
        }
    }

    protected final void append(StringBuffer message, double value) {
        if (value < 0) {
            message.append('-');
            value = -value;
        }
        if (value < 10) {
            message.append('0');
        }
        append2(message, value);
    }

    protected final void append2(StringBuffer message, double value) {
        final int intValue = (int) value;
        if (value == intValue) {
            message.append(intValue);
        } else {
            append3(message, value);
        }
    }

    private void append3(StringBuffer message, double value) {
        String d = String.valueOf(value);
        int eIndex = d.indexOf('E');
        if (eIndex == -1) {
            message.append(d);
            return;
        }
        int exp;
        if (value < 1) {
            // Need to convert from scientific notation of the form
            // n.nnn...E-N (N >= 4) to a normal decimal value.
            try {
                exp = parseInt(d, eIndex + 2, d.length());
            } // This should never happen.
            // It's only possible if String.valueOf(double) is broken.
            catch (Exception e) {
                message.append(d);
                return;
            }
            message.append("0.");
            for (int i = 1; i < exp; ++i) {
                message.append('0');
            }
            // Remove trailing zeros.
            int end = eIndex - 1;
            while (end > 0) {
                char c = d.charAt(end);
                if (c != '0') {
                    break;
                }
                --end;
            }
            // Now append the digits to the end. Skip over the decimal point.
            for (int i = 0; i <= end; ++i) {
                char c = d.charAt(i);
                if (c != '.') {
                    message.append(c);
                }
            }
        } else {
            // Need to convert from scientific notation of the form
            // n.nnn...EN (N >= 7) to a normal decimal value.
            try {
                exp = parseInt(d, eIndex + 1, d.length());
            } // This should never happen.
            // It's only possible if String.valueOf(double) is broken.
            catch (Exception e) {
                message.append(d);
                return;
            }
            final int integerEnd = exp + 2;
            for (int i = 0; i < eIndex; ++i) {
                char c = d.charAt(i);
                if (c != '.') {
                    if (i == integerEnd) {
                        message.append('.');
                    }
                    message.append(c);
                }
            }
            // Append trailing zeroes if necessary.
            for (int i = integerEnd - eIndex; i > 0; --i) {
                message.append('0');
            }
        }
    }

    protected double parseSecond(String buffer, int start, int end)
            throws NumberFormatException {
        int dot = -1;
        for (int i = start; i < end; i++) {
            char ch = buffer.charAt(i);
            if (ch == '.') {
                dot = i;
            } else if (ch > '9' || ch < '0') {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
        }
        if (dot == -1) {
            if (start + 2 != end) {
                throw new NumberFormatException("'" + buffer + "' has wrong format");
            }
        } else if (start + 2 != dot || dot + 1 == end) {
            throw new NumberFormatException("'" + buffer + "' has wrong format");
        }
        return Double.parseDouble(buffer.substring(start, end));
    }

    //
    //Private help functions
    //
    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;
    }

    /**
     * Represents date time data
     */
    static final class DateTimeData implements XSDateTime {

        int year, month, day, hour, minute, utc;
        double second;
        int timezoneHr, timezoneMin;
        private String originalValue;
        boolean normalized = true;
        int unNormYear;
        int unNormMonth;
        int unNormDay;
        int unNormHour;
        int unNormMinute;
        double unNormSecond;
        // used for comparisons - to decide the 'interesting' portions of
        // a date/time based data type.
        int position;
        // a pointer to the type that was used go generate this data
        // note that this is not the actual simple type, but one of the
        // statically created XXXDV objects, so this won't cause any GC problem.
        final AbstractDateTimeDV type;
        private volatile String canonical;

        public DateTimeData(String originalValue, AbstractDateTimeDV type) {
            this.originalValue = originalValue;
            this.type = type;
        }

        public DateTimeData(int year, int month, int day, int hour, int minute,
                double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) {
            this.year = year;
            this.month = month;
            this.day = day;
            this.hour = hour;
            this.minute = minute;
            this.second = second;
            this.utc = utc;
            this.type = type;
            this.originalValue = originalValue;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof DateTimeData)) {
                return false;
            }
            return type.compareDates(this, (DateTimeData) obj, true) == 0;
        }

        // If two DateTimeData are equals - then they should have the same
        // hashcode. This means we need to convert the date to UTC before
        // we return its hashcode.
        // The DateTimeData is unfortunately mutable - so we cannot
        // cache the result of the conversion...
        //
        @Override
        public int hashCode() {
            final DateTimeData tempDate = new DateTimeData(null, type);
            type.cloneDate(this, tempDate);
            type.normalize(tempDate);
            return type.dateToString(tempDate).hashCode();
        }

        @Override
        public String toString() {
            if (canonical == null) {
                canonical = type.dateToString(this);
            }
            return canonical;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear()
         */

        @Override
        public int getYears() {
            if (type instanceof DurationDV) {
                return 0;
            }
            return normalized ? year : unNormYear;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth()
         */

        @Override
        public int getMonths() {
            if (type instanceof DurationDV) {
                return year * 12 + month;
            }
            return normalized ? month : unNormMonth;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay()
         */

        @Override
        public int getDays() {
            if (type instanceof DurationDV) {
                return 0;
            }
            return normalized ? day : unNormDay;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour()
         */

        @Override
        public int getHours() {
            if (type instanceof DurationDV) {
                return 0;
            }
            return normalized ? hour : unNormHour;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes()
         */

        @Override
        public int getMinutes() {
            if (type instanceof DurationDV) {
                return 0;
            }
            return normalized ? minute : unNormMinute;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds()
         */

        @Override
        public double getSeconds() {
            if (type instanceof DurationDV) {
                return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second;
            }
            return normalized ? second : unNormSecond;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone()
         */

        @Override
        public boolean hasTimeZone() {
            return utc != 0;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours()
         */

        @Override
        public int getTimeZoneHours() {
            return timezoneHr;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes()
         */

        @Override
        public int getTimeZoneMinutes() {
            return timezoneMin;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue()
         */

        @Override
        public String getLexicalValue() {
            return originalValue;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize()
         */

        @Override
        public XSDateTime normalize() {
            if (!normalized) {
                DateTimeData dt = (DateTimeData) this.clone();
                dt.normalized = true;
                return dt;
            }
            return this;
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized()
         */

        @Override
        public boolean isNormalized() {
            return normalized;
        }

        @Override
        public Object clone() {
            DateTimeData dt = new DateTimeData(this.year, this.month, this.day, this.hour,
                    this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type);
            dt.canonical = this.canonical;
            dt.position = position;
            dt.timezoneHr = this.timezoneHr;
            dt.timezoneMin = this.timezoneMin;
            dt.unNormYear = this.unNormYear;
            dt.unNormMonth = this.unNormMonth;
            dt.unNormDay = this.unNormDay;
            dt.unNormHour = this.unNormHour;
            dt.unNormMinute = this.unNormMinute;
            dt.unNormSecond = this.unNormSecond;
            return dt;
        }

        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar()
         */
        @Override
        public XMLGregorianCalendar getXMLGregorianCalendar() {
            return type.getXMLGregorianCalendar(this);
        }
        /* (non-Javadoc)
         * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration()
         */

        @Override
        public Duration getDuration() {
            return type.getDuration(this);
        }
    }

    protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData data) {
        return null;
    }

    protected Duration getDuration(DateTimeData data) {
        return null;
    }

    protected final BigDecimal getFractionalSecondsAsBigDecimal(DateTimeData data) {
        final StringBuffer buf = new StringBuffer();
        append3(buf, data.unNormSecond);
        String value = buf.toString();
        final int index = value.indexOf('.');
        if (index == -1) {
            return null;
        }
        value = value.substring(index);
        final BigDecimal _val = new BigDecimal(value);
        if (_val.compareTo(BigDecimal.valueOf(0)) == 0) {
            return null;
        }
        return _val;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java AbstractDateTimeDV.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.