1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.util.cts;
17 
18 import static android.util.TimeUtils.isTimeBetween;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static junit.framework.TestCase.assertFalse;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28 
29 import android.platform.test.annotations.IgnoreUnderRavenwood;
30 import android.platform.test.ravenwood.RavenwoodRule;
31 import android.util.TimeUtils;
32 
33 import androidx.test.filters.SmallTest;
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.time.LocalTime;
41 import java.util.Calendar;
42 import java.util.Collection;
43 import java.util.List;
44 import java.util.TimeZone;
45 
46 @SmallTest
47 @RunWith(AndroidJUnit4.class)
48 @IgnoreUnderRavenwood(blockedBy = TimeUtils.class)
49 public class TimeUtilsTest {
50     @Rule
51     public final RavenwoodRule mRavenwood = new RavenwoodRule();
52 
53     @Test
testUnitedStates()54     public void testUnitedStates() throws Exception {
55         String[] mainstream = new String[] {
56             "America/New_York", // Eastern
57             "America/Chicago", // Central
58             "America/Denver", // Mountain
59             "America/Los_Angeles", // Pacific
60             "America/Anchorage", // Alaska
61             "Pacific/Honolulu", // Hawaii, no DST
62         };
63 
64         for (String name : mainstream) {
65             TimeZone tz = TimeZone.getTimeZone(name);
66             Calendar c = Calendar.getInstance(tz);
67             TimeZone guess;
68 
69             c.set(2016, Calendar.OCTOBER, 20, 12, 0, 0);
70             guess = guessTimeZone(c, "us");
71             assertEquals(name, guess.getID());
72 
73             c.set(2017, Calendar.JANUARY, 20, 12, 0, 0);
74             guess = guessTimeZone(c, "us");
75             assertEquals(name, guess.getID());
76         }
77     }
78 
79     @Test
testWeirdUnitedStates()80     public void testWeirdUnitedStates() throws Exception {
81         String[] weird = new String[] {
82             "America/Phoenix", // Mountain, no DST
83             "America/Adak", // Same as Hawaii, but with DST
84         };
85 
86         for (String name : weird) {
87             TimeZone tz = TimeZone.getTimeZone(name);
88             Calendar c = Calendar.getInstance(tz);
89             TimeZone guess;
90 
91             c.set(2016, Calendar.OCTOBER, 20, 12, 0, 0);
92             guess = guessTimeZone(c, "us");
93             assertEquals(name, guess.getID());
94         }
95     }
96 
97     @Test
testOld()98     public void testOld() throws Exception {
99         String[] old = new String[] {
100             "America/Indiana/Indianapolis", // Eastern, formerly no DST
101         };
102 
103         for (String name : old) {
104             TimeZone tz = TimeZone.getTimeZone(name);
105             Calendar c = Calendar.getInstance(tz);
106             TimeZone guess;
107 
108             c.set(2005, Calendar.OCTOBER, 20, 12, 0, 0);
109             guess = guessTimeZone(c, "us");
110             assertEquals(name, guess.getID());
111         }
112     }
113 
114     @Test
testWorldWeird()115     public void testWorldWeird() throws Exception {
116         String[] world = new String[] {
117             // Distinguisable from Sydney only when DST not in effect
118             "au", "Australia/Lord_Howe",
119         };
120 
121         for (int i = 0; i < world.length; i += 2) {
122             String country = world[i];
123             String name = world[i + 1];
124 
125             TimeZone tz = TimeZone.getTimeZone(name);
126             Calendar c = Calendar.getInstance(tz);
127             TimeZone guess;
128 
129             c.set(2016, Calendar.JULY, 20, 12, 0, 0);
130             guess = guessTimeZone(c, country);
131             assertEquals(name, guess.getID());
132         }
133     }
134 
guessTimeZone(Calendar c, String country)135     private static TimeZone guessTimeZone(Calendar c, String country) {
136         return TimeUtils.getTimeZone(c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET),
137                                      c.get(Calendar.DST_OFFSET) != 0,
138                                      c.getTimeInMillis(),
139                                      country);
140     }
141 
142     @Test
testFormatDuration()143     public void testFormatDuration() {
144         assertFormatDuration("0", 0);
145         assertFormatDuration("-1ms", -1);
146         assertFormatDuration("+1ms", 1);
147         assertFormatDuration("+10ms", 10);
148         assertFormatDuration("+100ms", 100);
149         assertFormatDuration("+101ms", 101);
150         assertFormatDuration("+330ms", 330);
151         assertFormatDuration("+1s0ms", 1000);
152         assertFormatDuration("+1s330ms", 1330);
153         assertFormatDuration("+10s24ms", 10024);
154         assertFormatDuration("+1m0s30ms", 60030);
155         assertFormatDuration("+1h0m0s30ms", 3600030);
156         assertFormatDuration("+1d0h0m0s30ms", 86400030);
157     }
158 
159     @Test
testFormatHugeDuration()160     public void testFormatHugeDuration() {
161         assertFormatDuration("+15542d1h11m11s555ms", 1342833071555L);
162         assertFormatDuration("-15542d1h11m11s555ms", -1342833071555L);
163     }
164 
assertFormatDuration(String expected, long duration)165     private static void assertFormatDuration(String expected, long duration) {
166         StringBuilder sb = new StringBuilder();
167         TimeUtils.formatDuration(duration, sb);
168         assertEquals("formatDuration(" + duration + ")", expected, sb.toString());
169     }
170 
171     @Test
testGetTimeZoneIdsForCountryCode()172     public void testGetTimeZoneIdsForCountryCode() {
173         List<String> usTimeZones = TimeUtils.getTimeZoneIdsForCountryCode("us");
174 
175         // Sample the content without being too exact.
176         assertCollectionContains(usTimeZones, "America/Los_Angeles");
177         assertCollectionContains(usTimeZones, "America/New_York");
178 
179         // Assert we don't care about casing of the country code.
180         assertEquals(usTimeZones, TimeUtils.getTimeZoneIdsForCountryCode("US"));
181         assertEquals(usTimeZones, TimeUtils.getTimeZoneIdsForCountryCode("uS"));
182         assertEquals(usTimeZones, TimeUtils.getTimeZoneIdsForCountryCode("Us"));
183     }
184 
185     @Test
getTimeZoneIdsForCountryCode_doesNotShowNoLongerActiveNames()186     public void getTimeZoneIdsForCountryCode_doesNotShowNoLongerActiveNames() {
187         List<String> usTimeZones = TimeUtils.getTimeZoneIdsForCountryCode("us");
188 
189         assertThat(usTimeZones).contains("America/New_York");
190         // America/Detroit was available only till 27 April 1975
191         assertThat(usTimeZones).doesNotContain("America/Detroit");
192     }
193 
194     @Test
testGetTimeZoneIdsForCountryCode_unknownCountryCode()195     public void testGetTimeZoneIdsForCountryCode_unknownCountryCode() {
196         String unknownCountryCode = "zx81";
197         assertNull(TimeUtils.getTimeZoneIdsForCountryCode(unknownCountryCode));
198     }
199 
200     @Test
testGetTimeZoneIdsForCountryCode_nullCountryCode()201     public void testGetTimeZoneIdsForCountryCode_nullCountryCode() {
202         try {
203             TimeUtils.getTimeZoneIdsForCountryCode(null);
204             fail();
205         } catch (NullPointerException expected) {
206         }
207     }
208 
209     @Test
testTimeClockBetweenTwoOff_refStartEnd()210     public void testTimeClockBetweenTwoOff_refStartEnd() {
211         LocalTime now = LocalTime.of(10, 0);
212         assertFalse(isTimeBetween(now, now.plusHours(1), now.plusHours(2)));
213     }
214 
215     @Test
testTimeClockBetweenTwoOn_startRefEnd()216     public void testTimeClockBetweenTwoOn_startRefEnd() {
217         LocalTime now = LocalTime.of(10, 0);
218         assertTrue(isTimeBetween(now, now.minusHours(1), now.plusHours(1)));
219     }
220 
221     @Test
testTimeClockBetweenTwoOn_startRefEndOvernight()222     public void testTimeClockBetweenTwoOn_startRefEndOvernight() {
223         LocalTime now = LocalTime.of(0, 0);
224         assertTrue(isTimeBetween(now, now.minusHours(1), now.plusHours(1)));
225     }
226 
227     @Test
testTimeClockBetweenTwoOff_endRefStart()228     public void testTimeClockBetweenTwoOff_endRefStart() {
229         LocalTime now = LocalTime.of(23, 0);
230         assertFalse(isTimeBetween(now, now.plusHours(2), now.minusHours(2)));
231     }
232 
233     @Test
testTimeClockBetweenTwoOff_startEndRef()234     public void testTimeClockBetweenTwoOff_startEndRef() {
235         LocalTime now = LocalTime.of(10, 0);
236         assertFalse(isTimeBetween(now, now.minusHours(2), now.minusHours(1)));
237     }
238 
239 
assertCollectionContains(Collection<? super T> collection, T value)240     private static <T> void assertCollectionContains(Collection<? super T> collection, T value) {
241         assertTrue(collection + " should contain " + value, collection.contains(value));
242     }
243 }
244