From dfe98d469ada7122f24e5bb09d86c5d7b889d0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Gonz=C3=A1lez=20Fern=C3=A1ndez?= Date: Thu, 25 Jun 2009 12:49:08 +0200 Subject: [PATCH] ItEr14S08ModeladoTempoItEr13S09: PartialDate initial implementation complete. --- .../business/test/time/PartialDateTest.java | 182 ++++++++++++++++ .../business/time/PartialDate.java | 198 ++++++++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 navalplanner-business/src/test/java/org/navalplanner/business/test/time/PartialDateTest.java create mode 100644 navalplanner-business/src/test/java/org/navalplanner/business/time/PartialDate.java diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/time/PartialDateTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/time/PartialDateTest.java new file mode 100644 index 000000000..0cf0077dd --- /dev/null +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/time/PartialDateTest.java @@ -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))); + } + +} \ No newline at end of file diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/time/PartialDate.java b/navalplanner-business/src/test/java/org/navalplanner/business/time/PartialDate.java new file mode 100644 index 000000000..ef19196a4 --- /dev/null +++ b/navalplanner-business/src/test/java/org/navalplanner/business/time/PartialDate.java @@ -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); + } + +}