
net.sf.mpxj.Duration Maven / Gradle / Ivy
/*
* file: Duration.java
* author: Scott Melville
* Jon Iles
* copyright: (c) Packwood Software 2002-2003
* date: 15/08/2002
*/
/*
* This library 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.1 of the License, or (at your
* option) any later version.
*
* This library 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 this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
package net.sf.mpxj;
import net.sf.mpxj.common.NumberHelper;
/**
* This represents time durations as specified in an MPX file.
*/
public final class Duration implements Comparable
{
/**
* Constructs an instance of this class from a duration amount and
* time unit type.
*
* @param duration amount of duration
* @param type time unit of duration
*/
private Duration(double duration, TimeUnit type)
{
m_duration = duration;
m_units = type;
}
/**
* Constructs an instance of this class from a duration amount and
* time unit type.
*
* @param duration amount of duration
* @param type time unit of duration
*/
private Duration(int duration, TimeUnit type)
{
m_duration = duration;
m_units = type;
}
/**
* This method is used to retrieve the size of the duration.
*
* @return size of the duration
*/
public double getDuration()
{
return (m_duration);
}
/**
* This method is used to retrieve the type of units the duration
* is expressed in. The valid types of units are found in the TimeUnit
* class.
*
* @return type of units
*/
public TimeUnit getUnits()
{
return (m_units);
}
/**
* This method provides an approximate conversion between duration
* units. It does take into account the project defaults for number of hours
* in a day and a week, but it does not take account of calendar details.
* The results obtained from it should therefore be treated with caution.
*
* @param type target duration type
* @param defaults project properties containing default values
* @return new Duration instance
*/
public Duration convertUnits(TimeUnit type, TimeUnitDefaultsContainer defaults)
{
if (type == m_units)
{
return this;
}
return convertUnits(m_duration, m_units, type, defaults);
}
/**
* This method provides an approximate conversion between duration
* units. It does take into account the project defaults for number of hours
* in a day and a week, but it does not take account of calendar details.
* The results obtained from it should therefore be treated with caution.
*
* @param duration duration value
* @param fromUnits units to convert from
* @param toUnits units to convert to
* @param defaults project properties containing default values
* @return new Duration instance
*/
public static Duration convertUnits(double duration, TimeUnit fromUnits, TimeUnit toUnits, TimeUnitDefaultsContainer defaults)
{
return convertUnits(duration, fromUnits, toUnits, defaults.getMinutesPerDay().doubleValue(), defaults.getMinutesPerWeek().doubleValue(), defaults.getDaysPerMonth().doubleValue());
}
/**
* This method provides an approximate conversion between duration
* units. It does take into account the project defaults for number of hours
* in a day and a week, but it does not take account of calendar details.
* The results obtained from it should therefore be treated with caution.
*
* @param duration duration value
* @param fromUnits units to convert from
* @param toUnits units to convert to
* @param minutesPerDay number of minutes per day
* @param minutesPerWeek number of minutes per week
* @param daysPerMonth number of days per month
* @return new Duration instance
*/
public static Duration convertUnits(double duration, TimeUnit fromUnits, TimeUnit toUnits, double minutesPerDay, double minutesPerWeek, double daysPerMonth)
{
if (fromUnits == toUnits)
{
return Duration.getInstance(duration, fromUnits);
}
switch (fromUnits)
{
case YEARS:
{
duration *= (minutesPerWeek * 52);
break;
}
case ELAPSED_YEARS:
{
duration *= (60 * 24 * 7 * 52);
break;
}
case MONTHS:
{
duration *= (minutesPerDay * daysPerMonth);
break;
}
case ELAPSED_MONTHS:
{
duration *= (60 * 24 * 30);
break;
}
case WEEKS:
{
duration *= minutesPerWeek;
break;
}
case ELAPSED_WEEKS:
{
duration *= (60 * 24 * 7);
break;
}
case DAYS:
{
duration *= minutesPerDay;
break;
}
case ELAPSED_DAYS:
{
duration *= (60 * 24);
break;
}
case HOURS:
case ELAPSED_HOURS:
{
duration *= 60;
break;
}
default:
{
break;
}
}
if (toUnits != TimeUnit.MINUTES && toUnits != TimeUnit.ELAPSED_MINUTES)
{
switch (toUnits)
{
case HOURS:
case ELAPSED_HOURS:
{
duration /= 60;
break;
}
case DAYS:
{
if (minutesPerDay != 0)
{
duration /= minutesPerDay;
}
else
{
duration = 0;
}
break;
}
case ELAPSED_DAYS:
{
duration /= (60 * 24);
break;
}
case WEEKS:
{
if (minutesPerWeek != 0)
{
duration /= minutesPerWeek;
}
else
{
duration = 0;
}
break;
}
case ELAPSED_WEEKS:
{
duration /= (60 * 24 * 7);
break;
}
case MONTHS:
{
if (minutesPerDay != 0 && daysPerMonth != 0)
{
duration /= (minutesPerDay * daysPerMonth);
}
else
{
duration = 0;
}
break;
}
case ELAPSED_MONTHS:
{
duration /= (60 * 24 * 30);
break;
}
case YEARS:
{
if (minutesPerWeek != 0)
{
duration /= (minutesPerWeek * 52);
}
else
{
duration = 0;
}
break;
}
case ELAPSED_YEARS:
{
duration /= (60 * 24 * 7 * 52);
break;
}
default:
{
break;
}
}
}
return (Duration.getInstance(duration, toUnits));
}
/**
* Retrieve a Duration instance. Use shared objects to
* represent common values for memory efficiency.
*
* @param duration duration value
* @param type duration type
* @return Duration instance
*/
public static Duration getInstance(double duration, TimeUnit type)
{
Duration result;
if (duration == 0)
{
result = ZERO_DURATIONS[type.getValue()];
}
else
{
result = new Duration(duration, type);
}
return (result);
}
/**
* Retrieve a Duration instance. Use shared objects to
* represent common values for memory efficiency.
*
* @param duration duration value
* @param type duration type
* @return Duration instance
*/
public static Duration getInstance(int duration, TimeUnit type)
{
Duration result;
if (duration == 0)
{
result = ZERO_DURATIONS[type.getValue()];
}
else
{
result = new Duration(duration, type);
}
return (result);
}
@Override public boolean equals(Object o)
{
boolean result = false;
if (o instanceof Duration)
{
Duration rhs = (Duration) o;
result = durationComponentEquals(rhs) && m_units == rhs.m_units;
}
return result;
}
@Override public int hashCode()
{
return (m_units.getValue() + (int) m_duration);
}
@Override public int compareTo(Duration rhs)
{
if (m_units != rhs.m_units)
{
rhs = convertUnits(rhs.m_duration, rhs.m_units, m_units, (8 * 60), (5 * 8 * 60), 20);
}
return durationComponentEquals(rhs) ? 0 : m_duration < rhs.m_duration ? -1 : 1;
}
/**
* Equality test for duration component of a Duration instance.
* Note that this does not take into account the units - use with care!
*
* @param rhs duration to compare
* @return true if duration components are equal, within the allowable delta
*/
public boolean durationComponentEquals(Duration rhs)
{
return durationValueEquals(m_duration, rhs.m_duration);
}
/**
* Equality test for two duration values.
*
* @param lhs duration value
* @param rhs duration value
* @return true if duration values are equal, within the allowable delta
*/
public static boolean durationValueEquals(double lhs, double rhs)
{
return NumberHelper.equals(lhs, rhs, 0.00001);
}
/**
* If a and b are not null, returns a new duration of a + b.
* If a is null and b is not null, returns b.
* If a is not null and b is null, returns a.
* If a and b are null, returns null.
* If needed, b is converted to a's time unit using the project properties.
*
* @param a first duration
* @param b second duration
* @param defaults project properties containing default values
* @return a + b
*/
public static Duration add(Duration a, Duration b, TimeUnitDefaultsContainer defaults)
{
if (a == null && b == null)
{
return null;
}
if (a == null)
{
return b;
}
if (b == null)
{
return a;
}
TimeUnit unit = a.getUnits();
if (b.getUnits() != unit)
{
b = b.convertUnits(unit, defaults);
}
return Duration.getInstance(a.getDuration() + b.getDuration(), unit);
}
@Override public String toString()
{
return (m_duration + m_units.toString());
}
/**
* Duration amount.
*/
private final double m_duration;
/**
* Duration type.
*/
private final TimeUnit m_units;
private static final Duration[] ZERO_DURATIONS =
{
new Duration(0, TimeUnit.MINUTES),
new Duration(0, TimeUnit.HOURS),
new Duration(0, TimeUnit.DAYS),
new Duration(0, TimeUnit.WEEKS),
new Duration(0, TimeUnit.MONTHS),
new Duration(0, TimeUnit.YEARS),
new Duration(0, TimeUnit.PERCENT),
new Duration(0, TimeUnit.ELAPSED_MINUTES),
new Duration(0, TimeUnit.ELAPSED_HOURS),
new Duration(0, TimeUnit.ELAPSED_DAYS),
new Duration(0, TimeUnit.ELAPSED_WEEKS),
new Duration(0, TimeUnit.ELAPSED_MONTHS),
new Duration(0, TimeUnit.ELAPSED_YEARS),
new Duration(0, TimeUnit.ELAPSED_PERCENT)
};
}