michael@0: /** michael@0: * Copyright (c) 2012, Ben Fortuna michael@0: * All rights reserved. michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions michael@0: * are met: michael@0: * michael@0: * o Redistributions of source code must retain the above copyright michael@0: * notice, this list of conditions and the following disclaimer. michael@0: * michael@0: * o Redistributions in binary form must reproduce the above copyright michael@0: * notice, this list of conditions and the following disclaimer in the michael@0: * documentation and/or other materials provided with the distribution. michael@0: * michael@0: * o Neither the name of Ben Fortuna nor the names of any other contributors michael@0: * may be used to endorse or promote products derived from this software michael@0: * without specific prior written permission. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR michael@0: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, michael@0: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, michael@0: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR michael@0: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF michael@0: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING michael@0: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS michael@0: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: package net.fortuna.ical4j.model; michael@0: michael@0: import java.text.DateFormat; michael@0: import java.util.Date; michael@0: michael@0: import net.fortuna.ical4j.util.CompatibilityHints; michael@0: import net.fortuna.ical4j.util.Dates; michael@0: import net.fortuna.ical4j.util.TimeZones; michael@0: michael@0: /** michael@0: * $Id$ michael@0: * michael@0: * Created on 30/06/2005 michael@0: * michael@0: * Base class for date and time representations as defined michael@0: * by the ISO 8601 standard. Sub-classes must ensure that either the correct michael@0: * precision is used in constructor arguments, or that Object.equals() michael@0: * is overridden to ensure equality checking is consistent with the type. michael@0: * @author Ben Fortuna michael@0: */ michael@0: public abstract class Iso8601 extends Date { michael@0: michael@0: /** michael@0: * michael@0: */ michael@0: private static final long serialVersionUID = -4290728005713946811L; michael@0: michael@0: private DateFormat format; michael@0: michael@0: private DateFormat gmtFormat; michael@0: michael@0: private int precision; michael@0: michael@0: /** michael@0: * @param time a time value in milliseconds michael@0: * @param pattern the formatting pattern to apply michael@0: * @param precision the precision to apply michael@0: * @param tz the timezone for the instance michael@0: * @see Dates#PRECISION_DAY michael@0: * @see Dates#PRECISION_SECOND michael@0: */ michael@0: public Iso8601(final long time, final String pattern, final int precision, java.util.TimeZone tz) { michael@0: super(Dates.round(time, precision, tz)); //, TimeZone.getTimeZone(TimeZones.GMT_ID))); michael@0: // format = new SimpleDateFormat(pattern); michael@0: format = CalendarDateFormatFactory.getInstance(pattern); michael@0: format.setTimeZone(tz); michael@0: format.setLenient(CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING)); michael@0: // use GMT timezone to avoid daylight savings rules affecting floating michael@0: // time values.. michael@0: // gmtFormat = new SimpleDateFormat(pattern); michael@0: // gmtFormat.setTimeZone(TimeZone.getTimeZone(TimeZones.GMT_ID)); michael@0: this.precision = precision; michael@0: } michael@0: michael@0: /** michael@0: * @param pattern the formatting pattern to apply michael@0: * @param precision the precision to apply michael@0: * @param tz the timezone for the instance michael@0: * @see Dates#PRECISION_DAY michael@0: * @see Dates#PRECISION_SECOND michael@0: */ michael@0: public Iso8601(final String pattern, final int precision, java.util.TimeZone tz) { michael@0: this(Dates.getCurrentTimeRounded(), pattern, precision, tz); michael@0: } michael@0: michael@0: /** michael@0: * @param time a time value as a date michael@0: * @param pattern the formatting pattern to apply michael@0: * @param precision the precision to apply michael@0: * @param tz the timezone for the instance michael@0: * @see Dates#PRECISION_DAY michael@0: * @see Dates#PRECISION_SECOND michael@0: */ michael@0: public Iso8601(final Date time, final String pattern, final int precision, java.util.TimeZone tz) { michael@0: this(time.getTime(), pattern, precision, tz); michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: public String toString() { michael@0: // if time is floating avoid daylight saving rules when generating michael@0: // string representation of date.. michael@3: final java.util.TimeZone timeZone = format.getTimeZone(); michael@3: if (!(timeZone instanceof TimeZone)) { michael@0: if (gmtFormat == null) { michael@0: gmtFormat = (DateFormat) format.clone(); michael@0: gmtFormat.setTimeZone(TimeZone.getTimeZone(TimeZones.GMT_ID)); michael@0: } michael@3: if (timeZone.inDaylightTime(this) michael@3: && timeZone.inDaylightTime(new Date(getTime() - 1))) { michael@3: michael@0: return gmtFormat.format(new Date(getTime() michael@3: + timeZone.getRawOffset() michael@3: + timeZone.getDSTSavings())); michael@0: // return format.format(new Date(getTime() - format.getTimeZone().getDSTSavings())); michael@0: } michael@0: // return gmtFormat.format(new Date(getTime() + format.getTimeZone().getOffset(getTime()))); michael@3: return gmtFormat.format(new Date(getTime() + timeZone.getRawOffset())); michael@0: } michael@0: return format.format(this); michael@0: } michael@0: michael@0: /** michael@0: * @return Returns the format. michael@0: */ michael@0: protected final DateFormat getFormat() { michael@0: return format; michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: public void setTime(final long time) { michael@0: // need to check for null format due to Android java.util.Date(long) constructor michael@0: // calling this method.. michael@0: if (format != null) { michael@0: super.setTime(Dates.round(time, precision, format.getTimeZone())); michael@0: } michael@0: else { michael@0: // XXX: what do we do here?? michael@0: super.setTime(time); michael@0: } michael@0: } michael@0: }