XML Java

/*
 * Copyright 2003, 2004  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.
 */
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.TimeZone;
/** 

An instance of {@link java.text.Format}, which may be used
 * to parse and format xs:dateTime values.


 */
public class XsDateTimeFormat extends Format {
  private static final long serialVersionUID = 3258131340871479609L;
  final boolean parseDate;
    final boolean parseTime;
    XsDateTimeFormat(boolean pParseDate, boolean pParseTime) {
        parseDate = pParseDate;
        parseTime = pParseTime;
    }
    /** Creates a new instance.
     */
    public XsDateTimeFormat() {
        this(true, true);
    }
    private int parseInt(String pString, int pOffset, StringBuffer pDigits) {
        int length = pString.length();
        pDigits.setLength(0);
        while (pOffset < length) {
            char c = pString.charAt(pOffset);
            if (Character.isDigit(c)) {
                pDigits.append(c);
                ++pOffset;
            } else {
                break;
            }
        }
        return pOffset;
    }
    public Object parseObject(String pString, ParsePosition pParsePosition) {
        if (pString == null) {
            throw new NullPointerException("The String argument must not be null.");
        }
        if (pParsePosition == null) {
            throw new NullPointerException("The ParsePosition argument must not be null.");
        }
        int offset = pParsePosition.getIndex();
        int length = pString.length();
        boolean isMinus = false;
        StringBuffer digits = new StringBuffer();
        int year, month, mday;
        if (parseDate) {
            // Sign
            if (offset < length) {
                char c = pString.charAt(offset);
                if (c == '+') {
                    ++offset;
                } else if (c == '-') {
                    ++offset;
                    isMinus = true;
                }
            }
          offset = parseInt(pString, offset, digits);
          if (digits.length() < 4) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          year = Integer.parseInt(digits.toString());
  
          if (offset < length  &&  pString.charAt(offset) == '-') {
              ++offset;
          } else {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
  
          offset = parseInt(pString, offset, digits);
          if (digits.length() != 2) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          month = Integer.parseInt(digits.toString());
  
          if (offset < length &&  pString.charAt(offset) == '-') {
              ++offset;
          } else {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
  
          offset = parseInt(pString, offset, digits);
          if (digits.length() != 2) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          mday = Integer.parseInt(digits.toString());
          if (parseTime) {
              if (offset < length  &&  pString.charAt(offset) == 'T') {
                  ++offset;
              } else {
                  pParsePosition.setErrorIndex(offset);
                  return null;
              }
          }
        } else {
            year = month = mday = 0;
        }
        int hour, minute, second, millis;
        if (parseTime) {
          offset = parseInt(pString, offset, digits);
          if (digits.length() != 2) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          hour = Integer.parseInt(digits.toString());
  
          if (offset < length  &&  pString.charAt(offset) == ':') {
              ++offset;
          } else {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
  
          offset = parseInt(pString, offset, digits);
          if (digits.length() != 2) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          minute = Integer.parseInt(digits.toString());
  
          if (offset < length  &&  pString.charAt(offset) == ':') {
              ++offset;
          } else {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
  
          offset = parseInt(pString, offset, digits);
          if (digits.length() != 2) {
              pParsePosition.setErrorIndex(offset);
              return null;
          }
          second = Integer.parseInt(digits.toString());
  
          if (offset < length  &&  pString.charAt(offset) == '.') {
              ++offset;
              offset = parseInt(pString, offset, digits);
              if (digits.length() > 0) {
                  millis = Integer.parseInt(digits.toString());
                    if (millis > 999) {
                        pParsePosition.setErrorIndex(offset);
                        return null;
                    }
                    for (int i = digits.length();  i < 3;  i++) {
                        millis *= 10;
                    }
              } else {
                  millis = 0;
              }
          } else {
              millis = 0;
          }
        } else {
            hour = minute = second = millis = 0;
        }
        digits.setLength(0);
        digits.append("GMT");
        if (offset < length) {
            char c = pString.charAt(offset);
            if (c == 'Z') {
                // Ignore UTC, it is the default
                ++offset;
            } else if (c == '+' || c == '-') {
                digits.append(c);
                ++offset;
                for (int i = 0;  i < 5;  i++) {
                    if (offset >= length) {
                        pParsePosition.setErrorIndex(offset);
                        return null;
                    }
                    c = pString.charAt(offset);
                    if ((i != 2  &&  Character.isDigit(c))  ||
                        (i == 2  &&  c == ':')) {
                        digits.append(c);
                    } else {
                        pParsePosition.setErrorIndex(offset);
                        return null;
                    }
                    ++offset;
                }
            }
        }
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(digits.toString()));
        cal.set(isMinus ? -year : year, parseDate ? month-1 : month, mday, hour, minute, second);
        cal.set(Calendar.MILLISECOND, millis);
        pParsePosition.setIndex(offset);
        return cal;
    }
    private void append(StringBuffer pBuffer, int pNum, int pMinLen) {
        String s = Integer.toString(pNum);
        for (int i = s.length();  i < pMinLen;  i++) {
            pBuffer.append('0');
        }
        pBuffer.append(s);
    }
    public StringBuffer format(Object pCalendar, StringBuffer pBuffer, FieldPosition pPos) {
        if (pCalendar == null) {
            throw new NullPointerException("The Calendar argument must not be null.");
        }
        if (pBuffer == null) {
            throw new NullPointerException("The StringBuffer argument must not be null.");
        }
        if (pPos == null) {
            throw new NullPointerException("The FieldPosition argument must not be null.");
        }
        Calendar cal = (Calendar) pCalendar;
        if (parseDate) {
          int year = cal.get(Calendar.YEAR);
          if (year < 0) {
              pBuffer.append('-');
              year = -year;
          }
          append(pBuffer, year, 4);
          pBuffer.append('-');
          append(pBuffer, cal.get(Calendar.MONTH)+1, 2);
          pBuffer.append('-');
          append(pBuffer, cal.get(Calendar.DAY_OF_MONTH), 2);
          if (parseTime) {
              pBuffer.append('T');
          }
        }
        if (parseTime) {
          append(pBuffer, cal.get(Calendar.HOUR_OF_DAY), 2);
          pBuffer.append(':');
          append(pBuffer, cal.get(Calendar.MINUTE), 2);
          pBuffer.append(':');
          append(pBuffer, cal.get(Calendar.SECOND), 2);
          int millis = cal.get(Calendar.MILLISECOND);
          if (millis > 0) {
              pBuffer.append('.');
              append(pBuffer, millis, 3);
          }
        }
        TimeZone tz = cal.getTimeZone();
        // JDK 1.4: int offset = tz.getOffset(cal.getTimeInMillis());
        int offset = cal.get(Calendar.ZONE_OFFSET);
        if (tz.inDaylightTime(cal.getTime())) {
          offset += cal.get(Calendar.DST_OFFSET);
        }
        if (offset == 0) {
            pBuffer.append('Z');
        } else {
            if (offset < 0) {
                pBuffer.append('-');
                offset = -offset;
            } else {
                pBuffer.append('+');
            }
            int minutes = offset / (60*1000);
            int hours = minutes / 60;
            minutes -= hours * 60;
            append(pBuffer, hours, 2);
            pBuffer.append(':');
            append(pBuffer, minutes, 2);
        }
        return pBuffer;
    }
}
/////////////////////////////////////////////////
/*
 * Copyright 2004  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 org.apache.ws.commons.util.test;
import java.text.Format;
import java.text.ParseException;
import java.util.Calendar;
import java.util.TimeZone;
import org.apache.ws.commons.util.XsDateFormat;
import org.apache.ws.commons.util.XsDateTimeFormat;
import org.apache.ws.commons.util.XsTimeFormat;
import junit.framework.TestCase;
/** 

Test case for the various instances of {@link java.text.Format},
 * which are being used to parse special types like xs:dateTime.


 *
 * @author Jochen Wiedmann
 */
public class XsDateTimeFormatTest extends TestCase {
    /** Creates a new test with the given name.
     */
    public XsDateTimeFormatTest(String pName) {
        super(pName);
    }
    private Calendar getCalendar(TimeZone pTimeZone) {
        Calendar cal = Calendar.getInstance(pTimeZone);
        cal.set(2004, 01-1, 14, 03, 12, 07);
        cal.set(Calendar.MILLISECOND, 0);
        return cal;
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsDateTimeFormat#format(Object, StringBuffer, java.text.FieldPosition)}.
     */
    public void testFormatDateTime() {
        Calendar cal = getCalendar(TimeZone.getTimeZone("GMT"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        XsDateTimeFormat format = new XsDateTimeFormat();
        String got = format.format(cal);
        String expect = "2004-01-14T03:12:07Z";
        assertEquals(expect, got);
        cal = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        got = format.format(cal);
        expect = "2004-01-14T03:12:07-03:00";
        assertEquals(expect, got);
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsDateTimeFormat#parseObject(String, java.text.ParsePosition)}.
     */
    public void testParseDateTime() throws ParseException {
        String[] dateTimes = new String[]{
      "2004-01-14T03:12:07.000Z",
      "2004-01-14T03:12:07",
      "2004-01-14T03:12:07-00:00",
      "2004-01-14T03:12:07+00:00",
    };
        XsDateTimeFormat format = new XsDateTimeFormat();
        Calendar expect = getCalendar(TimeZone.getTimeZone("GMT"));
        for (int i = 0;  i < dateTimes.length;  i++) {
            Calendar got = (Calendar) format.parseObject(dateTimes[0]);
            assertEquals(expect, got);
        }
        String dateTime = "2004-01-14T03:12:07.000-03:00";
        expect = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        Calendar got = (Calendar) format.parseObject(dateTime);
        assertEquals(expect, got);
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsDateFormat#format(Object, StringBuffer, java.text.FieldPosition)}.
     */
    public void testFormatDate() {
        Calendar cal = getCalendar(TimeZone.getTimeZone("GMT"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        XsDateFormat format = new XsDateFormat();
        String got = format.format(cal);
        String expect = "2004-01-14Z";
        assertEquals(expect, got);
        cal = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        got = format.format(cal);
        expect = "2004-01-14-03:00";
        assertEquals(expect, got);
    }
    protected void assertEqualDate(Calendar pExpect, Calendar pGot) {
        assertEquals(pExpect.get(Calendar.YEAR), pGot.get(Calendar.YEAR));
        assertEquals(pExpect.get(Calendar.MONTH), pGot.get(Calendar.MONTH));
        assertEquals(pExpect.get(Calendar.DAY_OF_MONTH), pGot.get(Calendar.DAY_OF_MONTH));
        assertEquals(pExpect.getTimeZone(), pGot.getTimeZone());
    }
    protected void assertEqualTime(Calendar pExpect, Calendar pGot) {
        assertEquals(pExpect.get(Calendar.HOUR_OF_DAY), pGot.get(Calendar.HOUR_OF_DAY));
        assertEquals(pExpect.get(Calendar.MINUTE), pGot.get(Calendar.MINUTE));
        assertEquals(pExpect.get(Calendar.SECOND), pGot.get(Calendar.SECOND));
        assertEquals(pExpect.get(Calendar.MILLISECOND), pGot.get(Calendar.MILLISECOND));
        assertEquals(pExpect.getTimeZone(), pGot.getTimeZone());
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsDateFormat#parseObject(String, java.text.ParsePosition)}.
     */
    public void testParseDate() throws ParseException {
        String[] dateTimes = new String[]{
      "2004-01-14Z",
      "2004-01-14",
      "2004-01-14+00:00",
      "2004-01-14-00:00",
        };
        XsDateFormat format = new XsDateFormat();
        Calendar expect = getCalendar(TimeZone.getTimeZone("GMT"));
        for (int i = 0;  i < dateTimes.length;  i++) {
            Calendar got = (Calendar) format.parseObject(dateTimes[0]);
            assertEqualDate(expect, got);
        }
        String dateTime = "2004-01-14-03:00";
        expect = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        Calendar got = (Calendar) format.parseObject(dateTime);
        assertEqualDate(expect, got);
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsTimeFormat#format(Object, StringBuffer, java.text.FieldPosition)}.
     */
    public void testFormatTime() {
        Calendar cal = getCalendar(TimeZone.getTimeZone("GMT"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        XsTimeFormat format = new XsTimeFormat();
        String got = format.format(cal);
        String expect = "03:12:07Z";
        assertEquals(expect, got);
        cal = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        assertEquals(0, cal.get(Calendar.MILLISECOND));
        got = format.format(cal);
        expect = "03:12:07-03:00";
        assertEquals(expect, got);
    }
    /** Test for
     * {@link org.apache.ws.jaxme.xs.util.XsTimeFormat#parseObject(String, java.text.ParsePosition)}.
     */
    public void testParseTime() throws ParseException {
        String[] dateTimes = new String[]{
      "03:12:07.000Z",
      "03:12:07",
      "03:12:07-00:00",
      "03:12:07+00:00",
        };
        XsTimeFormat format = new XsTimeFormat();
        Calendar expect = getCalendar(TimeZone.getTimeZone("GMT"));
        for (int i = 0;  i < dateTimes.length;  i++) {
            Calendar got = (Calendar) format.parseObject(dateTimes[0]);
            assertEqualTime(expect, got);
        }
        String dateTime = "03:12:07.000-03:00";
        expect = getCalendar(TimeZone.getTimeZone("GMT-03:00"));
        Calendar got = (Calendar) format.parseObject(dateTime);
        assertEqualTime(expect, got);
    }
    /** Tests, whether e zero as suffix matters in milliseconds.
     */
    public void testZeroSuffix() throws Exception {
        Format format = new XsDateTimeFormat();
        Calendar c1 = (Calendar) format.parseObject("2006-05-03T15:29:17.15Z");
        Calendar c2 = (Calendar) format.parseObject("2006-05-03T15:29:17.150Z");
        assertEquals(c1, c2);
        format = new XsTimeFormat();
        c1 = (Calendar) format.parseObject("15:29:17.15Z");
        c2 = (Calendar) format.parseObject("15:29:17.150Z");
        assertEquals(c1, c2);
    }
}