diff options
Diffstat (limited to 'tests/src/com/android/calendarcommon2/TimeTest.java')
-rw-r--r-- | tests/src/com/android/calendarcommon2/TimeTest.java | 762 |
1 files changed, 762 insertions, 0 deletions
diff --git a/tests/src/com/android/calendarcommon2/TimeTest.java b/tests/src/com/android/calendarcommon2/TimeTest.java new file mode 100644 index 0000000..df27c4f --- /dev/null +++ b/tests/src/com/android/calendarcommon2/TimeTest.java @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * 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.android.calendarcommon2; + +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.TimeFormatException; + +import junit.framework.TestCase; + +/** + * Tests for com.android.calendarcommon2.Time. + * + * Some of these tests are borrowed from android.text.format.TimeTest. + */ +public class TimeTest extends TestCase { + + @SmallTest + public void testNullTimezone() { + try { + Time t = new Time(null); + fail("expected a null timezone to throw an exception."); + } catch (NullPointerException npe) { + // expected. + } + } + + @SmallTest + public void testTimezone() { + Time t = new Time(Time.TIMEZONE_UTC); + assertEquals(Time.TIMEZONE_UTC, t.getTimezone()); + } + + @SmallTest + public void testSwitchTimezone() { + Time t = new Time(Time.TIMEZONE_UTC); + String newTimezone = "America/Los_Angeles"; + t.switchTimezone(newTimezone); + assertEquals(newTimezone, t.getTimezone()); + } + + @SmallTest + public void testGetActualMaximum() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 0, 2020); + assertEquals(59, t.getActualMaximum(Time.SECOND)); + assertEquals(59, t.getActualMaximum(Time.MINUTE)); + assertEquals(23, t.getActualMaximum(Time.HOUR)); + assertEquals(31, t.getActualMaximum(Time.MONTH_DAY)); + assertEquals(11, t.getActualMaximum(Time.MONTH)); + assertEquals(7, t.getActualMaximum(Time.WEEK_DAY)); + assertEquals(366, t.getActualMaximum(Time.YEAR_DAY)); // 2020 is a leap year + t.set(1, 0, 2019); + assertEquals(365, t.getActualMaximum(Time.YEAR_DAY)); + } + + @SmallTest + public void testAdd() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(0, 0, 0, 1, 0, 2020); + t.add(Time.SECOND, 1); + assertEquals(1, t.getSecond()); + t.add(Time.MINUTE, 1); + assertEquals(1, t.getMinute()); + t.add(Time.HOUR, 1); + assertEquals(1, t.getHour()); + t.add(Time.MONTH_DAY, 1); + assertEquals(2, t.getDay()); + t.add(Time.MONTH, 1); + assertEquals(1, t.getMonth()); + t.add(Time.YEAR, 1); + assertEquals(2021, t.getYear()); + } + + @SmallTest + public void testClear() { + Time t = new Time(Time.TIMEZONE_UTC); + t.clear(Time.TIMEZONE_UTC); + + assertEquals(Time.TIMEZONE_UTC, t.getTimezone()); + assertFalse(t.isAllDay()); + assertEquals(0, t.getSecond()); + assertEquals(0, t.getMinute()); + assertEquals(0, t.getHour()); + assertEquals(1, t.getDay()); // default for Calendar is 1 + assertEquals(0, t.getMonth()); + assertEquals(1970, t.getYear()); + assertEquals(4, t.getWeekDay()); // 1970 Jan 1 --> Thursday + assertEquals(0, t.getYearDay()); + assertEquals(0, t.getGmtOffset()); + } + + @SmallTest + public void testCompare() { + Time a = new Time(Time.TIMEZONE_UTC); + Time b = new Time("America/Los_Angeles"); + assertTrue(a.compareTo(b) < 0); + + Time c = new Time("Asia/Calcutta"); + assertTrue(a.compareTo(c) > 0); + + Time d = new Time(Time.TIMEZONE_UTC); + assertEquals(0, a.compareTo(d)); + } + + @SmallTest + public void testFormat2445() { + Time t = new Time(); + assertEquals("19700101T000000", t.format2445()); + t.setTimezone(Time.TIMEZONE_UTC); + assertEquals("19700101T000000Z", t.format2445()); + t.setAllDay(true); + assertEquals("19700101", t.format2445()); + } + + @SmallTest + public void testFormat3339() { + Time t = new Time(Time.TIMEZONE_UTC); + assertEquals("1970-01-01", t.format3339(true)); + t.set(29, 1, 2020); + assertEquals("2020-02-29", t.format3339(true)); + } + + @SmallTest + public void testToMillis() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 0, 0, 1, 0, 1970); + assertEquals(1000L, t.toMillis()); + + t.set(0, 0, 0, 1, 1, 2020); + assertEquals(1580515200000L, t.toMillis()); + t.set(1, 0, 0, 1, 1, 2020); + assertEquals(1580515201000L, t.toMillis()); + + t.set(1, 0, 2020); + assertEquals(1577836800000L, t.toMillis()); + t.set(1, 1, 2020); + assertEquals(1580515200000L, t.toMillis()); + } + + @SmallTest + public void testToMillis_overflow() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(32, 0, 2020); + assertEquals(1580515200000L, t.toMillis()); + assertEquals(1, t.getDay()); + assertEquals(1, t.getMonth()); + } + + @SmallTest + public void testParse() { + Time t = new Time(Time.TIMEZONE_UTC); + t.parse("20201010T160000Z"); + assertEquals(2020, t.getYear()); + assertEquals(9, t.getMonth()); + assertEquals(10, t.getDay()); + assertEquals(16, t.getHour()); + assertEquals(0, t.getMinute()); + assertEquals(0, t.getSecond()); + + t.parse("20200220"); + assertEquals(2020, t.getYear()); + assertEquals(1, t.getMonth()); + assertEquals(20, t.getDay()); + assertEquals(0, t.getHour()); + assertEquals(0, t.getMinute()); + assertEquals(0, t.getSecond()); + + try { + t.parse("invalid"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + + try { + t.parse("20201010Z160000"); + fail(); + } catch (IllegalArgumentException e) { + // expected + } + } + + @SmallTest + public void testParse3339() { + Time t = new Time(Time.TIMEZONE_UTC); + + t.parse3339("1980-05-23"); + if (!t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23) { + fail("Did not parse all-day date correctly"); + } + + t.parse3339("1980-05-23T09:50:50"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse timezone-offset-less date correctly"); + } + + t.parse3339("1980-05-23T09:50:50Z"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse UTC date correctly"); + } + + t.parse3339("1980-05-23T09:50:50.0Z"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse UTC date correctly"); + } + + t.parse3339("1980-05-23T09:50:50.12Z"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse UTC date correctly"); + } + + t.parse3339("1980-05-23T09:50:50.123Z"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse UTC date correctly"); + } + + // the time should be normalized to UTC + t.parse3339("1980-05-23T09:50:50-01:05"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 10 || t.getMinute() != 55 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse timezone-offset date correctly"); + } + + // the time should be normalized to UTC + t.parse3339("1980-05-23T09:50:50.123-01:05"); + if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 + || t.getHour() != 10 || t.getMinute() != 55 || t.getSecond() != 50 + || t.getGmtOffset() != 0) { + fail("Did not parse timezone-offset date correctly"); + } + + try { + t.parse3339("1980"); + fail("Did not throw error on truncated input length"); + } catch (TimeFormatException e) { + // successful + } + + try { + t.parse3339("1980-05-23T09:50:50.123+"); + fail("Did not throw error on truncated timezone offset"); + } catch (TimeFormatException e1) { + // successful + } + + try { + t.parse3339("1980-05-23T09:50:50.123+05:0"); + fail("Did not throw error on truncated timezone offset"); + } catch (TimeFormatException e1) { + // successful + } + } + + @SmallTest + public void testSet_millis() { + Time t = new Time(Time.TIMEZONE_UTC); + + t.set(1000L); + assertEquals(1970, t.getYear()); + assertEquals(1, t.getSecond()); + + t.set(2000L); + assertEquals(2, t.getSecond()); + assertEquals(0, t.getMinute()); + + t.set(1000L * 60); + assertEquals(1, t.getMinute()); + assertEquals(0, t.getHour()); + + t.set(1000L * 60 * 60); + assertEquals(1, t.getHour()); + assertEquals(1, t.getDay()); + + t.set((1000L * 60 * 60 * 24) + 1000L); + assertEquals(2, t.getDay()); + assertEquals(1970, t.getYear()); + } + + @SmallTest + public void testSet_dayMonthYear() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 2, 2021); + assertEquals(1, t.getDay()); + assertEquals(2, t.getMonth()); + assertEquals(2021, t.getYear()); + } + + @SmallTest + public void testSet_secondMinuteHour() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 2, 3, 4, 5, 2021); + assertEquals(1, t.getSecond()); + assertEquals(2, t.getMinute()); + assertEquals(3, t.getHour()); + assertEquals(4, t.getDay()); + assertEquals(5, t.getMonth()); + assertEquals(2021, t.getYear()); + } + + @SmallTest + public void testSet_overflow() { + // Jan 32nd --> Feb 1st + Time t = new Time(Time.TIMEZONE_UTC); + t.set(32, 0, 2020); + assertEquals(1, t.getDay()); + assertEquals(1, t.getMonth()); + assertEquals(2020, t.getYear()); + + t = new Time(Time.TIMEZONE_UTC); + t.set(5, 10, 15, 32, 0, 2020); + assertEquals(5, t.getSecond()); + assertEquals(10, t.getMinute()); + assertEquals(15, t.getHour()); + assertEquals(1, t.getDay()); + assertEquals(1, t.getMonth()); + assertEquals(2020, t.getYear()); + } + + @SmallTest + public void testSet_other() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1, 2, 3, 4, 5, 2021); + Time t2 = new Time(); + t2.set(t); + assertEquals(Time.TIMEZONE_UTC, t2.getTimezone()); + assertEquals(1, t2.getSecond()); + assertEquals(2, t2.getMinute()); + assertEquals(3, t2.getHour()); + assertEquals(4, t2.getDay()); + assertEquals(5, t2.getMonth()); + assertEquals(2021, t2.getYear()); + } + + @SmallTest + public void testSetToNow() { + long now = System.currentTimeMillis(); + Time t = new Time(Time.TIMEZONE_UTC); + t.set(now); + long ms = t.toMillis(); + // ensure time is within 1 second because of rounding errors + assertTrue("now: " + now + "; actual: " + ms, Math.abs(ms - now) < 1000); + } + + @SmallTest + public void testGetWeekNumber() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(1000L); + assertEquals(1, t.getWeekNumber()); + t.set(1, 1, 2020); + assertEquals(5, t.getWeekNumber()); + + // ensure ISO 8601 standards are met: weeks start on Monday and the first week has at least + // 4 days in it (the year's first Thursday or Jan 4th) + for (int i = 1; i <= 8; i++) { + t.set(i, 0, 2020); + // Jan 6th is the first Monday in 2020 so that would be week 2 + assertEquals(i < 6 ? 1 : 2, t.getWeekNumber()); + } + } + + private static class DateTest { + public int year1; + public int month1; + public int day1; + public int hour1; + public int minute1; + + public int offset; + + public int year2; + public int month2; + public int day2; + public int hour2; + public int minute2; + + public DateTest(int year1, int month1, int day1, int hour1, int minute1, + int offset, int year2, int month2, int day2, int hour2, int minute2) { + this.year1 = year1; + this.month1 = month1; + this.day1 = day1; + this.hour1 = hour1; + this.minute1 = minute1; + this.offset = offset; + this.year2 = year2; + this.month2 = month2; + this.day2 = day2; + this.hour2 = hour2; + this.minute2 = minute2; + } + + public boolean equals(Time time) { + return time.getYear() == year2 && time.getMonth() == month2 && time.getDay() == day2 + && time.getHour() == hour2 && time.getMinute() == minute2; + } + } + + @SmallTest + public void testNormalize() { + Time t = new Time(Time.TIMEZONE_UTC); + t.parse("20060432T010203"); + assertEquals(1146531723000L, t.normalize()); + } + + /* These tests assume that DST changes on Nov 4, 2007 at 2am (to 1am). */ + + // The "offset" field in "dayTests" represents days. + // Note: the month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 + private DateTest[] dayTests = { + // Nov 4, 12am + 0 day = Nov 4, 12am + new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), + // Nov 5, 12am + 0 day = Nov 5, 12am + new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), + // Nov 3, 12am + 1 day = Nov 4, 12am + new DateTest(2007, 10, 3, 0, 0, 1, 2007, 10, 4, 0, 0), + // Nov 4, 12am + 1 day = Nov 5, 12am + new DateTest(2007, 10, 4, 0, 0, 1, 2007, 10, 5, 0, 0), + // Nov 5, 12am + 1 day = Nov 6, 12am + new DateTest(2007, 10, 5, 0, 0, 1, 2007, 10, 6, 0, 0), + // Nov 3, 1am + 1 day = Nov 4, 1am + new DateTest(2007, 10, 3, 1, 0, 1, 2007, 10, 4, 1, 0), + // Nov 4, 1am + 1 day = Nov 5, 1am + new DateTest(2007, 10, 4, 1, 0, 1, 2007, 10, 5, 1, 0), + // Nov 5, 1am + 1 day = Nov 6, 1am + new DateTest(2007, 10, 5, 1, 0, 1, 2007, 10, 6, 1, 0), + // Nov 3, 2am + 1 day = Nov 4, 2am + new DateTest(2007, 10, 3, 2, 0, 1, 2007, 10, 4, 2, 0), + // Nov 4, 2am + 1 day = Nov 5, 2am + new DateTest(2007, 10, 4, 2, 0, 1, 2007, 10, 5, 2, 0), + // Nov 5, 2am + 1 day = Nov 6, 2am + new DateTest(2007, 10, 5, 2, 0, 1, 2007, 10, 6, 2, 0), + }; + + // The "offset" field in "minuteTests" represents minutes. + // Note: the month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 + private DateTest[] minuteTests = { + // Nov 4, 12am + 0 minutes = Nov 4, 12am + new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), + // Nov 4, 12am + 60 minutes = Nov 4, 1am + new DateTest(2007, 10, 4, 0, 0, 60, 2007, 10, 4, 1, 0), + // Nov 5, 12am + 0 minutes = Nov 5, 12am + new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), + // Nov 3, 12am + 60 minutes = Nov 3, 1am + new DateTest(2007, 10, 3, 0, 0, 60, 2007, 10, 3, 1, 0), + // Nov 4, 12am + 60 minutes = Nov 4, 1am + new DateTest(2007, 10, 4, 0, 0, 60, 2007, 10, 4, 1, 0), + // Nov 5, 12am + 60 minutes = Nov 5, 1am + new DateTest(2007, 10, 5, 0, 0, 60, 2007, 10, 5, 1, 0), + // Nov 3, 1am + 60 minutes = Nov 3, 2am + new DateTest(2007, 10, 3, 1, 0, 60, 2007, 10, 3, 2, 0), + // Nov 4, 12:59am (PDT) + 2 minutes = Nov 4, 1:01am (PDT) + new DateTest(2007, 10, 4, 0, 59, 2, 2007, 10, 4, 1, 1), + // Nov 4, 12:59am (PDT) + 62 minutes = Nov 4, 1:01am (PST) + new DateTest(2007, 10, 4, 0, 59, 62, 2007, 10, 4, 1, 1), + // Nov 4, 12:30am (PDT) + 120 minutes = Nov 4, 1:30am (PST) + new DateTest(2007, 10, 4, 0, 30, 120, 2007, 10, 4, 1, 30), + // Nov 4, 12:30am (PDT) + 90 minutes = Nov 4, 1:00am (PST) + new DateTest(2007, 10, 4, 0, 30, 90, 2007, 10, 4, 1, 0), + // Nov 4, 1am (PDT) + 30 minutes = Nov 4, 1:30am (PDT) + new DateTest(2007, 10, 4, 1, 0, 30, 2007, 10, 4, 1, 30), + // Nov 4, 1:30am (PDT) + 15 minutes = Nov 4, 1:45am (PDT) + new DateTest(2007, 10, 4, 1, 30, 15, 2007, 10, 4, 1, 45), + // Mar 11, 1:30am (PST) + 30 minutes = Mar 11, 3am (PDT) + new DateTest(2007, 2, 11, 1, 30, 30, 2007, 2, 11, 3, 0), + // Nov 4, 1:30am (PST) + 15 minutes = Nov 4, 1:45am (PST) + new DateTest(2007, 10, 4, 1, 30, 15, 2007, 10, 4, 1, 45), + // Nov 4, 1:30am (PST) + 30 minutes = Nov 4, 2:00am (PST) + new DateTest(2007, 10, 4, 1, 30, 30, 2007, 10, 4, 2, 0), + // Nov 5, 1am + 60 minutes = Nov 5, 2am + new DateTest(2007, 10, 5, 1, 0, 60, 2007, 10, 5, 2, 0), + // Nov 3, 2am + 60 minutes = Nov 3, 3am + new DateTest(2007, 10, 3, 2, 0, 60, 2007, 10, 3, 3, 0), + // Nov 4, 2am + 30 minutes = Nov 4, 2:30am + new DateTest(2007, 10, 4, 2, 0, 30, 2007, 10, 4, 2, 30), + // Nov 4, 2am + 60 minutes = Nov 4, 3am + new DateTest(2007, 10, 4, 2, 0, 60, 2007, 10, 4, 3, 0), + // Nov 5, 2am + 60 minutes = Nov 5, 3am + new DateTest(2007, 10, 5, 2, 0, 60, 2007, 10, 5, 3, 0), + // NOTE: Calendar assumes 1am PDT == 1am PST, the two are not distinct, hence why the transition boundary itself has no tests + }; + + @MediumTest + public void testNormalize_dst() { + Time local = new Time("America/Los_Angeles"); + + int len = dayTests.length; + for (int index = 0; index < len; index++) { + DateTest test = dayTests[index]; + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.add(Time.MONTH_DAY, test.offset); + if (!test.equals(local)) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.getYear(), local.getMonth(), local.getDay(), local.getHour(), + local.getMinute()); + fail("Expected: " + expectedTime + "; Actual: " + actualTime); + } + + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.add(Time.MONTH_DAY, test.offset); + if (!test.equals(local)) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.getYear(), local.getMonth(), local.getDay(), local.getHour(), + local.getMinute()); + fail("Expected: " + expectedTime + "; Actual: " + actualTime); + } + } + + len = minuteTests.length; + for (int index = 0; index < len; index++) { + DateTest test = minuteTests[index]; + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.add(Time.MINUTE, test.offset); + if (!test.equals(local)) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.getYear(), local.getMonth(), local.getDay(), local.getHour(), + local.getMinute()); + fail("Expected: " + expectedTime + "; Actual: " + actualTime); + } + + local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); + local.add(Time.MINUTE, test.offset); + if (!test.equals(local)) { + String expectedTime = String.format("%d-%02d-%02d %02d:%02d", + test.year2, test.month2, test.day2, test.hour2, test.minute2); + String actualTime = String.format("%d-%02d-%02d %02d:%02d", + local.getYear(), local.getMonth(), local.getDay(), local.getHour(), + local.getMinute()); + fail("Expected: " + expectedTime + "; Actual: " + actualTime); + } + } + } + + @SmallTest + public void testNormalize_overflow() { + Time t = new Time(Time.TIMEZONE_UTC); + t.set(32, 0, 2020); + t.normalize(); + assertEquals(1, t.getDay()); + assertEquals(1, t.getMonth()); + } + + @SmallTest + public void testDstBehavior_addDays_ignoreDst() { + Time time = new Time("America/Los_Angeles"); + time.set(4, 10, 2007); // set to Nov 4, 2007, 12am + assertEquals(1194159600000L, time.normalize()); + time.add(Time.MONTH_DAY, 1); // changes to Nov 5, 2007, 12am + assertEquals(1194249600000L, time.toMillis()); + + time = new Time("America/Los_Angeles"); + time.set(11, 2, 2007); // set to Mar 11, 2007, 12am + assertEquals(1173600000000L, time.normalize()); + time.add(Time.MONTH_DAY, 1); // changes to Mar 12, 2007, 12am + assertEquals(1173682800000L, time.toMillis()); + } + + @SmallTest + public void testDstBehavior_addDays_applyDst() { + if (!Time.APPLY_DST_CHANGE_LOGIC) { + return; + } + Time time = new Time("America/Los_Angeles"); + time.set(4, 10, 2007); // set to Nov 4, 2007, 12am + assertEquals(1194159600000L, time.normalizeApplyDst()); + time.add(Time.MONTH_DAY, 1); // changes to Nov 4, 2007, 11pm (fall back) + assertEquals(1194246000000L, time.toMillisApplyDst()); + + time = new Time("America/Los_Angeles"); + time.set(11, 2, 2007); // set to Mar 11, 2007, 12am + assertEquals(1173600000000L, time.normalizeApplyDst()); + time.add(Time.MONTH_DAY, 1); // changes to Mar 12, 2007, 1am (roll forward) + assertEquals(1173686400000L, time.toMillisApplyDst()); + } + + @SmallTest + public void testDstBehavior_addHours_ignoreDst() { + // Note: by default, Calendar applies DST logic if adding hours or minutes but not if adding + // days, hence in this test, only if the APPLY_DST_CHANGE_LOGIC flag is false, then the time + // is adjusted with DST + Time time = new Time("America/Los_Angeles"); + time.set(4, 10, 2007); // set to Nov 4, 2007, 12am + assertEquals(1194159600000L, time.normalize()); + time.add(Time.HOUR, 24); // changes to Nov 5, 2007, 12am + assertEquals(Time.APPLY_DST_CHANGE_LOGIC ? 1194249600000L : 1194246000000L, + time.toMillis()); + + time = new Time("America/Los_Angeles"); + time.set(11, 2, 2007); // set to Mar 11, 2007, 12am + assertEquals(1173600000000L, time.normalize()); + time.add(Time.HOUR, 24); // changes to Mar 12, 2007, 12am + assertEquals(Time.APPLY_DST_CHANGE_LOGIC ? 1173682800000L : 1173686400000L, + time.toMillis()); + } + + @SmallTest + public void testDstBehavior_addHours_applyDst() { + if (!Time.APPLY_DST_CHANGE_LOGIC) { + return; + } + Time time = new Time("America/Los_Angeles"); + time.set(4, 10, 2007); // set to Nov 4, 2007, 12am + assertEquals(1194159600000L, time.normalizeApplyDst()); + time.add(Time.HOUR, 24); // changes to Nov 4, 2007, 11pm (fall back) + assertEquals(1194246000000L, time.toMillisApplyDst()); + + time = new Time("America/Los_Angeles"); + time.set(11, 2, 2007); // set to Mar 11, 2007, 12am + assertEquals(1173600000000L, time.normalizeApplyDst()); + time.add(Time.HOUR, 24); // changes to Mar 12, 2007, 1am (roll forward) + assertEquals(1173686400000L, time.toMillisApplyDst()); + } + + // Timezones that cover the world. + // Some GMT offsets occur more than once in case some cities decide to change their GMT offset. + private static final String[] mTimeZones = { + "Pacific/Kiritimati", + "Pacific/Enderbury", + "Pacific/Fiji", + "Antarctica/South_Pole", + "Pacific/Norfolk", + "Pacific/Ponape", + "Asia/Magadan", + "Australia/Lord_Howe", + "Australia/Sydney", + "Australia/Adelaide", + "Asia/Tokyo", + "Asia/Seoul", + "Asia/Taipei", + "Asia/Singapore", + "Asia/Hong_Kong", + "Asia/Saigon", + "Asia/Bangkok", + "Indian/Cocos", + "Asia/Rangoon", + "Asia/Omsk", + "Antarctica/Mawson", + "Asia/Colombo", + "Asia/Calcutta", + "Asia/Oral", + "Asia/Kabul", + "Asia/Dubai", + "Asia/Tehran", + "Europe/Moscow", + "Asia/Baghdad", + "Africa/Mogadishu", + "Europe/Athens", + "Africa/Cairo", + "Europe/Rome", + "Europe/Berlin", + "Europe/Amsterdam", + "Africa/Tunis", + "Europe/London", + "Europe/Dublin", + "Atlantic/St_Helena", + "Africa/Monrovia", + "Africa/Accra", + "Atlantic/Azores", + "Atlantic/South_Georgia", + "America/Noronha", + "America/Sao_Paulo", + "America/Cayenne", + "America/St_Johns", + "America/Puerto_Rico", + "America/Aruba", + "America/New_York", + "America/Chicago", + "America/Denver", + "America/Los_Angeles", + "America/Anchorage", + "Pacific/Marquesas", + "America/Adak", + "Pacific/Honolulu", + "Pacific/Midway", + }; + + @MediumTest + public void testGetJulianDay() { + Time time = new Time(Time.TIMEZONE_UTC); + + // for 30 random days in the year 2020 and for a random timezone, get the Julian day for + // 12am and then check that if we change the time we get the same Julian day. + for (int i = 0; i < 30; i++) { + int monthDay = (int) (Math.random() * 365) + 1; + int zoneIndex = (int) (Math.random() * mTimeZones.length); + time.setTimezone(mTimeZones[zoneIndex]); + time.set(0, 0, 0, monthDay, 0, 2020); + + int julianDay = Time.getJulianDay(time.normalize(), time.getGmtOffset()); + + // change the time during the day and check that we get the same Julian day. + for (int hour = 0; hour < 24; hour++) { + for (int minute = 0; minute < 60; minute += 15) { + time.set(0, minute, hour, monthDay, 0, 2020); + int day = Time.getJulianDay(time.normalize(), time.getGmtOffset()); + assertEquals(day, julianDay); + time.clear(Time.TIMEZONE_UTC); + } + } + } + } + + @MediumTest + public void testSetJulianDay() { + Time time = new Time(Time.TIMEZONE_UTC); + + // for each day in the year 2020, pick a random timezone, and verify that we can + // set the Julian day correctly. + for (int monthDay = 1; monthDay <= 366; monthDay++) { + int zoneIndex = (int) (Math.random() * mTimeZones.length); + // leave the "month" as zero because we are changing the "monthDay" from 1 to 366. + // the call to normalize() will then change the "month" (but we don't really care). + time.set(0, 0, 0, monthDay, 0, 2020); + time.setTimezone(mTimeZones[zoneIndex]); + long millis = time.normalize(); + int julianDay = Time.getJulianDay(millis, time.getGmtOffset()); + + time.setJulianDay(julianDay); + + // some places change daylight saving time at 12am and so there is no 12am on some days + // in some timezones - in those cases, the time is set to 1am. + // some examples: Africa/Cairo, America/Sao_Paulo, Atlantic/Azores + assertTrue(time.getHour() == 0 || time.getHour() == 1); + assertEquals(0, time.getMinute()); + assertEquals(0, time.getSecond()); + + millis = time.toMillis(); + int day = Time.getJulianDay(millis, time.getGmtOffset()); + assertEquals(day, julianDay); + time.clear(Time.TIMEZONE_UTC); + } + } +} |