/* * TimeScale.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.evolution.util; /** * Class for defining and converting between time scales * * @version $Id: TimeScale.java,v 1.11 2005/05/24 20:25:57 rambaut Exp $ * * @author Alexei Drummond * @author Andrew Rambaut */ public class TimeScale implements Units { /** * Constructor for a timescale that starts at Jan 1st 1970. This constructor * can be used if we are not interested in absolute time. * param units The units * param backwards True if the timescale goes backwards in time */ public TimeScale(Type units, boolean backwards) { this(units, backwards, 0.0); } /** * Constructor for a timescale that starts at origin * param units The units * param backwards True if the timescale goes backwards in time * param origin The origin specified relative to 1970 in same units */ public TimeScale(Type units, boolean backwards, double origin) { this.units = units; this.backwards = backwards; this.origin = origin; } /** * Constructor for a timescale that starts at origin * param units The units * param backwards True if the timescale goes backwards in time * param origin The origin specified as a date */ public TimeScale(Type units, boolean backwards, java.util.Date origin) { this.units = units; this.backwards = backwards; long millisAhead = origin.getTime(); double daysAhead = ((double)millisAhead)/MILLIS_PER_DAY; switch (units) { case DAYS: this.origin = daysAhead; break; case MONTHS: this.origin = daysAhead / DAYS_PER_MONTH; break; case YEARS: this.origin = daysAhead / DAYS_PER_YEAR; break; default: throw new IllegalArgumentException(); } } /** * @return the units of this timescale */ public Type getUnits() { return units; } /** * Sets the units for this timescale. */ public void setUnits(Type units) { this.units = units; } /** * @return true if larger numbers represent older dates in this time scale. */ public boolean isBackwards() { return backwards; } /** * @return the date corresponding to the value zero in this time scale. */ public double getOrigin() { return origin; } /** * @return a time given in timescale scale as a time in this timescale */ public double convertTime(double time, TimeScale timeScale) { // make it forwards if (timeScale.isBackwards()) time = -time; // make it absolute time += timeScale.getOrigin(); // convert to the new timescale units double newTime = convertTimeUnits(time, getUnits(), timeScale.getUnits()); // make it relative newTime -= origin; // make it backwards if required if (backwards) newTime = -newTime; return newTime; } public String toString() { StringBuffer buffer = new StringBuffer("timescale("); buffer.append(unitString(0.0)); if (backwards) { buffer.append(", backwards"); } else { buffer.append(", forewards"); } buffer.append(" from " + origin + ")"); return buffer.toString(); } public String unitString(double time) { String unitString = null; switch (units) { case DAYS: unitString = "day"; break; case MONTHS: unitString = "month"; break; case YEARS: unitString = "year"; break; default: throw new IllegalArgumentException(); } if (time == 1.0) { return unitString; } else return unitString + "s"; } public static void main(String[] args) { TimeScale timeScale1 = new TimeScale(Units.Type.DAYS, true); TimeScale timeScale2 = new TimeScale(Units.Type.YEARS, true); System.out.println(timeScale1); System.out.println(timeScale2); double testTime = 100.0; System.out.println("Test time = " + testTime); System.out.println("timeScale1.convertTime(" + testTime + ", timeScale2)=" + timeScale1.convertTime(testTime, timeScale2)); System.out.println("timeScale2.convertTime(" + testTime + ", timeScale1)=" + timeScale2.convertTime(testTime, timeScale1)); } //************************************************************************* // STATIC STUFF //************************************************************************* /** * @return time in currentUnits as newUnits. */ public static double convertTimeUnits(double time, Type currentUnits, Type newUnits) { return time * getScale(currentUnits, newUnits); } /** * @return the scaling factor for converting currentUnits into newUnits. */ public static double getScale(Type currentUnits, Type newUnits) { if (currentUnits == newUnits) return 1.0; switch (currentUnits) { case DAYS: switch (newUnits) { case MONTHS: return 1.0/DAYS_PER_MONTH; case YEARS: return 1.0/DAYS_PER_YEAR; default: throw new IllegalArgumentException(); } case MONTHS: switch (newUnits) { case DAYS: return DAYS_PER_MONTH; case YEARS: return 1.0/MONTHS_PER_YEAR; default: throw new IllegalArgumentException(); } case YEARS: switch (newUnits) { case DAYS: return DAYS_PER_YEAR; case MONTHS: return MONTHS_PER_YEAR; default: throw new IllegalArgumentException(); } default: throw new IllegalArgumentException(); } } //************************************************************************* // PRIVATE STUFF //************************************************************************* // The origin is specified in days relative to 1st January 1970 protected double origin = 720035.0; protected Type units; protected boolean backwards; protected static double MILLIS_PER_DAY = 86400000.0; protected static double DAYS_PER_YEAR = 365.25; protected static double MONTHS_PER_YEAR = 12.0; protected static double DAYS_PER_MONTH = DAYS_PER_YEAR / MONTHS_PER_YEAR; }