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.io.IOException; michael@0: import java.io.Serializable; michael@0: import java.text.DecimalFormat; michael@0: import java.text.NumberFormat; michael@0: michael@0: import net.fortuna.ical4j.util.Dates; michael@0: michael@4: import org.apache.commons.lang3.builder.HashCodeBuilder; michael@0: import org.apache.commons.logging.Log; michael@0: import org.apache.commons.logging.LogFactory; michael@0: michael@0: /** michael@0: * $Id$ michael@0: * michael@0: * Created on 26/06/2005 michael@0: * michael@0: * Represents a timezone offset from UTC time. michael@0: * michael@0: * @author Ben Fortuna michael@0: */ michael@0: public class UtcOffset implements Serializable { michael@0: michael@0: private static final long serialVersionUID = 5883111996721531728L; michael@0: michael@0: private static final int HOUR_START_INDEX = 1; michael@0: michael@0: private static final int HOUR_END_INDEX = 3; michael@0: michael@0: private static final int MINUTE_START_INDEX = 3; michael@0: michael@0: private static final int MINUTE_END_INDEX = 5; michael@0: michael@0: private static final int SECOND_START_INDEX = 5; michael@0: michael@0: private static final int SECOND_END_INDEX = 7; michael@0: michael@0: private static final NumberFormat HOUR_FORMAT = new DecimalFormat("00"); michael@0: michael@0: private static final NumberFormat MINUTE_FORMAT = new DecimalFormat("00"); michael@0: michael@0: private static final NumberFormat SECOND_FORMAT = new DecimalFormat("00"); michael@0: michael@0: private long offset; michael@0: michael@0: /** michael@0: * @param value a string representation of an offset michael@0: */ michael@0: public UtcOffset(final String value) { michael@0: michael@0: if (value.length() < MINUTE_END_INDEX) { michael@0: throw new IllegalArgumentException("Invalid UTC offset [" + value michael@0: + "] - must be of the form: (+/-)HHMM[SS]"); michael@0: } michael@0: michael@0: final boolean negative = value.charAt(0) == '-'; michael@0: michael@0: if (!negative && !(value.charAt(0) == '+')) { michael@0: throw new IllegalArgumentException("UTC offset value must be signed"); michael@0: } michael@0: michael@0: offset = 0; michael@0: offset += Integer.parseInt(value.substring(HOUR_START_INDEX, michael@0: HOUR_END_INDEX)) michael@0: * Dates.MILLIS_PER_HOUR; michael@0: offset += Integer.parseInt(value.substring(MINUTE_START_INDEX, michael@0: MINUTE_END_INDEX)) michael@0: * Dates.MILLIS_PER_MINUTE; michael@0: if (value.length() == SECOND_END_INDEX) { michael@0: offset += Integer.parseInt(value.substring(SECOND_START_INDEX, michael@0: SECOND_END_INDEX)) michael@0: * Dates.MILLIS_PER_SECOND; michael@0: } michael@0: if (negative) { michael@0: offset = -offset; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * @param offset an offset value in milliseconds michael@0: */ michael@0: public UtcOffset(final long offset) { michael@0: this.offset = (long) Math.floor(offset / (double) Dates.MILLIS_PER_SECOND) * Dates.MILLIS_PER_SECOND; michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: public final String toString() { michael@0: final StringBuffer b = new StringBuffer(); michael@0: long remainder = Math.abs(offset); michael@0: michael@0: if (offset < 0) { michael@0: b.append('-'); michael@0: } michael@0: else { michael@0: b.append('+'); michael@0: } michael@0: b.append(HOUR_FORMAT.format(remainder / Dates.MILLIS_PER_HOUR)); michael@0: michael@0: remainder = remainder % Dates.MILLIS_PER_HOUR; michael@0: b.append(MINUTE_FORMAT.format(remainder / Dates.MILLIS_PER_MINUTE)); michael@0: michael@0: remainder = remainder % Dates.MILLIS_PER_MINUTE; michael@0: if (remainder > 0) { michael@0: b.append(SECOND_FORMAT.format(remainder / Dates.MILLIS_PER_SECOND)); michael@0: } michael@0: return b.toString(); michael@0: } michael@0: michael@0: /** michael@0: * @return Returns the offset. michael@0: */ michael@0: public final long getOffset() { michael@0: return offset; michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: public final boolean equals(final Object arg0) { michael@0: if (arg0 instanceof UtcOffset) { michael@0: return getOffset() == ((UtcOffset) arg0).getOffset(); michael@0: } michael@0: return super.equals(arg0); michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: public final int hashCode() { michael@0: return new HashCodeBuilder().append(getOffset()).toHashCode(); michael@0: } michael@0: }