ItEr14S08ModeladoTempoItEr13S09: PartialDate initial implementation complete.

This commit is contained in:
Óscar González Fernández 2009-06-25 12:49:08 +02:00 committed by Javier Moran Rua
parent 691c659f2c
commit dfe98d469a
2 changed files with 380 additions and 0 deletions

View file

@ -0,0 +1,182 @@
package org.navalplanner.business.test.time;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.DateTimeFieldType;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.joda.time.ReadablePartial;
import org.junit.Test;
import org.navalplanner.business.time.PartialDate;
import org.navalplanner.business.time.PartialDate.Granularity;
public class PartialDateTest {
@Test
public void defaultTimeUnitIsMilliseconds() throws Exception {
Date date = new Date();
PartialDate partialDate = PartialDate.from(date);
assertThat(partialDate.getGranularity(), equalTo(Granularity.MILLISECONDS));
}
@Test
public void isAReadablePartial() {
assertTrue(PartialDate.from(new Date()) instanceof ReadablePartial);
}
@Test
public void canBeCreatedFromJavaUtilDate() {
Date now = new Date();
PartialDate partial = PartialDate.from(now).with(Granularity.DAY);
Granularity unit = partial.getGranularity();
assertThat(unit, equalTo(Granularity.DAY));
}
@Test
public void canBeCreatedFromJodaDateTime() {
LocalDate date = new LocalDate(2000, 10, 12);
DateTime dateTimeAtCurrentTime = date.toDateTimeAtCurrentTime();
PartialDate partial = PartialDate.from(dateTimeAtCurrentTime).with(
Granularity.DAY);
Granularity unit = partial.getGranularity();
assertThat(unit, equalTo(Granularity.DAY));
assertThat(partial.get(DateTimeFieldType.dayOfMonth()), equalTo(12));
}
@Test
public void canBeCreatedFromLocalDateAndPutsGranularityAsDay() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partial = PartialDate.from(date);
assertThat(partial.getGranularity(), equalTo(Granularity.DAY));
check(partial, 2000, 10, 12);
}
@Test
public void granularityOfDayAndMoreFineGrainedCanBeConvertedToLocalDate() {
Instant now = new Instant();
LocalDate today = new LocalDate();
Granularity[] supportingConversionToLocalDate = Granularity.DAY
.thisAndMoreFineGrained();
for (Granularity g : supportingConversionToLocalDate) {
PartialDate partialDate = PartialDate.from(now).with(g);
assertTrue(partialDate.canBeConvertedToLocalDate());
LocalDate converted = PartialDate
.tryToConvertToLocalDate(partialDate);
assertThat(converted, equalTo(today));
}
Granularity[] notSupportingConversionToLocalDate = Granularity.DAY
.moreCoarseGrained();
for (Granularity g : notSupportingConversionToLocalDate) {
PartialDate partialDate = PartialDate.from(now).with(g);
assertFalse(partialDate.canBeConvertedToLocalDate());
try {
LocalDate converted = PartialDate
.tryToConvertToLocalDate(partialDate);
fail("the partial date cannot be converted to a LocalDate");
} catch (IllegalArgumentException e) {
// ok
}
}
}
@Test
public void fieldsDependOnTimeUnit() throws Exception {
Date now = new Date();
for (Granularity timeUnit : Granularity.values()) {
PartialDate partial = PartialDate.from(now).with(timeUnit);
DateTimeFieldType types[] = timeUnit.getDateTimeTypes();
for (int i = 0; i < types.length; i++) {
assertThat(partial.getFieldType(i), equalTo(types[i]));
}
}
}
@Test
public void retainsValues() throws Exception {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight().toDate()).with(Granularity.DAY);
check(partialDate, 2000, 10, 12);
}
private void check(PartialDate partialDate, int year, int month, int day) {
assertThat(partialDate.get(DateTimeFieldType.year()), equalTo(year));
assertThat(partialDate.get(DateTimeFieldType.monthOfYear()),
equalTo(month));
assertThat(partialDate.get(DateTimeFieldType.dayOfMonth()),
equalTo(day));
}
@Test(expected = IllegalArgumentException.class)
public void dontSupportAllTypes() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight().toDate()).with(Granularity.DAY);
partialDate.get(DateTimeFieldType.minuteOfHour());
}
@Test
public void canBeConvertedToMoreCoarseGrained() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight().toDate()).with(Granularity.DAY);
PartialDate onlyUntilMonthSpecified = partialDate.with(Granularity.MONTH);
assertThat(
onlyUntilMonthSpecified.get(DateTimeFieldType.monthOfYear()),
equalTo(10));
try {
onlyUntilMonthSpecified.get(DateTimeFieldType.dayOfMonth());
fail("must send exception since the day is lost in the conversion");
} catch (IllegalArgumentException e) {
// ok
}
}
@Test
public void thereIsQueryMethodToKnowIfItCanBeConverted() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight().toDate()).with(Granularity.DAY);
Granularity[] moreCoarseGrained = { Granularity.YEAR, Granularity.MONTH,
Granularity.DAY };
for (Granularity t : moreCoarseGrained) {
assertTrue(partialDate.canBeConvertedTo(t));
}
Granularity[] moreFineGrained = { Granularity.HOUR, Granularity.MINUTE,
Granularity.SECOND, Granularity.MILLISECONDS };
for (Granularity t : moreFineGrained) {
assertFalse(partialDate.canBeConvertedTo(t));
}
}
@Test(expected = IllegalArgumentException.class)
public void cannotBeConvertedToMoreFineGrained() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight().toDate()).with(Granularity.DAY);
partialDate.with(Granularity.HOUR);
}
@Test
public void onlyPartialDatesOfTheSameGranuralityCanBeEqual() {
LocalDate date = new LocalDate(2000, 10, 12);
PartialDate partialDate = PartialDate.from(
date.toDateMidnight()).with(
Granularity.DAY);
PartialDate otherOnSameInstantWithDifferentGranularity = PartialDate
.from(date.toDateMidnight()).with(
Granularity.MILLISECONDS);
assertThat(partialDate,
not(equalTo(otherOnSameInstantWithDifferentGranularity)));
}
}

View file

@ -0,0 +1,198 @@
package org.navalplanner.business.time;
import java.util.Date;
import org.joda.time.Chronology;
import org.joda.time.DateTime;
import org.joda.time.DateTimeField;
import org.joda.time.DateTimeFieldType;
import org.joda.time.DateTimeZone;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.joda.time.Partial;
import org.joda.time.ReadableInstant;
import org.joda.time.ReadablePartial;
public class PartialDate implements ReadablePartial {
private static final DateTimeFieldType year = DateTimeFieldType.year();
private static final DateTimeFieldType monthOfYear = DateTimeFieldType
.monthOfYear();
private static final DateTimeFieldType weekOfYear = DateTimeFieldType
.weekOfWeekyear();
private static final DateTimeFieldType dayOfMonth = DateTimeFieldType
.dayOfMonth();
private static final DateTimeFieldType hourOfDay = DateTimeFieldType
.hourOfDay();
private static final DateTimeFieldType minuteOfHour = DateTimeFieldType
.minuteOfHour();
private static final DateTimeFieldType secondOfMinute = DateTimeFieldType
.secondOfMinute();
private static final DateTimeFieldType millisOfSecond = DateTimeFieldType
.millisOfSecond();
public enum Granularity {
YEAR(year), MONTH(year, monthOfYear), WEEK(year, weekOfYear), DAY(year,
monthOfYear, dayOfMonth), HOUR(year, monthOfYear, dayOfMonth,
hourOfDay), MINUTE(year, monthOfYear, dayOfMonth, hourOfDay,
minuteOfHour), SECOND(year, monthOfYear, dayOfMonth, hourOfDay,
minuteOfHour, secondOfMinute), MILLISECONDS(year, monthOfYear,
dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
millisOfSecond);
private DateTimeFieldType[] types;
private Granularity(DateTimeFieldType... types) {
this.types = types;
}
public DateTimeFieldType[] getDateTimeTypes() {
return types.clone();
}
boolean isMoreCoarseGrainedThan(Granularity other) {
return this.ordinal() < other.ordinal();
}
public Granularity[] thisAndMoreFineGrained() {
Granularity[] result = new Granularity[values().length
- this.ordinal()];
for (int i = 0; i < result.length; i++) {
result[i] = values()[i + this.ordinal()];
}
return result;
}
public Granularity[] moreCoarseGrained() {
Granularity[] result = new Granularity[this.ordinal() - 1];
for (int i = 0; i < result.length; i++) {
result[i] = values()[i];
}
return result;
}
}
public static LocalDate tryToConvertToLocalDate(PartialDate partialDate) {
if (!partialDate.canBeConvertedToLocalDate())
throw new IllegalArgumentException("the partialDate " + partialDate
+ " doesn't support be converted to local date");
return new LocalDate(partialDate.instant);
}
public static PartialDate from(LocalDate date) {
long millis = date.toDateMidnight().getMillis();
return from(millis).with(Granularity.DAY);
}
public static PartialDate from(DateTime dateTime) {
return from(dateTime.getMillis());
}
public static PartialDate from(Date date) {
return from(date.getTime());
}
public static PartialDate from(ReadableInstant instant) {
return from(instant.getMillis());
}
public static PartialDate from(long timeMilliseconds) {
return new PartialDate(new Instant(timeMilliseconds),
Granularity.MILLISECONDS);
}
private final Granularity granularity;
private final Partial partial;
private final Instant instant;
private PartialDate(Instant instant, Granularity unit) {
this.partial = asPartial(instant, unit);
this.granularity = unit;
this.instant = instant;
}
private static Partial asPartial(ReadableInstant instant, Granularity unit) {
DateTime dateTime = interpretInDefaultTimeZone(instant);
DateTimeFieldType[] dateTimeTypes = unit.getDateTimeTypes();
int[] values = new int[dateTimeTypes.length];
for (int i = 0; i < values.length; i++) {
values[i] = dateTime.get(dateTimeTypes[i]);
}
return new Partial(dateTimeTypes, values);
}
private static DateTime interpretInDefaultTimeZone(ReadableInstant instant) {
return new DateTime(instant.getMillis(), DateTimeZone.getDefault());
}
public PartialDate with(Granularity granularity) {
if (!canBeConvertedTo(granularity)) {
throw new IllegalArgumentException("the granularity " + granularity
+ " is more fine-grained than the current one("
+ this.granularity + "). Conversion is impossible");
}
return new PartialDate(instant, granularity);
}
public Granularity getGranularity() {
return this.granularity;
}
public boolean canBeConvertedToLocalDate() {
return !this.granularity.isMoreCoarseGrainedThan(Granularity.DAY);
}
public boolean canBeConvertedTo(Granularity unit) {
return !this.granularity.isMoreCoarseGrainedThan(unit);
}
@Override
public int get(DateTimeFieldType field) {
return partial.get(field);
}
@Override
public Chronology getChronology() {
return partial.getChronology();
}
@Override
public DateTimeField getField(int index) {
return partial.getField(index);
}
@Override
public DateTimeFieldType getFieldType(int index) {
return granularity.types[index];
}
@Override
public int getValue(int index) {
return partial.getValue(index);
}
@Override
public boolean isSupported(DateTimeFieldType field) {
return partial.isSupported(field);
}
@Override
public int size() {
return partial.size();
}
@Override
public DateTime toDateTime(ReadableInstant baseInstant) {
return partial.toDateTime(baseInstant);
}
}