tikhomirov@211: /* tikhomirov@211: * Copyright (c) 2011 TMate Software Ltd tikhomirov@211: * tikhomirov@211: * This program is free software; you can redistribute it and/or modify tikhomirov@211: * it under the terms of the GNU General Public License as published by tikhomirov@211: * the Free Software Foundation; version 2 of the License. tikhomirov@211: * tikhomirov@211: * This program is distributed in the hope that it will be useful, tikhomirov@211: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@211: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@211: * GNU General Public License for more details. tikhomirov@211: * tikhomirov@211: * For information on how to redistribute this software under tikhomirov@211: * the terms of a license other than GNU General Public License tikhomirov@211: * contact TMate Software at support@hg4j.com tikhomirov@211: */ tikhomirov@211: package org.tmatesoft.hg.core; tikhomirov@211: tikhomirov@211: import java.util.Calendar; tikhomirov@211: import java.util.Formatter; tikhomirov@211: import java.util.Locale; tikhomirov@211: import java.util.TimeZone; tikhomirov@211: tikhomirov@211: /** tikhomirov@211: * Compound object to keep time and time zone of a change. Time zone is not too useful unless you'd like to indicate where tikhomirov@211: * the change was made (original hg shows date of a change in its original time zone) tikhomirov@211: * tikhomirov@211: * @author Artem Tikhomirov tikhomirov@211: * @author TMate Software Ltd. tikhomirov@211: */ tikhomirov@211: public final class HgDate implements Comparable, Cloneable { tikhomirov@211: private final long time; tikhomirov@211: private final TimeZone tzone; tikhomirov@211: tikhomirov@211: tikhomirov@211: /** tikhomirov@211: * @param millis UTC, milliseconds tikhomirov@211: * @param timezone zone offset in seconds, UTC - local == timezone. I.e. positive in the Western Hemisphere. tikhomirov@211: */ tikhomirov@211: public HgDate(long millis, int timezone) { tikhomirov@211: time = millis; tikhomirov@211: // @see http://pydoc.org/2.5.1/time.html time.timezone -- difference in seconds between UTC and local standard time tikhomirov@211: // UTC - local = timezone. local = UTC - timezone tikhomirov@211: // In Java, timezone is positive right of Greenwich, UTC+timezone = local tikhomirov@214: // tikhomirov@214: // tikhomirov@214: /* tikhomirov@214: * The approach with available-short didn't work out as final timezone still relied tikhomirov@214: * on daylight saving settings (and added/substracted hour shift according to date supplied) tikhomirov@214: * E.g. 1218917104000 in zone GMT+2 (hello sample, changeset #2), results in EET timezone and 23 hours instead of 22 tikhomirov@214: * tikhomirov@211: String[] available = TimeZone.getAvailableIDs(-timezone * 1000); tikhomirov@211: assert available != null && available.length > 0 : String.valueOf(timezone); tikhomirov@214: // this is sort of hack, I don't know another way how to get tikhomirov@211: // abbreviated name from zone offset (other than to have own mapping) tikhomirov@211: // And I can't use any id, because e.g. zone with id "US/Mountain" tikhomirov@211: // gives incorrect (according to hg cmdline) result, unlike MST or US/Arizona (all ids for zone -0700) tikhomirov@211: // use 1125044450000L to see the difference tikhomirov@211: String shortID = TimeZone.getTimeZone(available[0]).getDisplayName(false, TimeZone.SHORT); tikhomirov@211: // XXX in fact, might need to handle daylight saving time, but not sure how, tikhomirov@211: // getTimeZone(GMT-timezone*1000).inDaylightTime()? tikhomirov@211: TimeZone tz = TimeZone.getTimeZone(shortID); tikhomirov@214: */ tikhomirov@214: int tz_hours = -timezone/3600; tikhomirov@214: int tz_mins = timezone % 3600; tikhomirov@214: String customId = String.format("GMT%+02d:%02d", tz_hours, tz_mins); tikhomirov@214: TimeZone tz = TimeZone.getTimeZone(customId); tikhomirov@211: tzone = tz; tikhomirov@211: } tikhomirov@211: tikhomirov@211: public long getRawTime() { tikhomirov@211: return time; tikhomirov@211: } tikhomirov@211: tikhomirov@211: /** tikhomirov@211: * @return zone object by reference, do not alter it (make own copy by {@link TimeZone#clone()}, to modify). tikhomirov@211: */ tikhomirov@211: public TimeZone getTimeZone() { tikhomirov@211: return tzone; tikhomirov@211: } tikhomirov@211: tikhomirov@211: @Override tikhomirov@211: public String toString() { tikhomirov@211: // format the same way hg does tikhomirov@211: return toString(Locale.US); tikhomirov@211: } tikhomirov@211: tikhomirov@211: public String toString(Locale l) { tikhomirov@211: Calendar c = Calendar.getInstance(getTimeZone()); tikhomirov@211: c.setTimeInMillis(getRawTime()); tikhomirov@211: Formatter f = new Formatter(new StringBuilder(), l); tikhomirov@211: f.format("%ta %> 32); tikhomirov@211: } tikhomirov@211: tikhomirov@211: @Override tikhomirov@211: protected Object clone() { tikhomirov@211: try { tikhomirov@211: return super.clone(); tikhomirov@211: } catch (CloneNotSupportedException ex) { tikhomirov@211: throw new InternalError(ex.toString()); tikhomirov@211: } tikhomirov@211: } tikhomirov@211: }