/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.addthis.basis.time;
import org.joda.time.DateTime;
import org.joda.time.DateTimeFieldType;
import org.joda.time.DateTimeZone;
import org.joda.time.Days;
import org.joda.time.DurationFieldType;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.junit.Ignore;
import org.junit.Test;
import static com.addthis.basis.time.Dates.rfc1123;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class TestDates {
private DTimeUnit[] types = DTimeUnit.values();
@Test
public void testIterableInterval() {
for (DTimeUnit unit : types) {
switch (unit) {
case ALL_TIME:
default:
testIterableInterval(0, unit);
testIterableInterval(1, unit);
testIterableInterval(2, unit);
testIterableInterval(100, unit);
}
}
}
@SuppressWarnings("unused")
private void testIterableInterval(int length, DTimeUnit unit) {
int expectedCount;
DateTimeFieldType dtft = null;
PeriodType pt = null;
if (unit == DTimeUnit.ALL_TIME) {
dtft = DateTimeFieldType.dayOfMonth();
pt = PeriodType.days();
expectedCount = 1;
} else {
dtft = unit.toDateTimeFieldType();
pt = unit.toPeriodType();
expectedCount = length + 1;
}
Period unitPeriod = Dates.period(1, pt);
DateTime begEarly = new DateTime().property(dtft).roundFloorCopy();
DateTime begLate = begEarly.plus(unitPeriod).minusMillis(1);
DateTime endEarly = begEarly.plus(Dates.period(length, pt));
DateTime endLate = endEarly.plus(unitPeriod).minusMillis(1);
Interval interval = new Interval(begEarly, endEarly);
int count = 0;
for (DateTime dt : Dates.iterableInterval(interval, unit)) {
count++;
}
assertEquals(interval.toString(), expectedCount, count);
interval = new Interval(begEarly, endLate);
count = 0;
for (DateTime dt : Dates.iterableInterval(interval, unit)) {
count++;
}
assertEquals(interval.toString(), expectedCount, count);
interval = new Interval(begLate, endLate);
count = 0;
for (DateTime dt : Dates.iterableInterval(interval, unit)) {
count++;
}
assertEquals(interval.toString(), expectedCount, count);
if (length > 0) {
interval = new Interval(begLate, endEarly);
count = 0;
for (
DateTime dt : Dates.iterableInterval(interval, unit)) {
count++;
}
assertEquals(interval.toString(), expectedCount, count);
}
}
@Test @Ignore("does not handle daylight savings / TZ stuff, and is hard coded in the impl")
public void testTruncateInterval() {
DateTime end = new DateTime();
Interval interval;
for (DTimeUnit per : types) {
switch (per) {
case ALL_TIME:
break;
default:
PeriodType type = per.toPeriodType();
DurationFieldType fieldType = type.getFieldType(0);
// instant (no truncation)
interval = new Interval(Dates.period(0, type), end);
interval = Dates.truncateInterval(interval, 10, type);
assertEquals(interval.toString(), 0, interval.toPeriod(type).get(fieldType));
// interval does not exceed limit (no truncation)
interval = new Interval(Dates.period(5, type), end);
interval = Dates.truncateInterval(interval, 10, type);
assertEquals(interval.toString(), 5, interval.toPeriod(type).get(fieldType));
// interval exceeds limit
interval = new Interval(Dates.period(10, type), end);
interval = Dates.truncateInterval(interval, 10, type);
assertEquals(interval.toString() + ',' + type.getName(), 9, interval.toPeriod(type).get(fieldType));
// null (no truncation)
interval = new Interval(Dates.period(100, type), end);
interval = Dates.truncateInterval(interval, 10, null);
assertEquals(interval.toString(), 100, interval.toPeriod(type).get(fieldType));
// end is in the future
interval = new Interval(Dates.period(11, type), (new DateTime()).plus(Dates.period(10, type)));
interval = Dates.truncateInterval(interval, 5, type);
assertFalse(interval.getEnd().isAfterNow());
assertEquals(interval.toString(), 1, interval.toPeriod(type).get(fieldType));
// end is in the future and limit exceeded
interval = new Interval(Dates.period(20, type), (new DateTime()).plus(Dates.period(10, type)));
interval = Dates.truncateInterval(interval, 5, type);
assertFalse(interval.getEnd().isAfterNow());
assertEquals(interval.toString(), 4, interval.toPeriod(type).get(fieldType));
// start and end are in the future
interval = new Interval((new DateTime()).plus(Dates.period(5, type)), (new DateTime()).plus(Dates.period(10, type)));
interval = Dates.truncateInterval(interval, 3, type);
assertFalse(interval.getEnd().isAfterNow());
assertFalse(interval.getEnd().isBefore(end));
assertEquals(interval.getStart(), interval.getEnd());
}
}
}
@Test
public void testParseInterval() {
DateTime now = new DateTime();
DateTime beg = now.minusMonths(2).withTimeAtStartOfDay();
DateTime end = now.plusMonths(2).withTimeAtStartOfDay();
String begStr = beg.toString(Dates.yMdFormat);
String endStr = end.toString(Dates.yMdFormat);
String invStr = "DEADBEEF";
Interval nowInterval = new Interval(now, now.plusSeconds(30));
// null, null
assertTrue(nowInterval.contains(Dates.parseInterval(null, null)));
// null, E
assertEquals(new Interval(end, end), Dates.parseInterval(null, endStr));
// B, null
assertEquals(new Interval(beg, beg), Dates.parseInterval(begStr, null));
// B, E
assertEquals(new Interval(beg, end), Dates.parseInterval(begStr, endStr));
// E, B
assertEquals(new Interval(beg, beg), Dates.parseInterval(endStr, begStr));
// inv, inv
assertTrue(nowInterval.contains(Dates.parseInterval(invStr, invStr)));
// inv, E
assertEquals(new Interval(end, end), Dates.parseInterval(invStr, endStr));
// B, inv
assertEquals(new Interval(beg, beg), Dates.parseInterval(begStr, invStr));
// inv, null
assertTrue(nowInterval.contains(Dates.parseInterval(invStr, null)));
// null, inv
assertTrue(nowInterval.contains(Dates.parseInterval(null, invStr)));
}
@Test
@Ignore
public void testJoda() {
DateTime begEarly = new DateTime().withTimeAtStartOfDay();
DateTime begNoon = begEarly.withHourOfDay(12);
DateTime begLate = begEarly.withHourOfDay(23);
DateTime endEarly = begEarly.plusDays(2);
DateTime endNoon = endEarly.withHourOfDay(12);
DateTime endLate = endEarly.withHourOfDay(23);
assertEquals(2, Days.daysBetween(begEarly, endEarly).getDays());
assertEquals(2, Days.daysBetween(begEarly, endNoon).getDays());
assertEquals(2, Days.daysBetween(begEarly, endLate).getDays());
assertEquals(1, Days.daysBetween(begNoon, endEarly).getDays());
assertEquals(2, Days.daysBetween(begNoon, endNoon).getDays());
assertEquals(2, Days.daysBetween(begNoon, endLate).getDays());
assertEquals(1, Days.daysBetween(begLate, endEarly).getDays());
assertEquals(1, Days.daysBetween(begLate, endNoon).getDays());
assertEquals(2, Days.daysBetween(begLate, endLate).getDays());
Interval interval = new Interval(null);
assertTrue(interval.toString(), interval.getStart().equals(interval.getEnd()));
}
@Test
public void testRfc1123() {
DateTime dt = new DateTime(0, DateTimeZone.UTC);
assertEquals("Thu, 01 Jan 1970 00:00:00 +0000", dt.toString(rfc1123));
dt = new DateTime(2050, 12, 26, 11, 33, 8, 0, DateTimeZone.UTC);
assertEquals("Mon, 26 Dec 2050 11:33:08 +0000", dt.toString(rfc1123));
dt = new DateTime(2050, 12, 26, 11, 33, 8, 0, DateTimeZone.forID("EST"));
assertEquals("Mon, 26 Dec 2050 11:33:08 -0500", dt.toString(rfc1123));
}
}