ItEr14S08ModeladoTempoItEr13S09: PartialDate, IntervalsOfPartialDates and TimeQuantities.
This commit is contained in:
parent
dfe98d469a
commit
56925dd424
8 changed files with 1060 additions and 380 deletions
|
|
@ -0,0 +1,52 @@
|
|||
package org.navalplanner.business.partialtime;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
public class IntervalOfPartialDates {
|
||||
|
||||
private final PartialDate start;
|
||||
|
||||
private final PartialDate end;
|
||||
|
||||
public IntervalOfPartialDates(PartialDate start, PartialDate end) {
|
||||
if (!start.getGranularity().equals(end.getGranularity()))
|
||||
throw new IllegalArgumentException(
|
||||
"the from and the to must have the same granularity");
|
||||
if (!start.before(end)) {
|
||||
throw new IllegalArgumentException(
|
||||
"the start must be before the end");
|
||||
}
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public PartialDate getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public PartialDate getEnd() {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
public TimeQuantity getDuration() {
|
||||
return end.quantityFrom(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj instanceof IntervalOfPartialDates) {
|
||||
IntervalOfPartialDates other = (IntervalOfPartialDates) obj;
|
||||
return new EqualsBuilder().append(this.start, other.start).append(
|
||||
this.end, other.end).isEquals();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(start).append(end).toHashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
package org.navalplanner.business.partialtime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
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;
|
||||
import org.joda.time.chrono.ISOChronology;
|
||||
|
||||
/**
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
*/
|
||||
public class PartialDate implements ReadablePartial {
|
||||
private static final DateTimeFieldType year = DateTimeFieldType.year();
|
||||
|
||||
private static final DateTimeFieldType monthOfYear = DateTimeFieldType
|
||||
.monthOfYear();
|
||||
|
||||
private static final DateTimeFieldType weekyear = DateTimeFieldType
|
||||
.weekyear();
|
||||
|
||||
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(weekyear, weekOfYear) {
|
||||
TimeQuantity asQuantity(TimeQuantity acc, List<Integer> values) {
|
||||
return acc.plus(values.get(0), Granularity.YEAR).plus(
|
||||
values.get(1), Granularity.WEEK);
|
||||
}
|
||||
},
|
||||
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();
|
||||
}
|
||||
|
||||
public TimeQuantity asQuantity(int[] values) {
|
||||
return asQuantity(TimeQuantity.empty(), asIntegersList(values));
|
||||
}
|
||||
|
||||
TimeQuantity asQuantity(TimeQuantity acc, List<Integer> values) {
|
||||
Integer current = values.remove(values.size() - 1);
|
||||
acc = acc.plus(current, this);
|
||||
if (hasPrevious()) {
|
||||
acc = getPrevious().asQuantity(acc, values);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
private boolean hasPrevious() {
|
||||
return ordinal() > 0;
|
||||
}
|
||||
|
||||
private Granularity getPrevious() {
|
||||
Granularity granularity = Granularity.values()[ordinal() - 1];
|
||||
// we bypass week, as it isn't part of the rest of hierarchy
|
||||
if (granularity == WEEK) {
|
||||
return WEEK.getPrevious();
|
||||
}
|
||||
return granularity;
|
||||
}
|
||||
|
||||
private List<Integer> asIntegersList(int[] values) {
|
||||
List<Integer> result = new ArrayList<Integer>();
|
||||
for (int value : values) {
|
||||
result.add(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = values()[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Granularity forType(DateTimeFieldType fieldType) {
|
||||
for (Granularity granularity : Granularity.values()) {
|
||||
if (granularity.specifies(fieldType)) {
|
||||
return granularity;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("not found granularity for " + fieldType);
|
||||
}
|
||||
|
||||
private boolean specifies(DateTimeFieldType fieldType) {
|
||||
return getMostSpecific().equals(fieldType);
|
||||
}
|
||||
|
||||
private DateTimeFieldType getMostSpecific() {
|
||||
return getDateTimeTypes()[getDateTimeTypes().length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public static PartialDate createFrom(LocalDate date) {
|
||||
long millis = date.toDateTimeAtStartOfDay().getMillis();
|
||||
return createFrom(millis).with(Granularity.DAY);
|
||||
}
|
||||
|
||||
public static PartialDate createFrom(DateTime dateTime) {
|
||||
return createFrom(dateTime.getMillis());
|
||||
}
|
||||
|
||||
public static PartialDate createFrom(Date date) {
|
||||
return createFrom(date.getTime());
|
||||
}
|
||||
|
||||
public static PartialDate createFrom(ReadableInstant instant) {
|
||||
return createFrom(instant.getMillis());
|
||||
}
|
||||
|
||||
public static PartialDate createFrom(long timeMilliseconds) {
|
||||
return new PartialDate(new Instant(timeMilliseconds),
|
||||
Granularity.MILLISECONDS);
|
||||
}
|
||||
|
||||
private static List<Integer> getValues(Partial partial,
|
||||
Granularity granularity) {
|
||||
List<Integer> values = new ArrayList<Integer>();
|
||||
for (DateTimeFieldType fieldType : granularity.getDateTimeTypes()) {
|
||||
values.add(partial.get(fieldType));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private static Instant toNormalizedInstant(Granularity granularity,
|
||||
List<Integer> values) {
|
||||
return new Partial(granularity.getDateTimeTypes(), asIntArray(values),
|
||||
ISOChronology.getInstance(DateTimeZone.getDefault()))
|
||||
.toDateTime(new DateTime(0, DateTimeZone.getDefault()))
|
||||
.toInstant();
|
||||
}
|
||||
|
||||
private static int[] asIntArray(List<Integer> values) {
|
||||
int[] result = new int[values.size()];
|
||||
int i = 0;
|
||||
for (Integer integer : values) {
|
||||
result[i++] = integer;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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 final Granularity granularity;
|
||||
|
||||
private final Partial partial;
|
||||
|
||||
private final Instant normalizedInstant;
|
||||
|
||||
private List<Integer> values;
|
||||
|
||||
private PartialDate(Instant instant, Granularity granularityUnit) {
|
||||
this.partial = asPartial(instant, granularityUnit);
|
||||
this.granularity = granularityUnit;
|
||||
this.values = Collections.unmodifiableList(getValues(partial,
|
||||
granularityUnit));
|
||||
this.normalizedInstant = toNormalizedInstant(granularityUnit, values);
|
||||
assert this.partial.equals(asPartial(this.normalizedInstant,
|
||||
granularityUnit));
|
||||
}
|
||||
|
||||
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(normalizedInstant, granularity);
|
||||
}
|
||||
|
||||
public Granularity getGranularity() {
|
||||
return this.granularity;
|
||||
}
|
||||
|
||||
public boolean canBeConvertedToLocalDate() {
|
||||
return !this.granularity.isMoreCoarseGrainedThan(Granularity.DAY);
|
||||
}
|
||||
|
||||
public boolean canBeConvertedTo(Granularity unit) {
|
||||
Validate.notNull(unit);
|
||||
return !this.granularity.isMoreCoarseGrainedThan(unit);
|
||||
}
|
||||
|
||||
public boolean before(PartialDate other) throws IllegalArgumentException {
|
||||
if (!getGranularity().equals(other.getGranularity())) {
|
||||
throw new IllegalArgumentException(
|
||||
"It's required that the two PartialDates have the same granularity");
|
||||
}
|
||||
assert this.values.size() == other.values.size();
|
||||
Iterator<Integer> iterator = this.values.iterator();
|
||||
Iterator<Integer> otherIterator = other.values.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
int diff = iterator.next() - otherIterator.next();
|
||||
if (diff > 0)
|
||||
return false;
|
||||
if (diff < 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean after(PartialDate other) throws IllegalArgumentException {
|
||||
return !before(other) && !equals(other);
|
||||
}
|
||||
|
||||
public LocalDate tryToConvertToLocalDate() throws IllegalArgumentException {
|
||||
if (!this.canBeConvertedToLocalDate())
|
||||
throw new IllegalArgumentException("the partialDate " + this
|
||||
+ " can't support be converted to local date");
|
||||
return new LocalDate(this.normalizedInstant, ISOChronology
|
||||
.getInstance(DateTimeZone.getDefault()));
|
||||
}
|
||||
|
||||
public IntervalOfPartialDates to(PartialDate to) {
|
||||
return new IntervalOfPartialDates(this, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder().append(getGranularity()).append(values)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof PartialDate) {
|
||||
PartialDate other = (PartialDate) obj;
|
||||
if (!getGranularity().equals(other.getGranularity())) {
|
||||
return false;
|
||||
}
|
||||
return this.values.equals(other.values);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
public IntervalOfPartialDates to(TimeQuantity timeQuantity) {
|
||||
return to(this.plus(timeQuantity));
|
||||
}
|
||||
|
||||
public PartialDate plus(TimeQuantity timeQuantity) {
|
||||
if (granularity.isMoreCoarseGrainedThan(timeQuantity
|
||||
.getGreatestGranularitySpecified())) {
|
||||
throw new IllegalArgumentException("");
|
||||
}
|
||||
DateTimeFieldType[] dateTimeTypes = granularity.getDateTimeTypes();
|
||||
long result = normalizedInstant.getMillis();
|
||||
for (int i = 0; i < dateTimeTypes.length; i++) {
|
||||
DateTimeField field = dateTimeTypes[i].getField(getChronology());
|
||||
result = field.add(result, timeQuantity.valueFor(Granularity
|
||||
.forType(dateTimeTypes[i])));
|
||||
}
|
||||
return new PartialDate(new Instant(result), granularity);
|
||||
}
|
||||
|
||||
public TimeQuantity quantityFrom(PartialDate start) {
|
||||
Validate.isTrue(this.granularity.equals(start.getGranularity()),
|
||||
"must have the same granularity");
|
||||
Validate.isTrue(this.after(start));
|
||||
int[] values = substract(this.values, start.values);
|
||||
return this.granularity.asQuantity(values);
|
||||
}
|
||||
|
||||
private static int[] substract(List<Integer> bigger, List<Integer> other) {
|
||||
assert bigger.size() == other.size();
|
||||
int[] result = new int[bigger.size()];
|
||||
Iterator<Integer> iterator = bigger.iterator();
|
||||
Iterator<Integer> otherIterator = other.iterator();
|
||||
int i = 0;
|
||||
while (iterator.hasNext()) {
|
||||
result[i] = iterator.next() - otherIterator.next();
|
||||
i++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Integer valueFor(Granularity granularity) {
|
||||
if (this.granularity.isMoreCoarseGrainedThan(granularity))
|
||||
throw new IllegalArgumentException(granularity
|
||||
+ " is more specific than this instance granularity: "
|
||||
+ this.granularity);
|
||||
return get(granularity.getMostSpecific());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package org.navalplanner.business.partialtime;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.navalplanner.business.partialtime.PartialDate.Granularity;
|
||||
|
||||
/**
|
||||
* Represents a quantity of time. It's composed from granularities and integers <br />
|
||||
* @author Óscar González Fernández <ogonzalez@igalia.com>
|
||||
*/
|
||||
public class TimeQuantity {
|
||||
|
||||
private static EnumMap<Granularity, Integer> createSumOf(
|
||||
EnumMap<Granularity, Integer>... values) {
|
||||
EnumMap<Granularity, Integer> result = new EnumMap<Granularity, Integer>(
|
||||
Granularity.class);
|
||||
for (Granularity granularity : Granularity.values()) {
|
||||
Integer acc = sumAll(granularity, values);
|
||||
if (acc != null) {
|
||||
result.put(granularity, acc);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Integer sumAll(Granularity granularity,
|
||||
EnumMap<Granularity, Integer>... maps) {
|
||||
Integer result = null;
|
||||
for (EnumMap<Granularity, Integer> enumMap : maps) {
|
||||
if (enumMap.containsKey(granularity)) {
|
||||
Integer valueToAdd = enumMap.get(granularity);
|
||||
result = result == null ? enumMap.get(granularity) : result
|
||||
+ valueToAdd;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EnumMap<Granularity, Integer> copyAndAdd(
|
||||
EnumMap<Granularity, Integer> existent, int quantity,
|
||||
Granularity granularity) {
|
||||
EnumMap<Granularity, Integer> result = new EnumMap<Granularity, Integer>(
|
||||
existent);
|
||||
int newQuantity = quantity;
|
||||
if (result.containsKey(granularity)) {
|
||||
newQuantity += result.get(granularity);
|
||||
}
|
||||
result.put(granularity, newQuantity);
|
||||
return result;
|
||||
}
|
||||
|
||||
private final EnumMap<Granularity, Integer> values;
|
||||
|
||||
public static TimeQuantity empty() {
|
||||
return new TimeQuantity();
|
||||
}
|
||||
|
||||
public TimeQuantity() {
|
||||
this(new EnumMap<Granularity, Integer>(Granularity.class));
|
||||
}
|
||||
|
||||
private TimeQuantity(EnumMap<Granularity, Integer> enumMap) {
|
||||
Validate.notNull(enumMap);
|
||||
this.values = enumMap;
|
||||
}
|
||||
|
||||
public Integer valueFor(Granularity granularity) {
|
||||
return values.containsKey(granularity) ? values.get(granularity) : 0;
|
||||
}
|
||||
|
||||
public TimeQuantity plus(int quantity, Granularity granularity) {
|
||||
Validate.notNull(granularity, "granularity must be not null");
|
||||
return new TimeQuantity(copyAndAdd(values, quantity, granularity));
|
||||
}
|
||||
|
||||
public TimeQuantity plus(TimeQuantity other) {
|
||||
return new TimeQuantity(createSumOf(values, other.values));
|
||||
}
|
||||
|
||||
public Granularity getGreatestGranularitySpecified() {
|
||||
Granularity result = Granularity.YEAR;
|
||||
for (Granularity granularity : values.keySet()) {
|
||||
if (result == null || result.isMoreCoarseGrainedThan(granularity)) {
|
||||
result = granularity;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package org.navalplanner.business.test.partialtime;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.junit.Test;
|
||||
import org.navalplanner.business.partialtime.IntervalOfPartialDates;
|
||||
import org.navalplanner.business.partialtime.PartialDate;
|
||||
import org.navalplanner.business.partialtime.TimeQuantity;
|
||||
import org.navalplanner.business.partialtime.PartialDate.Granularity;
|
||||
|
||||
public class IntervalOfPartialDatesTest {
|
||||
|
||||
private PartialDate start = PartialDate.createFrom(new LocalDate(2006, 10, 2));
|
||||
private PartialDate end = PartialDate.createFrom(new LocalDate(2006, 11, 5));
|
||||
private IntervalOfPartialDates interval = new IntervalOfPartialDates(start,
|
||||
end);
|
||||
|
||||
@Test
|
||||
public void isComposedFromTwoPartialDates() {
|
||||
assertThat(interval.getStart(), equalTo(start));
|
||||
assertThat(interval.getEnd(), equalTo(end));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void thePartialDatesMustBeOfTheSameGranularity() {
|
||||
new IntervalOfPartialDates(start, end.with(Granularity.MONTH));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void theFromMustBeBeforeTo() {
|
||||
new IntervalOfPartialDates(end, start);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void cannotCreateEmptyInterval() {
|
||||
PartialDate.createFrom(new LocalDate(2006, 11, 2)).to(
|
||||
PartialDate.createFrom(new LocalDate(2006, 11, 2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBeCreatedFromPartialDate() {
|
||||
PartialDate.createFrom(new LocalDate(2006, 10, 2)).to(
|
||||
PartialDate.createFrom(new LocalDate(2006, 11, 2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetTheDurationOfTheInterval() {
|
||||
TimeQuantity duration = interval.getDuration();
|
||||
assertThat(duration.valueFor(Granularity.MONTH), equalTo(1));
|
||||
assertThat(duration.valueFor(Granularity.DAY), equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void twoIntervalsAreEqualsIfTheirPartialDatesAreEquals() {
|
||||
PartialDate from = PartialDate.createFrom(new LocalDate(2006, 10, 2)
|
||||
.toDateTimeAtStartOfDay());
|
||||
IntervalOfPartialDates oneInterval = from.to(PartialDate
|
||||
.createFrom(new LocalDate(2006, 10, 3).toDateTimeAtStartOfDay()));
|
||||
IntervalOfPartialDates otherInterval = PartialDate.createFrom(
|
||||
new LocalDate(2006, 10, 2).toDateTimeAtStartOfDay()).to(
|
||||
PartialDate.createFrom(new LocalDate(2006, 10, 3)
|
||||
.toDateTimeAtStartOfDay()));
|
||||
IntervalOfPartialDates differentInterval = from.to(PartialDate
|
||||
.createFrom(new LocalDate(2006, 10, 4).toDateTimeAtStartOfDay()));
|
||||
assertEquals(oneInterval, oneInterval);
|
||||
|
||||
assertEquals(oneInterval, otherInterval);
|
||||
assertEquals(otherInterval, oneInterval);
|
||||
assertEquals(oneInterval.hashCode(), otherInterval.hashCode());
|
||||
|
||||
assertFalse(oneInterval.equals(differentInterval));
|
||||
assertFalse(differentInterval.equals(oneInterval));
|
||||
assertFalse(oneInterval.hashCode() == differentInterval.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetTheDurationInMilliseconds() {
|
||||
DateTime startOfDay = new LocalDate(2009, 3, 8)
|
||||
.toDateTimeAtStartOfDay();
|
||||
PartialDate startOfDayPartial = PartialDate.createFrom(startOfDay);
|
||||
long millis = startOfDay.getMillis();
|
||||
PartialDate after = PartialDate.createFrom(new DateTime(millis + 3));
|
||||
PartialDate before = PartialDate.createFrom(new DateTime(millis - 3));
|
||||
IntervalOfPartialDates[] intervalsWithTheSameDuration = {
|
||||
before.to(startOfDayPartial), startOfDayPartial.to(after) };
|
||||
for (IntervalOfPartialDates interval : intervalsWithTheSameDuration) {
|
||||
TimeQuantity duration = interval.getDuration();
|
||||
PartialDate start2 = interval.getStart();
|
||||
PartialDate endCalculated = start2.plus(duration);
|
||||
PartialDate originalEnd = interval.getEnd();
|
||||
assertThat(endCalculated, equalTo(originalEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
package org.navalplanner.business.test.partialtime;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
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.partialtime.IntervalOfPartialDates;
|
||||
import org.navalplanner.business.partialtime.PartialDate;
|
||||
import org.navalplanner.business.partialtime.TimeQuantity;
|
||||
import org.navalplanner.business.partialtime.PartialDate.Granularity;
|
||||
|
||||
public class PartialDateTest {
|
||||
|
||||
@Test
|
||||
public void defaultTimeUnitIsMilliseconds() throws Exception {
|
||||
Date date = new Date();
|
||||
PartialDate partialDate = PartialDate.createFrom(date);
|
||||
assertThat(partialDate.getGranularity(),
|
||||
equalTo(Granularity.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAReadablePartial() {
|
||||
assertTrue(PartialDate.createFrom(new Date()) instanceof ReadablePartial);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBeCreatedFromJavaUtilDate() {
|
||||
Date now = new Date();
|
||||
PartialDate partial = PartialDate.createFrom(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.createFrom(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.createFrom(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.createFrom(now).with(g);
|
||||
assertTrue(partialDate.canBeConvertedToLocalDate());
|
||||
LocalDate converted = partialDate.tryToConvertToLocalDate();
|
||||
assertThat(converted, equalTo(today));
|
||||
}
|
||||
Granularity[] notSupportingConversionToLocalDate = Granularity.DAY
|
||||
.moreCoarseGrained();
|
||||
for (Granularity g : notSupportingConversionToLocalDate) {
|
||||
PartialDate partialDate = PartialDate.createFrom(now).with(g);
|
||||
assertFalse(partialDate.canBeConvertedToLocalDate());
|
||||
try {
|
||||
LocalDate converted = partialDate.tryToConvertToLocalDate();
|
||||
fail("the partial date cannot be converted to a LocalDate");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void availableFieldsDependOnTimeUnit() throws Exception {
|
||||
Date now = new Date();
|
||||
for (Granularity timeUnit : Granularity.values()) {
|
||||
PartialDate partial = PartialDate.createFrom(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 canAccessFieldsUsingGranularity() {
|
||||
LocalDate date = new LocalDate(2000, 10, 12);
|
||||
PartialDate partialDate = PartialDate.createFrom(date.toDateMidnight()
|
||||
.toDate());
|
||||
assertThat(partialDate.valueFor(Granularity.MINUTE), equalTo(0));
|
||||
assertThat(partialDate.valueFor(Granularity.YEAR), equalTo(2000));
|
||||
assertThat(partialDate.valueFor(Granularity.DAY), equalTo(12));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotAccessFieldsOfMoreSpecificGranularity() {
|
||||
PartialDate partialDate = PartialDate.createFrom(
|
||||
new LocalDate(2000, 10, 12)).with(Granularity.MONTH);
|
||||
Granularity[] moreSpecific = Granularity.MONTH.thisAndMoreFineGrained();
|
||||
for (int i = 1; i < moreSpecific.length; i++) {
|
||||
try {
|
||||
partialDate.valueFor(moreSpecific[i]);
|
||||
fail("must send IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retainsValues() throws Exception {
|
||||
LocalDate date = new LocalDate(2000, 10, 12);
|
||||
PartialDate partialDate = PartialDate.createFrom(
|
||||
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.createFrom(
|
||||
date.toDateMidnight().toDate()).with(Granularity.DAY);
|
||||
partialDate.get(DateTimeFieldType.minuteOfHour());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBeConvertedToMoreCoarseGrained() {
|
||||
LocalDate date = new LocalDate(2000, 10, 12);
|
||||
PartialDate partialDate = PartialDate.createFrom(
|
||||
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.createFrom(
|
||||
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.createFrom(
|
||||
date.toDateMidnight().toDate()).with(Granularity.DAY);
|
||||
partialDate.with(Granularity.HOUR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onlyPartialDatesOfTheSameGranuralityCanBeEqual() {
|
||||
LocalDate date = new LocalDate(2000, 10, 12);
|
||||
PartialDate partialDate = PartialDate.createFrom(
|
||||
date.toDateTimeAtStartOfDay()).with(Granularity.DAY);
|
||||
PartialDate otherOnSameInstantWithDifferentGranularity = PartialDate
|
||||
.createFrom(date.toDateTimeAtStartOfDay()).with(
|
||||
Granularity.MILLISECONDS);
|
||||
assertThat(partialDate,
|
||||
not(equalTo(otherOnSameInstantWithDifferentGranularity)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsAndHashCodeBasedOnTheValuesForCurrentGranularity() {
|
||||
LocalDate localDate = new LocalDate(2000, 10, 12);
|
||||
DateTime dateTime = localDate.toDateTimeAtStartOfDay();
|
||||
PartialDate partial = PartialDate.createFrom(localDate).with(
|
||||
Granularity.DAY);
|
||||
PartialDate other = PartialDate.createFrom(dateTime).with(
|
||||
Granularity.DAY);
|
||||
int partialHashCode = partial.hashCode();
|
||||
int otherHashCode = other.hashCode();
|
||||
assertThat(partialHashCode, equalTo(otherHashCode));
|
||||
assertThat(partial, equalTo(other));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forTwoEqualsPartialsChangingGranularityTheSameWayKeepsEquality() {
|
||||
DateTime dateTime = new LocalDate(2000, 10, 12)
|
||||
.toDateTimeAtStartOfDay();
|
||||
PartialDate partial1 = PartialDate.createFrom(dateTime).with(
|
||||
Granularity.MILLISECONDS);
|
||||
PartialDate partial2 = PartialDate.createFrom(dateTime).with(
|
||||
Granularity.MILLISECONDS);
|
||||
assertEquals(partial1, partial2);
|
||||
Granularity[] granularities = Granularity.values();
|
||||
for (int i = granularities.length - 1; i >= 0; i--) {
|
||||
partial1 = partial1.with(granularities[i]);
|
||||
partial2 = partial2.with(granularities[i]);
|
||||
assertEquals(partial1, partial2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasBeforeAndAfterMethod() {
|
||||
PartialDate beforePartialDate = PartialDate.createFrom(new LocalDate(
|
||||
2000, 9, 12));
|
||||
PartialDate posteriorPartialDate = PartialDate
|
||||
.createFrom(new LocalDate(2000, 10, 1));
|
||||
assertTrue(beforePartialDate.before(posteriorPartialDate));
|
||||
assertFalse(posteriorPartialDate.before(beforePartialDate));
|
||||
assertFalse(posteriorPartialDate.before(posteriorPartialDate));
|
||||
assertFalse(beforePartialDate.before(beforePartialDate));
|
||||
assertTrue(posteriorPartialDate.after(beforePartialDate));
|
||||
assertFalse(beforePartialDate.after(posteriorPartialDate));
|
||||
assertFalse(posteriorPartialDate.after(posteriorPartialDate));
|
||||
assertFalse(beforePartialDate.after(beforePartialDate));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void cantUseBeforeWithPartialsOfDifferentGranularity() {
|
||||
PartialDate p = PartialDate.createFrom(new LocalDate(2000, 9, 12));
|
||||
PartialDate withDifferentGranularity = p.with(Granularity.MONTH);
|
||||
p.before(withDifferentGranularity);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void cantUseAfterWithPartialsOfDifferentGranularity() {
|
||||
PartialDate p = PartialDate.createFrom(new LocalDate(2000, 9, 12));
|
||||
PartialDate withDifferentGranularity = p.with(Granularity.MONTH);
|
||||
p.after(withDifferentGranularity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canAddATimeQuantity() {
|
||||
PartialDate partialDate = PartialDate.createFrom(new LocalDate(2009, 8,
|
||||
4));
|
||||
assertThat(partialDate.plus(
|
||||
TimeQuantity.empty().plus(3, Granularity.MONTH))
|
||||
.tryToConvertToLocalDate().getMonthOfYear(), equalTo(11));
|
||||
assertThat(partialDate.plus(
|
||||
TimeQuantity.empty().plus(3, Granularity.DAY))
|
||||
.tryToConvertToLocalDate().getDayOfMonth(), equalTo(7));
|
||||
assertThat(partialDate.plus(
|
||||
TimeQuantity.empty().plus(4, Granularity.MONTH))
|
||||
.tryToConvertToLocalDate().getMonthOfYear(), equalTo(12));
|
||||
PartialDate overflowedToYear = partialDate.plus(TimeQuantity.empty()
|
||||
.plus(5, Granularity.MONTH));
|
||||
assertThat(overflowedToYear.tryToConvertToLocalDate().getMonthOfYear(),
|
||||
equalTo(1));
|
||||
assertThat(overflowedToYear.tryToConvertToLocalDate().getYear(),
|
||||
equalTo(2010));
|
||||
assertThat(partialDate.plus(
|
||||
TimeQuantity.empty().plus(-1, Granularity.DAY))
|
||||
.tryToConvertToLocalDate().getDayOfMonth(), equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canAddTimeQuantityWithMillisecondsGranularity() {
|
||||
PartialDate partialDate = PartialDate.createFrom(new LocalDate(2009, 8,
|
||||
4).toDateTimeAtStartOfDay());
|
||||
assertThat(partialDate.valueFor(Granularity.MILLISECONDS), equalTo(0));
|
||||
PartialDate sum = partialDate.plus(TimeQuantity.empty().plus(4,
|
||||
Granularity.MILLISECONDS));
|
||||
assertThat(sum.valueFor(Granularity.MILLISECONDS), equalTo(4));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void theTimeQuantityMustNotHaveGreaterGranularityThanThePartialDate() {
|
||||
PartialDate partialDate = PartialDate.createFrom(new LocalDate(2009, 8,
|
||||
4));
|
||||
partialDate.plus(TimeQuantity.empty().plus(3, Granularity.HOUR));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCreateIntervalsUsingQuantities() {
|
||||
PartialDate start = PartialDate.createFrom(new LocalDate(2009, 8, 4));
|
||||
IntervalOfPartialDates interval = start.to(TimeQuantity.empty().plus(3,
|
||||
Granularity.MONTH));
|
||||
assertThat(
|
||||
interval.getEnd().tryToConvertToLocalDate().getMonthOfYear(),
|
||||
equalTo(11));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package org.navalplanner.business.test.partialtime;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.navalplanner.business.partialtime.TimeQuantity;
|
||||
import org.navalplanner.business.partialtime.PartialDate.Granularity;
|
||||
|
||||
public class TimeQuantityTest {
|
||||
|
||||
@Test
|
||||
public void aEmptyTimeQuantityHasAValueOfZeroForAllGranularities() {
|
||||
TimeQuantity empty = TimeQuantity.empty();
|
||||
for (Granularity granularity : Granularity.values()) {
|
||||
assertThat(empty.valueFor(granularity), equalTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aTimeQuantityIsComposedOfIntengersAssociatedToSeveralGranularities() {
|
||||
TimeQuantity timeQuantity = TimeQuantity.empty().plus(2,
|
||||
Granularity.MONTH).plus(-1, Granularity.DAY);
|
||||
assertThat(timeQuantity.valueFor(Granularity.MONTH), equalTo(2));
|
||||
assertThat(timeQuantity.valueFor(Granularity.DAY), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void theGranularityMustBeNotNull() {
|
||||
TimeQuantity.empty().plus(3, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void severalPlusOnTheSameGranularityAccumulateTheValue() {
|
||||
TimeQuantity timeQuantity = TimeQuantity.empty().plus(2,
|
||||
Granularity.MONTH).plus(4, Granularity.DAY).plus(3,
|
||||
Granularity.MONTH);
|
||||
assertThat(timeQuantity.valueFor(Granularity.MONTH), equalTo(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isInmutable() {
|
||||
TimeQuantity initial = TimeQuantity.empty();
|
||||
TimeQuantity modified = initial.plus(3, Granularity.HOUR);
|
||||
assertNotSame(initial, modified);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theAmountCanBeZero() {
|
||||
TimeQuantity.empty().plus(0, Granularity.MONTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theAmountCanBeNegative() {
|
||||
TimeQuantity.empty().plus(-1, Granularity.MONTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeQuantitiesCanBeAdded() {
|
||||
TimeQuantity one = TimeQuantity.empty().plus(2, Granularity.MONTH)
|
||||
.plus(4, Granularity.DAY);
|
||||
TimeQuantity another = TimeQuantity.empty().plus(3, Granularity.YEAR)
|
||||
.plus(2, Granularity.DAY);
|
||||
TimeQuantity result = one.plus(another);
|
||||
assertThat(result.valueFor(Granularity.MONTH), equalTo(2));
|
||||
assertThat(result.valueFor(Granularity.DAY), equalTo(6));
|
||||
assertThat(result.valueFor(Granularity.YEAR), equalTo(3));
|
||||
assertThat(result.valueFor(Granularity.MINUTE), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSubstractUsingNegativeIntegers() {
|
||||
TimeQuantity one = TimeQuantity.empty().plus(2, Granularity.MONTH)
|
||||
.plus(4, Granularity.DAY);
|
||||
TimeQuantity another = TimeQuantity.empty().plus(3, Granularity.YEAR)
|
||||
.plus(-5, Granularity.DAY);
|
||||
TimeQuantity result = one.plus(another);
|
||||
assertThat(result.valueFor(Granularity.MONTH), equalTo(2));
|
||||
assertThat(result.valueFor(Granularity.DAY), equalTo(-1));
|
||||
assertThat(result.valueFor(Granularity.YEAR), equalTo(3));
|
||||
assertThat(result.valueFor(Granularity.MINUTE), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeQuantitiesDontOverflowIntoLargerGranularities() {
|
||||
TimeQuantity quantity = TimeQuantity.empty()
|
||||
.plus(13, Granularity.MONTH);
|
||||
assertThat(quantity.valueFor(Granularity.MONTH), equalTo(13));
|
||||
assertThat(quantity.valueFor(Granularity.YEAR), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theGreatestGranularitySpecifiedCanBeKnown() {
|
||||
TimeQuantity timeQuantity = TimeQuantity.empty().plus(2,
|
||||
Granularity.MONTH).plus(4, Granularity.DAY);
|
||||
assertThat(timeQuantity.getGreatestGranularitySpecified(),
|
||||
equalTo(Granularity.DAY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void theGranularityOfAnEmptyTimeQuantityIsYear() {
|
||||
TimeQuantity empty = TimeQuantity.empty();
|
||||
assertThat(empty.getGreatestGranularitySpecified(),
|
||||
equalTo(Granularity.YEAR));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
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