src/net/fortuna/ical4j/model/CalendarDateFormatFactory.java

Tue, 10 Feb 2015 19:58:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 10 Feb 2015 19:58:00 +0100
changeset 4
45d57ecba757
permissions
-rw-r--r--

Upgrade the upgraded ical4j component to use org.apache.commons.lang3.

     1 /**
     2  * Copyright (c) 2012, Ben Fortuna
     3  * All rights reserved.
     4  *
     5  * Redistribution and use in source and binary forms, with or without
     6  * modification, are permitted provided that the following conditions
     7  * are met:
     8  *
     9  *  o Redistributions of source code must retain the above copyright
    10  * notice, this list of conditions and the following disclaimer.
    11  *
    12  *  o Redistributions in binary form must reproduce the above copyright
    13  * notice, this list of conditions and the following disclaimer in the
    14  * documentation and/or other materials provided with the distribution.
    15  *
    16  *  o Neither the name of Ben Fortuna nor the names of any other contributors
    17  * may be used to endorse or promote products derived from this software
    18  * without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  */
    32 package net.fortuna.ical4j.model;
    34 import java.text.FieldPosition;
    35 import java.text.NumberFormat;
    36 import java.text.ParsePosition;
    37 import java.text.SimpleDateFormat;
    38 import java.util.Date;
    39 import java.util.GregorianCalendar;
    40 import java.util.TimeZone;
    42 import org.apache.commons.logging.Log;
    43 import org.apache.commons.logging.LogFactory;
    45 /**
    46  * $Id$ [06-Apr-2004]
    47  * 
    48  * Creates DateFormat objects optimized for common iCalendar date patterns.
    49  * 
    50  * @author Dave Nault dnault@laszlosystems.com
    51  * @see #getInstance(String)
    52  */
    53 public final class CalendarDateFormatFactory {
    54     private static final Log LOG = LogFactory.getLog(CalendarDateFormatFactory.class);
    56     private static final String DATETIME_PATTERN = "yyyyMMdd'T'HHmmss";
    57     private static final String DATETIME_UTC_PATTERN = "yyyyMMdd'T'HHmmss'Z'";
    58     private static final String DATE_PATTERN = "yyyyMMdd";
    59     private static final String TIME_PATTERN = "HHmmss";
    60     private static final String TIME_UTC_PATTERN = "HHmmss'Z'";
    62     /**
    63      * Constructor made private to enforce static nature.
    64      */
    65     private CalendarDateFormatFactory() {
    66     }
    68     /**
    69      * Returns DateFormat objects optimized for common iCalendar date patterns. The DateFormats are *not* thread safe.
    70      * Attempts to get or set the Calendar or NumberFormat of an optimized DateFormat will result in an
    71      * UnsupportedOperation exception being thrown.
    72      * 
    73      * @param pattern
    74      *            a SimpleDateFormat-compatible pattern
    75      * @return an optimized DateFormat instance if possible, otherwise a normal SimpleDateFormat instance
    76      */
    77     public static java.text.DateFormat getInstance(String pattern) {
    78         java.text.DateFormat instance = null;
    80         // if (true) {
    81         // return new SimpleDateFormat(pattern);
    82         // }
    84         if (pattern.equals(DATETIME_PATTERN) || pattern.equals(DATETIME_UTC_PATTERN)) {
    85             instance = new DateTimeFormat(pattern);
    86         }
    87         else if (pattern.equals(DATE_PATTERN)) {
    88             instance = new DateFormat(pattern);
    89         }
    90         else if (pattern.equals(TIME_PATTERN) || pattern.equals(TIME_UTC_PATTERN)) {
    91             instance = new TimeFormat(pattern);
    92         }
    93         else {
    94             if (LOG.isDebugEnabled()) {
    95                 LOG.debug("unexpected date format pattern: " + pattern);
    96             }
    98             instance = new SimpleDateFormat(pattern);
    99         }
   100         return instance;
   101     }
   103     private abstract static class CalendarDateFormat extends java.text.DateFormat {
   104         /**
   105 		 * 
   106 		 */
   107         private static final long serialVersionUID = -4191402739860280205L;
   109         private static final java.util.TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault();
   111         private final String pattern;
   113         private boolean lenient = true;
   115         private java.util.TimeZone timeZone = DEFAULT_TIME_ZONE;
   117         public CalendarDateFormat(String pattern) {
   118             this.pattern = pattern;
   119         }
   121         public java.util.TimeZone getTimeZone() {
   122             return this.timeZone;
   123         }
   125         public void setTimeZone(java.util.TimeZone tz) {
   126             this.timeZone = tz;
   127         }
   129         public void setLenient(boolean lenient) {
   130             this.lenient = lenient;
   131         }
   133         public boolean isLenient() {
   134             return lenient;
   135         }
   137         public java.util.Calendar getCalendar() {
   138             throw new UnsupportedOperationException();
   139         }
   141         public void setCalendar(java.util.Calendar c) {
   142             throw new UnsupportedOperationException();
   143         }
   145         public NumberFormat getNumberFormat() {
   146             throw new UnsupportedOperationException();
   147         }
   149         public void setNumberFormat(NumberFormat n) {
   150             throw new UnsupportedOperationException();
   151         }
   153         public Object clone() {
   154             // don't call super.clone()
   155             final CalendarDateFormat f = (CalendarDateFormat) CalendarDateFormatFactory.getInstance(pattern);
   156             f.setTimeZone(getTimeZone());
   157             f.setLenient(isLenient());
   158             return f;
   159         }
   161         public boolean equals(Object o) {
   162             if (this == o) {
   163                 return true;
   164             }
   165             if (o == null || getClass() != o.getClass()) {
   166                 return false;
   167             }
   168             if (!super.equals(o)) {
   169                 return false;
   170             }
   172             final CalendarDateFormat that = (CalendarDateFormat) o;
   174             if (lenient != that.lenient) {
   175                 return false;
   176             }
   177             if (!pattern.equals(that.pattern)) {
   178                 return false;
   179             }
   180             if (!timeZone.equals(that.timeZone)) {
   181                 return false;
   182             }
   184             return true;
   185         }
   187         public int hashCode() {
   188             int result = super.hashCode();
   189             result = 31 * result + pattern.hashCode();
   190             result = 31 * result + (lenient ? 1 : 0);
   191             result = 31 * result + timeZone.hashCode();
   192             return result;
   193         }
   194     }
   196     /**
   197      * A custom date-time formatter.
   198      * Parses and formats these patterns:
   199      * 
   200      * <pre>
   201      * yyyyMMdd'T'HHmmss
   202      * yyyyMMdd'T'HHmmss'Z'
   203      * </pre>
   204      */
   205     private static class DateTimeFormat extends CalendarDateFormat {
   207         /**
   208 		 * 
   209 		 */
   210         private static final long serialVersionUID = 3005824302269636122L;
   212         final boolean patternEndsWithZ;
   214         public DateTimeFormat(String pattern) {
   215             super(pattern);
   216             patternEndsWithZ = pattern.endsWith("'Z'");
   217         }
   219         public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
   220             final java.util.Calendar cal = new GregorianCalendar(getTimeZone());
   221             cal.setTimeInMillis(date.getTime());
   223             appendPadded(toAppendTo, cal.get(GregorianCalendar.YEAR), 4);
   224             appendPadded(toAppendTo, cal.get(GregorianCalendar.MONTH) + 1, 2);
   225             appendPadded(toAppendTo, cal.get(GregorianCalendar.DAY_OF_MONTH), 2);
   226             toAppendTo.append("T");
   228             appendPadded(toAppendTo, cal.get(GregorianCalendar.HOUR_OF_DAY), 2);
   229             appendPadded(toAppendTo, cal.get(GregorianCalendar.MINUTE), 2);
   230             appendPadded(toAppendTo, cal.get(GregorianCalendar.SECOND), 2);
   232             if (patternEndsWithZ) {
   233                 toAppendTo.append("Z");
   234             }
   236             return toAppendTo;
   237         }
   239         public Date parse(String source, ParsePosition pos) {
   240             // if lenient ignore superfluous input..
   241             if (patternEndsWithZ) {
   242                 if (source.length() > DATETIME_UTC_PATTERN.length() && !isLenient()) {
   243                     pos.setErrorIndex(DATETIME_UTC_PATTERN.length());
   244                     return null;
   245                 }
   246             } else if (source.length() > DATETIME_PATTERN.length() && !isLenient()) {
   247                 pos.setErrorIndex(DATETIME_PATTERN.length());
   248                 return null;
   249             }
   251             try {
   252                 if (source.charAt(8) != 'T') {
   253                     pos.setErrorIndex(8);
   254                     return null;
   255                 }
   256                 if (patternEndsWithZ && source.charAt(15) != 'Z') {
   257                     pos.setErrorIndex(15);
   258                     return null;
   259                 }
   261                 final int year = Integer.parseInt(source.substring(0, 4));
   262                 final int month = Integer.parseInt(source.substring(4, 6)) - 1;
   263                 final int day = Integer.parseInt(source.substring(6, 8));
   264                 final int hour = Integer.parseInt(source.substring(9, 11));
   265                 final int minute = Integer.parseInt(source.substring(11, 13));
   266                 final int second = Integer.parseInt(source.substring(13, 15));
   268                 final Date d = makeCalendar(isLenient(), getTimeZone(),
   269                         year, month, day, hour, minute, second).getTime();
   270                 pos.setIndex(15);
   271                 return d;
   272             } catch (Exception e) {
   273                 return null;
   274             }
   275         }
   276     }
   278     /**
   279      * Custom date formatter.
   280      * Parses and formats this pattern:
   281      * 
   282      * <pre>
   283      * yyyyMMdd
   284      * </pre>
   285      */
   286     private static class DateFormat extends CalendarDateFormat {
   288         /**
   289 		 * 
   290 		 */
   291         private static final long serialVersionUID = -7626077667268431779L;
   293         public DateFormat(String pattern) {
   294             super(pattern);
   295         }
   297         public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
   298             final java.util.Calendar cal = java.util.Calendar.getInstance(getTimeZone());
   299             cal.setTimeInMillis(date.getTime());
   301             appendPadded(toAppendTo, cal.get(GregorianCalendar.YEAR), 4);
   302             appendPadded(toAppendTo, cal.get(GregorianCalendar.MONTH) + 1, 2);
   303             appendPadded(toAppendTo, cal.get(GregorianCalendar.DAY_OF_MONTH), 2);
   305             return toAppendTo;
   306         }
   308         public Date parse(String source, ParsePosition pos) {
   309             // if lenient ignore superfluous input..
   310             if (source.length() > DATE_PATTERN.length() && !isLenient()) {
   311                 pos.setErrorIndex(DATE_PATTERN.length());
   312                 return null;
   313             }
   315             try {
   316                 final int year = Integer.parseInt(source.substring(0, 4));
   317                 final int month = Integer.parseInt(source.substring(4, 6)) - 1;
   318                 final int day = Integer.parseInt(source.substring(6, 8));
   320                 final Date d = makeCalendar(isLenient(), getTimeZone(), year, month, day).getTime();
   321                 pos.setIndex(8);
   322                 return d;
   323             } catch (Exception e) {
   324                 return null;
   325             }
   326         }
   327     }
   329     /**
   330      * Custom time formatter.
   331      * Parses and formats these patterns:
   332      * 
   333      * <pre>
   334      * HHmmss
   335      * HHmmss'Z'
   336      * </pre>
   337      */
   338     private static class TimeFormat extends CalendarDateFormat {
   340         /**
   341 		 * 
   342 		 */
   343         private static final long serialVersionUID = -1367114409994225425L;
   345         final boolean patternEndsWithZ;
   347         public TimeFormat(String pattern) {
   348             super(pattern);
   349             patternEndsWithZ = pattern.endsWith("'Z'");
   350         }
   352         public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
   353             final java.util.Calendar cal = new GregorianCalendar(getTimeZone());
   354             cal.setTimeInMillis(date.getTime());
   356             appendPadded(toAppendTo, cal.get(GregorianCalendar.HOUR_OF_DAY), 2);
   357             appendPadded(toAppendTo, cal.get(GregorianCalendar.MINUTE), 2);
   358             appendPadded(toAppendTo, cal.get(GregorianCalendar.SECOND), 2);
   360             if (patternEndsWithZ) {
   361                 toAppendTo.append("Z");
   362             }
   364             return toAppendTo;
   365         }
   367         public Date parse(String source, ParsePosition pos) {
   368             // if lenient ignore superfluous input..
   369             if (patternEndsWithZ) {
   370                 if (source.length() > TIME_UTC_PATTERN.length() && !isLenient()) {
   371                     pos.setErrorIndex(TIME_UTC_PATTERN.length());
   372                     return null;
   373                 }
   374             } else if (source.length() > TIME_PATTERN.length() && !isLenient()) {
   375                 pos.setErrorIndex(TIME_PATTERN.length());
   376                 return null;
   377             }
   379             try {
   380                 if (patternEndsWithZ && source.charAt(6) != 'Z') {
   381                     pos.setErrorIndex(6);
   382                     return null;
   383                 }
   385                 final int hour = Integer.parseInt(source.substring(0, 2));
   386                 final int minute = Integer.parseInt(source.substring(2, 4));
   387                 final int second = Integer.parseInt(source.substring(4, 6));
   389                 final Date d = makeCalendar(isLenient(), getTimeZone(), 1970, 0, 1, hour, minute, second).getTime();
   390                 pos.setIndex(6);
   391                 return d;
   392             } catch (Exception e) {
   393                 return null;
   394             }
   395         }
   396     }
   398     private static java.util.Calendar makeCalendar(boolean lenient, java.util.TimeZone timeZone, int year,
   399             int zeroBasedMonth, int day, int hour, int minutes, int seconds) {
   400         final java.util.Calendar cal = new GregorianCalendar(timeZone);
   401         cal.setLenient(lenient);
   402         cal.set(year, zeroBasedMonth, day, hour, minutes, seconds);
   403         cal.set(java.util.Calendar.MILLISECOND, 0);
   404         return cal;
   405     }
   407     private static java.util.Calendar makeCalendar(boolean lenient, TimeZone timeZone, int year, int month, int day) {
   408         return makeCalendar(lenient, timeZone, year, month, day, 0, 0, 0);
   409     }
   411     private static void appendPadded(StringBuffer toAppendTo, int value, int fieldWidth) {
   412         final String s = Integer.toString(value);
   413         final int max = fieldWidth - s.length();
   414         for (int i = 0; i < max; i++) {
   415             toAppendTo.append("0");
   416         }
   417         toAppendTo.append(s);
   418     }
   420 }

mercurial