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