
ucar.nc2.time.CalendarPeriod Maven / Gradle / Ivy
/*
* Copyright (c) 1998 - 2011. University Corporation for Atmospheric Research/Unidata
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.time;
import net.jcip.annotations.Immutable;
import org.joda.time.DurationFieldType;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import ucar.unidata.util.StringUtil2;
/**
* A CalendarPeriod is a logical duration of time, it requires a Calendar to convert to an actual duration of time.
* A CalendarField is expressed as {integer x Field}.
*
* Design follows joda Period class.
* @author caron
* @since 3/30/11
*/
@Immutable
public class CalendarPeriod {
static private final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CalendarPeriod.class);
static public final CalendarPeriod Hour = CalendarPeriod.of(1, Field.Hour);
public enum Field {
Millisec(PeriodType.millis()), Second(PeriodType.seconds()), Minute(PeriodType.minutes()), Hour(PeriodType.hours()),
Day(PeriodType.days()), Month(PeriodType.months()), Year(PeriodType.years());
PeriodType p;
Field(PeriodType p) {
this.p = p;
}
}
/**
* Convert a period string into a CalendarPeriod.Field.
* @param udunit period string
* @return CalendarPeriod.Field enum
* @throws IllegalArgumentException if not valid format
*/
public static CalendarPeriod.Field fromUnitString(String udunit) {
udunit = udunit.trim();
udunit = udunit.toLowerCase();
if (udunit.equals("s")) return Field.Second;
if (udunit.equals("ms")) return Field.Millisec;
// eliminate plurals
if (udunit.endsWith("s")) udunit = udunit.substring(0, udunit.length()-1);
if (udunit.equals("second") || udunit.equals("sec")) {
return Field.Second;
} else if (udunit.equals("millisec") || udunit.equals("msec")) {
return Field.Millisec;
} else if (udunit.equals("minute") || udunit.equals("min")) {
return Field.Minute;
} else if (udunit.equals("hour") || udunit.equals("hr") || udunit.equals("h")) {
return Field.Hour;
} else if (udunit.equals("day") || udunit.equals("d")) {
return Field.Day;
} else if (udunit.equals("month") || udunit.equals("mon")) {
return Field.Month;
} else if (udunit.equals("year") || udunit.equals("yr")) {
return Field.Year;
} else {
throw new IllegalArgumentException("cant convert "+ udunit +" to CalendarPeriod");
}
}
public static CalendarPeriod of(int value, Field field) {
return new CalendarPeriod(value, field);
}
/**
* Convert a udunit period string into a CalendarPeriod
* @param udunit period string : "[val] unit"
* @return CalendarPeriod or null if illegal
*/
public static CalendarPeriod of(String udunit) {
int value;
String units;
String[] split = StringUtil2.splitString(udunit);
if (split.length == 1) {
value = 1;
units = split[0];
} else if (split.length == 2) {
try {
value = Integer.parseInt(split[0]);
} catch (Throwable t) {
return null;
}
units = split[1];
} else
return null;
CalendarPeriod.Field unit = CalendarPeriod.fromUnitString(units);
return CalendarPeriod.of(value, unit);
}
////////////////////////
// the common case is a single field
private final int value;
private final Field field;
private CalendarPeriod (int value, Field field) {
this.value = value;
this.field = field;
}
/**
* Multiply the period by an integer
* @param value multiply by this
* @return new period
*/
public CalendarPeriod multiply(int value) {
return new CalendarPeriod(this.value * value, this.field);
}
public int getValue() {
return value;
}
public Field getField() {
return field;
}
/**
* Subtract two dates, return difference in units of this period.
* If not even, will round down and log a warning
* @param start start date
* @param end end date
* @return difference in units of this period
*/
public int subtract(CalendarDate start, CalendarDate end) {
long diff = end.getDifferenceInMsecs(start);
int thislen = millisecs();
if ((diff % thislen != 0))
log.warn("roundoff error");
return (int) (diff / thislen);
}
/**
* Get the conversion factor of the other CalendarPeriod to this one
* @param from convert from this
* @return conversion factor, so that getConvertFactor(from) * from = this
*/
public double getConvertFactor(CalendarPeriod from) {
if (field == CalendarPeriod.Field.Month || field == CalendarPeriod.Field.Year) {
log.warn(" CalendarDate.convert on Month or Year");
}
return (double)from.millisecs() / millisecs();
}
/**
* Get the duration in seconds -+
* @return the duration in seconds
* @deprecated dont use because these are fixed length and thus approximate.
*/
public double getValueInMillisecs() {
if (field == CalendarPeriod.Field.Month)
return 30.0 * 24.0 * 60.0 * 60.0 * 1000.0 * value;
else if (field == CalendarPeriod.Field.Year)
return 365.0 * 24.0 * 60.0 * 60.0 * 1000.0 * value;
else return millisecs();
}
private int millisecs() {
if (field == CalendarPeriod.Field.Millisec)
return value;
else if (field == CalendarPeriod.Field.Second)
return 1000 * value;
else if (field == CalendarPeriod.Field.Minute)
return 60 * 1000 * value;
else if (field == CalendarPeriod.Field.Hour)
return 60 * 60 * 1000 * value;
else if (field == CalendarPeriod.Field.Day)
return 24 * 60 * 60 * 1000 * value;
else throw new IllegalStateException("Illegal Field = "+field);
}
// offset from start to end, in these units
public int getOffset(CalendarDate start, CalendarDate end) {
Period p = new Period(start.getDateTime(), end.getDateTime(), getPeriodType());
return p.get(getDurationFieldType());
}
PeriodType getPeriodType() {
return getField().p;
}
DurationFieldType getDurationFieldType() {
return getField().p.getFieldType(0);
}
@Override
public String toString() {
return value + " " + field;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CalendarPeriod that = (CalendarPeriod) o;
if (value != that.value) return false;
if (field != that.field) return false;
return true;
}
@Override
public int hashCode() {
int result = value;
result = 31 * result + (field != null ? field.hashCode() : 0);
return result;
}
public static void main(String[] args) {
CalendarPeriod cp = new CalendarPeriod(1, Field.Day);
CalendarDate start = CalendarDate.parseUdunits(null, "3 days since 1970-01-01 12:00");
CalendarDate end = CalendarDate.parseUdunits(null, "6 days since 1970-01-01 12:00");
int offset = cp.getOffset(start, end);
System.out.printf("offset=%d%n", offset);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy