/** * A Chronology in which each year has exactly 360 days of 12 equal months ({@literal i.e.} each * month has exactly 30 days). This calendar system is used in many climate simulations. There are * no leap years. * * <p>In this Chronology, a millisecond instant of zero corresponds with 1970-01-01T00:00:00.000Z * and a year has a fixed number of milliseconds (1000*60*60*24*360). * * <p>There is no concept of an era in this calendar, so all durations and fields relating to this * concept are not supported. Additionally, the concept of a "weekyear" (the year that "owns" a * given week) is not implemented. * * <p>Instances of this class can only be created in {@link DateTimeZone#UTC}. (Support for time * zones makes little sense in this chronology). * * <p>Instances of this class are immutable. * * @author Jon Blower * @see http://cf-pcmdi.llnl.gov/documents/cf-conventions/1.4/cf-conventions.html#calendar */ public final class ThreeSixtyDayChronology extends FixedYearLengthChronology { ///// DURATIONS ///// /** 30 days in every month */ private final DurationField monthDuration = new PreciseDurationField(DurationFieldType.months(), 30 * this.days().getUnitMillis()); private final DateTimeField dayOfMonth = new OneBasedPreciseDateTimeField( DateTimeFieldType.dayOfMonth(), this.days(), this.monthDuration); private final DateTimeField monthOfYear = new OneBasedPreciseDateTimeField( DateTimeFieldType.monthOfYear(), this.monthDuration, this.years()); ///// CONSTRUCTORS AND FACTORIES ///// private static final ThreeSixtyDayChronology INSTANCE_UTC = new ThreeSixtyDayChronology(); /** Private constructor to prevent direct instantiation */ private ThreeSixtyDayChronology() { super(360); } /** Gets an instance of this Chronology in the UTC time zone */ public static ThreeSixtyDayChronology getInstanceUTC() { return INSTANCE_UTC; } ///// DURATION ACCESSORS ///// /** Each month has exactly 30 days */ @Override public DurationField months() { return this.monthDuration; } ///// DATE-TIME FIELD ACCESSORS ///// @Override public DateTimeField dayOfMonth() { return this.dayOfMonth; } @Override public DateTimeField monthOfYear() { return this.monthOfYear; } @Override public String toString() { return "360-day Chronology in UTC"; } }
/** Private method called from constructor. */ private void setPeriodInternal( int years, int months, int weeks, int days, int hours, int minutes, int seconds, int millis) { int[] newValues = new int[size()]; checkAndUpdate(DurationFieldType.years(), newValues, years); checkAndUpdate(DurationFieldType.months(), newValues, months); checkAndUpdate(DurationFieldType.weeks(), newValues, weeks); checkAndUpdate(DurationFieldType.days(), newValues, days); checkAndUpdate(DurationFieldType.hours(), newValues, hours); checkAndUpdate(DurationFieldType.minutes(), newValues, minutes); checkAndUpdate(DurationFieldType.seconds(), newValues, seconds); checkAndUpdate(DurationFieldType.millis(), newValues, millis); iValues = newValues; }
private void testAdd(Date start, DurationFieldType type, int amt, Date end) { DateTime dtStart = new DateTime(start, ISOChronology.getInstanceUTC()); DateTime dtEnd = new DateTime(end, ISOChronology.getInstanceUTC()); assertEquals(dtEnd, dtStart.withFieldAdded(type, amt)); assertEquals(dtStart, dtEnd.withFieldAdded(type, -amt)); DurationField field = type.getField(ISOChronology.getInstanceUTC()); int diff = field.getDifference(dtEnd.getMillis(), dtStart.getMillis()); assertEquals(amt, diff); if (type == DurationFieldType.years() || type == DurationFieldType.months() || type == DurationFieldType.days()) { LocalDate ymdStart = new LocalDate(start, ISOChronology.getInstanceUTC()); LocalDate ymdEnd = new LocalDate(end, ISOChronology.getInstanceUTC()); assertEquals(ymdEnd, ymdStart.withFieldAdded(type, amt)); assertEquals(ymdStart, ymdEnd.withFieldAdded(type, -amt)); } }
public void testAddMonths() { DateTimeFormat format = DateTimeFormat.getFormat("YYYY-MM-DD"); Date startDate = format.parse("1582-01-01"); Date endDate = format.parse("1582-02-01"); testAdd(startDate, DurationFieldType.months(), 1, endDate); startDate = format.parse("1582-01-01"); endDate = format.parse("1582-07-01"); testAdd(startDate, DurationFieldType.months(), 6, endDate); startDate = format.parse("1582-01-01"); endDate = format.parse("1583-01-01"); testAdd(startDate, DurationFieldType.months(), 12, endDate); startDate = format.parse("1582-11-15"); endDate = format.parse("1582-12-15"); testAdd(startDate, DurationFieldType.months(), 1, endDate); startDate = format.parse("1582-09-04"); endDate = format.parse("1582-11-04"); testAdd(startDate, DurationFieldType.months(), 2, endDate); startDate = format.parse("1582-09-05"); endDate = format.parse("1582-11-05"); testAdd(startDate, DurationFieldType.months(), 2, endDate); startDate = format.parse("1582-09-10"); endDate = format.parse("1582-11-10"); testAdd(startDate, DurationFieldType.months(), 2, endDate); startDate = format.parse("1582-09-15"); endDate = format.parse("1582-11-15"); testAdd(startDate, DurationFieldType.months(), 2, endDate); startDate = format.parse("1580-01-01"); endDate = format.parse("1584-01-01"); testAdd(startDate, DurationFieldType.months(), 48, endDate); startDate = format.parse("1580-02-29"); endDate = format.parse("1584-02-29"); testAdd(startDate, DurationFieldType.months(), 48, endDate); startDate = format.parse("1580-10-01"); endDate = format.parse("1584-10-01"); testAdd(startDate, DurationFieldType.months(), 48, endDate); startDate = format.parse("1580-10-10"); endDate = format.parse("1584-10-10"); testAdd(startDate, DurationFieldType.months(), 48, endDate); startDate = format.parse("1580-10-15"); endDate = format.parse("1584-10-15"); testAdd(startDate, DurationFieldType.months(), 48, endDate); startDate = format.parse("1580-12-31"); endDate = format.parse("1584-12-31"); testAdd(startDate, DurationFieldType.months(), 48, endDate); }