All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.fortuna.ical4j.model.CalendarDateFormatFactory Maven / Gradle / Ivy

There is a newer version: 4.0.8
Show newest version
/**
 * Copyright (c) 2012, Ben Fortuna
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  o Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 *  o Neither the name of Ben Fortuna nor the names of any other contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package net.fortuna.ical4j.model;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * $Id$ [06-Apr-2004]
 * 

* Creates DateFormat objects optimized for common iCalendar date patterns. * * @author Dave Nault [email protected] * @see #getInstance(String) */ public final class CalendarDateFormatFactory { private static final Logger LOG = LoggerFactory.getLogger(CalendarDateFormatFactory.class); private static final String DATETIME_PATTERN = "yyyyMMdd'T'HHmmss"; private static final String DATETIME_UTC_PATTERN = "yyyyMMdd'T'HHmmss'Z'"; private static final String DATE_PATTERN = "yyyyMMdd"; private static final String TIME_PATTERN = "HHmmss"; private static final String TIME_UTC_PATTERN = "HHmmss'Z'"; /** * Constructor made private to enforce static nature. */ private CalendarDateFormatFactory() { } /** * Returns DateFormat objects optimized for common iCalendar date patterns. The DateFormats are *not* thread safe. * Attempts to get or set the Calendar or NumberFormat of an optimized DateFormat will result in an * UnsupportedOperation exception being thrown. * * @param pattern a SimpleDateFormat-compatible pattern * @return an optimized DateFormat instance if possible, otherwise a normal SimpleDateFormat instance */ public static java.text.DateFormat getInstance(String pattern) { java.text.DateFormat instance; // if (true) { // return new SimpleDateFormat(pattern); // } if (pattern.equals(DATETIME_PATTERN) || pattern.equals(DATETIME_UTC_PATTERN)) { instance = new DateTimeFormat(pattern); } else if (pattern.equals(DATE_PATTERN)) { instance = new DateFormat(pattern); } else if (pattern.equals(TIME_PATTERN) || pattern.equals(TIME_UTC_PATTERN)) { instance = new TimeFormat(pattern); } else { if (LOG.isDebugEnabled()) { LOG.debug("unexpected date format pattern: " + pattern); } instance = new SimpleDateFormat(pattern); } return instance; } private abstract static class CalendarDateFormat extends java.text.DateFormat { /** * */ private static final long serialVersionUID = -4191402739860280205L; private static final java.util.TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault(); private final String pattern; private boolean lenient = true; private java.util.TimeZone timeZone = DEFAULT_TIME_ZONE; public CalendarDateFormat(String pattern) { this.pattern = pattern; } public java.util.TimeZone getTimeZone() { return this.timeZone; } public void setTimeZone(java.util.TimeZone tz) { this.timeZone = tz; } public void setLenient(boolean lenient) { this.lenient = lenient; } public boolean isLenient() { return lenient; } public java.util.Calendar getCalendar() { throw new UnsupportedOperationException(); } public void setCalendar(java.util.Calendar c) { throw new UnsupportedOperationException(); } public NumberFormat getNumberFormat() { throw new UnsupportedOperationException(); } public void setNumberFormat(NumberFormat n) { throw new UnsupportedOperationException(); } public Object clone() { // don't call super.clone() final CalendarDateFormat f = (CalendarDateFormat) CalendarDateFormatFactory.getInstance(pattern); f.setTimeZone(getTimeZone()); f.setLenient(isLenient()); return f; } public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } final CalendarDateFormat that = (CalendarDateFormat) o; return lenient == that.lenient && pattern.equals(that.pattern) && timeZone.equals(that.timeZone); } public int hashCode() { int result = super.hashCode(); result = 31 * result + pattern.hashCode(); result = 31 * result + (lenient ? 1 : 0); result = 31 * result + timeZone.hashCode(); return result; } } /** * A custom date-time formatter. * Parses and formats these patterns: *

*

     * yyyyMMdd'T'HHmmss
     * yyyyMMdd'T'HHmmss'Z'
     * 
*/ private static class DateTimeFormat extends CalendarDateFormat { /** * */ private static final long serialVersionUID = 3005824302269636122L; final boolean patternEndsWithZ; public DateTimeFormat(String pattern) { super(pattern); patternEndsWithZ = pattern.endsWith("'Z'"); } public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { final java.util.Calendar cal = new GregorianCalendar(getTimeZone()); cal.setTimeInMillis(date.getTime()); appendPadded(toAppendTo, cal.get(GregorianCalendar.YEAR), 4); appendPadded(toAppendTo, cal.get(GregorianCalendar.MONTH) + 1, 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.DAY_OF_MONTH), 2); toAppendTo.append("T"); appendPadded(toAppendTo, cal.get(GregorianCalendar.HOUR_OF_DAY), 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.MINUTE), 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.SECOND), 2); if (patternEndsWithZ) { toAppendTo.append("Z"); } return toAppendTo; } public Date parse(String source, ParsePosition pos) { // if lenient ignore superfluous input.. if (patternEndsWithZ) { if (source.length() > DATETIME_UTC_PATTERN.length() && !isLenient()) { pos.setErrorIndex(DATETIME_UTC_PATTERN.length()); return null; } } else if (source.length() > DATETIME_PATTERN.length() && !isLenient()) { pos.setErrorIndex(DATETIME_PATTERN.length()); return null; } try { if (source.charAt(8) != 'T') { pos.setErrorIndex(8); return null; } if (patternEndsWithZ && source.charAt(15) != 'Z') { pos.setErrorIndex(15); return null; } final int year = Integer.parseInt(source.substring(0, 4)); final int month = Integer.parseInt(source.substring(4, 6)) - 1; final int day = Integer.parseInt(source.substring(6, 8)); final int hour = Integer.parseInt(source.substring(9, 11)); final int minute = Integer.parseInt(source.substring(11, 13)); final int second = Integer.parseInt(source.substring(13, 15)); final Date d = makeCalendar(isLenient(), getTimeZone(), year, month, day, hour, minute, second).getTime(); pos.setIndex(15); return d; } catch (Exception e) { return null; } } } /** * Custom date formatter. * Parses and formats this pattern: *

*

     * yyyyMMdd
     * 
*/ private static class DateFormat extends CalendarDateFormat { /** * */ private static final long serialVersionUID = -7626077667268431779L; public DateFormat(String pattern) { super(pattern); } public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { final java.util.Calendar cal = java.util.Calendar.getInstance(getTimeZone()); cal.setTimeInMillis(date.getTime()); appendPadded(toAppendTo, cal.get(GregorianCalendar.YEAR), 4); appendPadded(toAppendTo, cal.get(GregorianCalendar.MONTH) + 1, 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.DAY_OF_MONTH), 2); return toAppendTo; } public Date parse(String source, ParsePosition pos) { // if lenient ignore superfluous input.. if (source.length() > DATE_PATTERN.length() && !isLenient()) { pos.setErrorIndex(DATE_PATTERN.length()); return null; } try { final int year = Integer.parseInt(source.substring(0, 4)); final int month = Integer.parseInt(source.substring(4, 6)) - 1; final int day = Integer.parseInt(source.substring(6, 8)); final Date d = makeCalendar(isLenient(), getTimeZone(), year, month, day).getTime(); pos.setIndex(8); return d; } catch (Exception e) { return null; } } } /** * Custom time formatter. * Parses and formats these patterns: *

*

     * HHmmss
     * HHmmss'Z'
     * 
*/ private static class TimeFormat extends CalendarDateFormat { /** * */ private static final long serialVersionUID = -1367114409994225425L; final boolean patternEndsWithZ; public TimeFormat(String pattern) { super(pattern); patternEndsWithZ = pattern.endsWith("'Z'"); } public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { final java.util.Calendar cal = new GregorianCalendar(getTimeZone()); cal.setTimeInMillis(date.getTime()); appendPadded(toAppendTo, cal.get(GregorianCalendar.HOUR_OF_DAY), 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.MINUTE), 2); appendPadded(toAppendTo, cal.get(GregorianCalendar.SECOND), 2); if (patternEndsWithZ) { toAppendTo.append("Z"); } return toAppendTo; } public Date parse(String source, ParsePosition pos) { // if lenient ignore superfluous input.. if (patternEndsWithZ) { if (source.length() > TIME_UTC_PATTERN.length() && !isLenient()) { pos.setErrorIndex(TIME_UTC_PATTERN.length()); return null; } } else if (source.length() > TIME_PATTERN.length() && !isLenient()) { pos.setErrorIndex(TIME_PATTERN.length()); return null; } try { if (patternEndsWithZ && source.charAt(6) != 'Z') { pos.setErrorIndex(6); return null; } final int hour = Integer.parseInt(source.substring(0, 2)); final int minute = Integer.parseInt(source.substring(2, 4)); final int second = Integer.parseInt(source.substring(4, 6)); final Date d = makeCalendar(isLenient(), getTimeZone(), 1970, 0, 1, hour, minute, second).getTime(); pos.setIndex(6); return d; } catch (Exception e) { return null; } } } private static java.util.Calendar makeCalendar(boolean lenient, java.util.TimeZone timeZone, int year, int zeroBasedMonth, int day, int hour, int minutes, int seconds) { final java.util.Calendar cal = new GregorianCalendar(timeZone); cal.setLenient(lenient); cal.set(year, zeroBasedMonth, day, hour, minutes, seconds); cal.set(java.util.Calendar.MILLISECOND, 0); return cal; } private static java.util.Calendar makeCalendar(boolean lenient, TimeZone timeZone, int year, int month, int day) { return makeCalendar(lenient, timeZone, year, month, day, 0, 0, 0); } private static void appendPadded(StringBuffer toAppendTo, int value, int fieldWidth) { final String s = Integer.toString(value); final int max = fieldWidth - s.length(); for (int i = 0; i < max; i++) { toAppendTo.append("0"); } toAppendTo.append(s); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy