ItEr14S08ModeladoTempoItEr13S09: PartialDate initial implementation complete.
This commit is contained in:
parent
691c659f2c
commit
dfe98d469a
2 changed files with 380 additions and 0 deletions
|
|
@ -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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue