/*
* Copyright (C) 2016 Facebook, Inc.
*
* 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.facebook.util;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.testng.Assert;
import org.testng.annotations.Test;
import static com.facebook.util.TimeIntervalType.DAY;
import static com.facebook.util.TimeIntervalType.HOUR;
import static com.facebook.util.TimeIntervalType.MILLIS;
import static com.facebook.util.TimeIntervalType.MINUTE;
import static com.facebook.util.TimeIntervalType.MONTH;
import static com.facebook.util.TimeIntervalType.SECOND;
import static com.facebook.util.TimeIntervalType.WEEK;
import static com.facebook.util.TimeIntervalType.YEAR;
import static org.joda.time.DateTimeZone.UTC;
/**
* Mostly conformance testing: these aren't testing how things <em>should</em> work but rather how
* they <em>do</em> work (since there's a lot of code that relies on the existing behavior).
*/
public class TestTimeIntervalType {
private static final DateTimeZone PDT = DateTimeZone.forID("America/Los_Angeles");
@Test
public void testMillisIntervalStart() throws Exception {
assertStart("2016-04-13T11:26:47.856-07:00", PDT, MILLIS, 1, "2016-04-13T11:26:47.856-07:00");
assertStart("2016-04-13T11:26:47.856-07:00", PDT, MILLIS, 100, "2016-04-13T11:26:47.800-07:00");
assertStart("2016-04-13T11:26:48.356-07:00", PDT, MILLIS, 1, "2016-04-13T11:26:48.356-07:00");
assertStart("2016-04-13T11:26:48.356-07:00", PDT, MILLIS, 100, "2016-04-13T11:26:48.300-07:00");
}
@Test
public void testSecondsIntervalStart() throws Exception {
assertStart("2016-04-13T11:25:51.302-07:00", PDT, SECOND, 1, "2016-04-13T11:25:51.000-07:00");
assertStart("2016-04-13T11:25:51.302-07:00", PDT, SECOND, 10, "2016-04-13T11:25:50.000-07:00");
assertStart("2016-04-13T11:25:51.302-07:00", PDT, SECOND, 30, "2016-04-13T11:25:30.000-07:00");
assertStart("2016-04-13T11:26:11.302-07:00", PDT, SECOND, 1, "2016-04-13T11:26:11.000-07:00");
assertStart("2016-04-13T11:26:11.302-07:00", PDT, SECOND, 10, "2016-04-13T11:26:10.000-07:00");
assertStart("2016-04-13T11:26:11.302-07:00", PDT, SECOND, 30, "2016-04-13T11:26:00.000-07:00");
}
@Test
public void testMinuteIntervalStart() throws Exception {
assertStart("2016-04-13T11:20:29.330-07:00", PDT, MINUTE, 1, "2016-04-13T11:20:00.000-07:00");
assertStart("2016-04-13T11:20:29.330-07:00", PDT, MINUTE, 5, "2016-04-13T11:20:00.000-07:00");
assertStart("2016-04-13T11:20:29.330-07:00", PDT, MINUTE, 15, "2016-04-13T11:15:00.000-07:00");
assertStart("2016-04-13T11:20:29.330-07:00", PDT, MINUTE, 30, "2016-04-13T11:00:00.000-07:00");
assertStart("2016-04-13T11:40:29.330-07:00", PDT, MINUTE, 1, "2016-04-13T11:40:00.000-07:00");
assertStart("2016-04-13T11:40:29.330-07:00", PDT, MINUTE, 5, "2016-04-13T11:40:00.000-07:00");
assertStart("2016-04-13T11:40:29.330-07:00", PDT, MINUTE, 15, "2016-04-13T11:30:00.000-07:00");
assertStart("2016-04-13T11:40:29.330-07:00", PDT, MINUTE, 30, "2016-04-13T11:30:00.000-07:00");
}
@Test
public void testDayIntervalStartUTC() throws Exception {
assertStart("2016-01-13T00:52:38.337Z", UTC, DAY, 1, "2016-01-13T00:00:00.000Z");
assertStart("2016-02-13T02:52:38.337Z", UTC, DAY, 2, "2016-02-13T00:00:00.000Z");
assertStart("2016-03-13T04:52:38.337Z", UTC, DAY, 3, "2016-03-13T00:00:00.000Z");
assertStart("2016-04-13T06:52:38.337Z", UTC, DAY, 5, "2016-04-11T00:00:00.000Z");
assertStart("2016-05-13T08:52:38.337Z", UTC, DAY, 7, "2016-05-08T00:00:00.000Z");
assertStart("2016-06-13T10:52:38.337Z", UTC, DAY, 14, "2016-06-01T00:00:00.000Z");
assertStart("2016-07-13T12:52:38.337Z", UTC, DAY, 30, "2016-07-01T00:00:00.000Z");
assertStart("2016-08-13T14:52:38.337Z", UTC, DAY, 1, "2016-08-13T00:00:00.000Z");
assertStart("2016-09-13T16:52:38.337Z", UTC, DAY, 2, "2016-09-13T00:00:00.000Z");
assertStart("2016-10-13T18:52:38.337Z", UTC, DAY, 3, "2016-10-13T00:00:00.000Z");
assertStart("2016-11-13T20:52:38.337Z", UTC, DAY, 5, "2016-11-11T00:00:00.000Z");
assertStart("2016-12-13T22:52:38.337Z", UTC, DAY, 7, "2016-12-08T00:00:00.000Z");
}
@Test
public void testDayIntervalStartPDT() throws Exception {
assertStart("2016-01-13T00:51:03.772-08:00", PDT, DAY, 1, "2016-01-13T00:00:00.000-08:00");
assertStart("2016-02-13T02:51:03.772-08:00", PDT, DAY, 2, "2016-02-13T00:00:00.000-08:00");
assertStart("2016-03-13T04:51:03.772-07:00", PDT, DAY, 3, "2016-03-13T00:00:00.000-08:00");
assertStart("2016-04-13T06:51:03.772-07:00", PDT, DAY, 5, "2016-04-11T00:00:00.000-07:00");
assertStart("2016-05-13T08:51:03.772-07:00", PDT, DAY, 7, "2016-05-08T00:00:00.000-07:00");
assertStart("2016-06-13T10:51:03.772-07:00", PDT, DAY, 14, "2016-06-01T00:00:00.000-07:00");
assertStart("2016-07-13T12:51:03.772-07:00", PDT, DAY, 30, "2016-07-01T00:00:00.000-07:00");
assertStart("2016-08-13T14:51:03.772-07:00", PDT, DAY, 1, "2016-08-13T00:00:00.000-07:00");
assertStart("2016-09-13T16:51:03.772-07:00", PDT, DAY, 2, "2016-09-13T00:00:00.000-07:00");
assertStart("2016-10-13T18:51:03.772-07:00", PDT, DAY, 3, "2016-10-13T00:00:00.000-07:00");
assertStart("2016-11-13T20:51:03.772-08:00", PDT, DAY, 5, "2016-11-11T00:00:00.000-08:00");
assertStart("2016-12-13T22:51:03.772-08:00", PDT, DAY, 7, "2016-12-08T00:00:00.000-08:00");
}
@Test
public void testHourIntervalStartUTC() throws Exception {
assertStart("2016-01-02T00:00:00.000Z", UTC, HOUR, 1, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T02:00:00.000Z", UTC, HOUR, 3, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T04:00:00.000Z", UTC, HOUR, 7, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T06:00:00.000Z", UTC, HOUR, 13, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T08:00:00.000Z", UTC, HOUR, 21, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T10:00:00.000Z", UTC, HOUR, 1, "2016-01-02T10:00:00.000Z");
assertStart("2016-01-02T12:00:00.000Z", UTC, HOUR, 3, "2016-01-02T12:00:00.000Z");
assertStart("2016-01-02T14:00:00.000Z", UTC, HOUR, 7, "2016-01-02T14:00:00.000Z");
assertStart("2016-01-02T16:00:00.000Z", UTC, HOUR, 13, "2016-01-02T13:00:00.000Z");
assertStart("2016-01-02T18:00:00.000Z", UTC, HOUR, 21, "2016-01-02T00:00:00.000Z");
assertStart("2016-01-02T20:00:00.000Z", UTC, HOUR, 1, "2016-01-02T20:00:00.000Z");
assertStart("2016-01-02T22:00:00.000Z", UTC, HOUR, 3, "2016-01-02T21:00:00.000Z");
}
@Test
public void testHourIntervalStartPDT() throws Exception {
assertStart("2016-01-02T00:00:00.000-08:00", PDT, HOUR, 1, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T02:00:00.000-08:00", PDT, HOUR, 3, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T04:00:00.000-08:00", PDT, HOUR, 7, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T06:00:00.000-08:00", PDT, HOUR, 13, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T08:00:00.000-08:00", PDT, HOUR, 21, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T10:00:00.000-08:00", PDT, HOUR, 1, "2016-01-02T10:00:00.000-08:00");
assertStart("2016-01-02T12:00:00.000-08:00", PDT, HOUR, 3, "2016-01-02T12:00:00.000-08:00");
assertStart("2016-01-02T14:00:00.000-08:00", PDT, HOUR, 7, "2016-01-02T14:00:00.000-08:00");
assertStart("2016-01-02T16:00:00.000-08:00", PDT, HOUR, 13, "2016-01-02T13:00:00.000-08:00");
assertStart("2016-01-02T18:00:00.000-08:00", PDT, HOUR, 21, "2016-01-02T00:00:00.000-08:00");
assertStart("2016-01-02T20:00:00.000-08:00", PDT, HOUR, 1, "2016-01-02T20:00:00.000-08:00");
assertStart("2016-01-02T22:00:00.000-08:00", PDT, HOUR, 3, "2016-01-02T21:00:00.000-08:00");
}
@Test
public void testWeekIntervalStartUTC() throws Exception {
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 1, "2016-04-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 2, "2016-03-25T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 3, "2016-03-25T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 11, "2016-03-18T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 26, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, WEEK, 50, "2016-01-01T00:00:00.000Z");
}
@Test
public void testWeekIntervalStartPDT() throws Exception {
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 1, "2016-04-01T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 2, "2016-03-25T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 3, "2016-03-25T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 11, "2016-03-18T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 26, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, WEEK, 50, "2016-01-01T00:00:00.000-08:00");
}
@Test
public void testMonthIntervalStartUTC() throws Exception {
assertStart("2016-04-05T00:00:00.000Z", UTC, MONTH, 1, "2016-04-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, MONTH, 2, "2016-03-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, MONTH, 3, "2016-04-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, MONTH, 7, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, MONTH, 12, "2016-01-01T00:00:00.000Z");
}
@Test
public void testMonthIntervalStartPDT() throws Exception {
assertStart("2016-04-05T00:00:00.000-07:00", PDT, MONTH, 1, "2016-04-01T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, MONTH, 2, "2016-03-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, MONTH, 3, "2016-04-01T00:00:00.000-07:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, MONTH, 7, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, MONTH, 12, "2016-01-01T00:00:00.000-08:00");
}
@Test
public void testYearIntervalStartUTC() throws Exception {
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 1, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 2, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 3, "2015-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 4, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 5, "2015-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 6, "2012-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 7, "2014-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 8, "2016-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 9, "2009-01-01T00:00:00.000Z");
assertStart("2016-04-05T00:00:00.000Z", UTC, YEAR, 10, "2010-01-01T00:00:00.000Z");
}
@Test
public void testYearIntervalStartPDT() throws Exception {
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 1, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 2, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 3, "2015-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 4, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 5, "2015-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 6, "2012-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 7, "2014-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 8, "2016-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 9, "2009-01-01T00:00:00.000-08:00");
assertStart("2016-04-05T00:00:00.000-07:00", PDT, YEAR, 10, "2010-01-01T00:00:00.000-08:00");
}
@Test
public void testHourGetTimeIntervalStartGap() throws Exception {
DateTimeZone timeZone = DateTimeZone.forID("America/Havana");
// Daylight saving causes a gap at midnight: time jumps from midnight to 1am on the 13th.
// This test checks that hourly code can correctly handle 00:00 not being a valid time.
assertStart("2016-03-13T15:09:26.535-0400", timeZone, HOUR, 1, "2016-03-13T15:00:00-0400");
}
@Test
public void testDayGetTimeIntervalStartGap() throws Exception {
DateTimeZone timeZone = DateTimeZone.forID("Asia/Amman");
// Daylight saving causes a gap at midnight: time jumps from midnight to 1am on the 1st.
// This test checks that daily code can correctly handle 04-01T00:00 not being a valid time.
assertStart("2016-04-12T15:09:26.535+0200", timeZone, DAY, 1, "2016-04-12T01:00:00.000+03:00");
}
private static void assertStart(
String date, DateTimeZone timeZone, TimeIntervalType type, int length, String expected
) {
DateTime actual = type.getTimeIntervalStart(new DateTime(date, timeZone), length);
Assert.assertEquals(actual, new DateTime(expected, timeZone), length + " " + type);
}
}