View Javadoc

    1   /*
    2    * Copyright 2003, 2004  The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    * http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.codehaus.xfire.util.date;
    17
    18  import java.text.FieldPosition;
    19  import java.text.Format;
    20  import java.text.ParsePosition;
    21  import java.util.Calendar;
    22  import java.util.TimeZone;
    23
    24  /***
    25   * <p>
    26   * An instance of {@link java.text.Format}, which may be used to parse and
    27   * format <code>xs:dateTime</code> values.
    28   * </p>
    29   */
    30  public class XsDateTimeFormat
    31      extends Format
    32  {
    33      private static final long serialVersionUID = 3258131340871479609L;
    34
    35      final boolean parseDate;
    36
    37      final boolean parseTime;
    38
    39      XsDateTimeFormat(boolean pParseDate, boolean pParseTime)
    40      {
    41          parseDate = pParseDate;
    42          parseTime = pParseTime;
    43      }
    44
    45      /***
    46       * Creates a new instance.
    47       */
    48      public XsDateTimeFormat()
    49      {
    50          this(true, true);
    51      }
    52
    53      private int parseInt(String pString, int pOffset, StringBuffer pDigits)
    54      {
    55          int length = pString.length();
    56          pDigits.setLength(0);
    57          while (pOffset < length)
    58          {
    59              char c = pString.charAt(pOffset);
    60              if (Character.isDigit(c))
    61              {
    62                  pDigits.append(c);
    63                  ++pOffset;
    64              }
    65              else
    66              {
    67                  break;
    68              }
    69          }
    70          return pOffset;
    71      }
    72
    73      public Object parseObject(String pString, ParsePosition pParsePosition)
    74      {
    75          if (pString == null)
    76          {
    77              throw new NullPointerException("The String argument must not be null.");
    78          }
    79          if (pParsePosition == null)
    80          {
    81              throw new NullPointerException("The ParsePosition argument must not be null.");
    82          }
    83          int offset = pParsePosition.getIndex();
    84          int length = pString.length();
    85
    86          boolean isMinus = false;
    87          StringBuffer digits = new StringBuffer();
    88          int year, month, mday;
    89          if (parseDate)
    90          {
    91              // Sign
    92              if (offset < length)
    93              {
    94                  char c = pString.charAt(offset);
    95                  if (c == '+')
    96                  {
    97                      ++offset;
    98                  }
    99                  else if (c == '-')
    100                 {
    101                     ++offset;
    102                     isMinus = true;
    103                 }
    104             }
    105
    106             offset = parseInt(pString, offset, digits);
    107             if (digits.length() < 4)
    108             {
    109                 pParsePosition.setErrorIndex(offset);
    110                 return null;
    111             }
    112             year = Integer.parseInt(digits.toString());
    113
    114             if (offset < length && pString.charAt(offset) == '-')
    115             {
    116                 ++offset;
    117             }
    118             else
    119             {
    120                 pParsePosition.setErrorIndex(offset);
    121                 return null;
    122             }
    123
    124             offset = parseInt(pString, offset, digits);
    125             if (digits.length() != 2)
    126             {
    127                 pParsePosition.setErrorIndex(offset);
    128                 return null;
    129             }
    130             month = Integer.parseInt(digits.toString());
    131
    132             if (offset < length && pString.charAt(offset) == '-')
    133             {
    134                 ++offset;
    135             }
    136             else
    137             {
    138                 pParsePosition.setErrorIndex(offset);
    139                 return null;
    140             }
    141
    142             offset = parseInt(pString, offset, digits);
    143             if (digits.length() != 2)
    144             {
    145                 pParsePosition.setErrorIndex(offset);
    146                 return null;
    147             }
    148             mday = Integer.parseInt(digits.toString());
    149
    150             if (parseTime)
    151             {
    152                 if (offset < length && pString.charAt(offset) == 'T')
    153                 {
    154                     ++offset;
    155                 }
    156                 else
    157                 {
    158                     pParsePosition.setErrorIndex(offset);
    159                     return null;
    160                 }
    161             }
    162         }
    163         else
    164         {
    165             year = month = mday = 0;
    166         }
    167
    168         int hour, minute, second, millis;
    169         if (parseTime)
    170         {
    171             offset = parseInt(pString, offset, digits);
    172             if (digits.length() != 2)
    173             {
    174                 pParsePosition.setErrorIndex(offset);
    175                 return null;
    176             }
    177             hour = Integer.parseInt(digits.toString());
    178
    179             if (offset < length && pString.charAt(offset) == ':')
    180             {
    181                 ++offset;
    182             }
    183             else
    184             {
    185                 pParsePosition.setErrorIndex(offset);
    186                 return null;
    187             }
    188
    189             offset = parseInt(pString, offset, digits);
    190             if (digits.length() != 2)
    191             {
    192                 pParsePosition.setErrorIndex(offset);
    193                 return null;
    194             }
    195             minute = Integer.parseInt(digits.toString());
    196
    197             if (offset < length && pString.charAt(offset) == ':')
    198             {
    199                 ++offset;
    200             }
    201             else
    202             {
    203                 pParsePosition.setErrorIndex(offset);
    204                 return null;
    205             }
    206
    207             offset = parseInt(pString, offset, digits);
    208             if (digits.length() != 2)
    209             {
    210                 pParsePosition.setErrorIndex(offset);
    211                 return null;
    212             }
    213             second = Integer.parseInt(digits.toString());
    214
    215             if (offset < length && pString.charAt(offset) == '.')
    216             {
    217                 ++offset;
    218                 offset = parseInt(pString, offset, digits);
    219                 if (digits.length() > 0)
    220                 {
    221                     millis = Integer.parseInt(digits.toString());
    222                 }
    223                 else
    224                 {
    225                     millis = 0;
    226                 }
    227             }
    228             else
    229             {
    230                 millis = 0;
    231             }
    232         }
    233         else
    234         {
    235             hour = minute = second = millis = 0;
    236         }
    237
    238         digits.setLength(0);
    239         digits.append("GMT");
    240         if (offset < length)
    241         {
    242             char c = pString.charAt(offset);
    243             if (c == 'Z')
    244             {
    245                 // Ignore UTC, it is the default
    246                 ++offset;
    247             }
    248             else if (c == '+' || c == '-')
    249             {
    250                 digits.append(c);
    251                 ++offset;
    252                 for (int i = 0; i < 5; i++)
    253                 {
    254                     if (offset >= length)
    255                     {
    256                         pParsePosition.setErrorIndex(offset);
    257                         return null;
    258                     }
    259                     c = pString.charAt(offset);
    260                     if ((i != 2 && Character.isDigit(c)) || (i == 2 && c == ':'))
    261                     {
    262                         digits.append(c);
    263                     }
    264                     else
    265                     {
    266                         pParsePosition.setErrorIndex(offset);
    267                         return null;
    268                     }
    269                     ++offset;
    270                 }
    271             }
    272         }
    273
    274         Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(digits.toString()));
    275         cal.set(isMinus ? -year : year, parseDate ? month - 1 : month, mday, hour, minute, second);
    276         cal.set(Calendar.MILLISECOND, millis);
    277         pParsePosition.setIndex(offset);
    278         return cal;
    279     }
    280
    281     private void append(StringBuffer pBuffer, int pNum, int pMinLen)
    282     {
    283         String s = Integer.toString(pNum);
    284         for (int i = s.length(); i < pMinLen; i++)
    285         {
    286             pBuffer.append('0');
    287         }
    288         pBuffer.append(s);
    289     }
    290
    291     public StringBuffer format(Object pCalendar, StringBuffer pBuffer, FieldPosition pPos)
    292     {
    293         if (pCalendar == null)
    294         {
    295             throw new NullPointerException("The Calendar argument must not be null.");
    296         }
    297         if (pBuffer == null)
    298         {
    299             throw new NullPointerException("The StringBuffer argument must not be null.");
    300         }
    301         if (pPos == null)
    302         {
    303             throw new NullPointerException("The FieldPosition argument must not be null.");
    304         }
    305
    306         Calendar cal = (Calendar) pCalendar;
    307         if (parseDate)
    308         {
    309             int year = cal.get(Calendar.YEAR);
    310             if (year < 0)
    311             {
    312                 pBuffer.append('-');
    313                 year = -year;
    314             }
    315             append(pBuffer, year, 4);
    316             pBuffer.append('-');
    317             append(pBuffer, cal.get(Calendar.MONTH) + 1, 2);
    318             pBuffer.append('-');
    319             append(pBuffer, cal.get(Calendar.DAY_OF_MONTH), 2);
    320             if (parseTime)
    321             {
    322                 pBuffer.append('T');
    323             }
    324         }
    325         if (parseTime)
    326         {
    327             append(pBuffer, cal.get(Calendar.HOUR_OF_DAY), 2);
    328             pBuffer.append(':');
    329             append(pBuffer, cal.get(Calendar.MINUTE), 2);
    330             pBuffer.append(':');
    331             append(pBuffer, cal.get(Calendar.SECOND), 2);
    332             int millis = cal.get(Calendar.MILLISECOND);
    333             if (millis > 0)
    334             {
    335                 pBuffer.append('.');
    336                 append(pBuffer, millis, 3);
    337             }
    338         }
    339         TimeZone tz = cal.getTimeZone();
    340         // JDK 1.4: int offset = tz.getOffset(cal.getTimeInMillis());
    341         int offset = cal.get(Calendar.ZONE_OFFSET);
    342         if (tz.inDaylightTime(cal.getTime()))
    343         {
    344             offset += cal.get(Calendar.DST_OFFSET);
    345         }
    346         if (offset == 0)
    347         {
    348             pBuffer.append('Z');
    349         }
    350         else
    351         {
    352             if (offset < 0)
    353             {
    354                 pBuffer.append('-');
    355                 offset = -offset;
    356             }
    357             else
    358             {
    359                 pBuffer.append('+');
    360             }
    361             int minutes = offset / (60 * 1000);
    362             int hours = minutes / 60;
    363             minutes -= hours * 60;
    364             append(pBuffer, hours, 2);
    365             pBuffer.append(':');
    366             append(pBuffer, minutes, 2);
    367         }
    368         return pBuffer;
    369     }
    370 }