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 
17 package android.text.format.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertSame;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.content.Context;
26 import android.text.format.DateUtils;
27 
28 import androidx.test.InstrumentationRegistry;
29 import androidx.test.filters.SmallTest;
30 import androidx.test.runner.AndroidJUnit4;
31 
32 import org.junit.After;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 
37 import java.util.Calendar;
38 import java.util.Date;
39 import java.util.Formatter;
40 import java.util.GregorianCalendar;
41 import java.util.Locale;
42 import java.util.TimeZone;
43 
44 @SmallTest
45 @RunWith(AndroidJUnit4.class)
46 public class DateUtilsTest {
47     private TimeZone mDefaultTimeZone;
48     private long mBaseTime;
49     private Context mContext;
50 
51     @Before
setup()52     public void setup() {
53         mContext = InstrumentationRegistry.getTargetContext();
54         mDefaultTimeZone = TimeZone.getDefault();
55         // All tests in this class can assume the device time zone is set to GMT.
56         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
57         mBaseTime = System.currentTimeMillis();
58     }
59 
60     @After
tearDown()61     public void tearDown() {
62         // Set the default time zone back to what it was before setup().
63         TimeZone.setDefault(mDefaultTimeZone);
64     }
65 
66     @Test
testGetDayOfWeekString()67     public void testGetDayOfWeekString() {
68         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
69             return;
70         }
71 
72         assertEquals("Sunday",
73                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_LONG));
74         assertEquals("Sun",
75                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_MEDIUM));
76         assertEquals("Sun",
77                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORT));
78         assertEquals("Sun",
79                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORTER));
80         assertEquals("S",
81                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORTEST));
82         // Other abbrev
83         assertEquals("Sun",
84                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, 60));
85     }
86 
87     @Test
testGetMonthString()88     public void testGetMonthString() {
89         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
90             return;
91         }
92         assertEquals("January", DateUtils.getMonthString(Calendar.JANUARY, DateUtils.LENGTH_LONG));
93         assertEquals("Jan",
94                 DateUtils.getMonthString(Calendar.JANUARY, DateUtils.LENGTH_MEDIUM));
95         assertEquals("Jan", DateUtils.getMonthString(Calendar.JANUARY, DateUtils.LENGTH_SHORT));
96         assertEquals("Jan",
97                 DateUtils.getMonthString(Calendar.JANUARY, DateUtils.LENGTH_SHORTER));
98         assertEquals("J",
99                 DateUtils.getMonthString(Calendar.JANUARY, DateUtils.LENGTH_SHORTEST));
100         // Other abbrev
101         assertEquals("Jan", DateUtils.getMonthString(Calendar.JANUARY, 60));
102     }
103 
104     @Test
testGetAMPMString()105     public void testGetAMPMString() {
106         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
107             return;
108         }
109         assertEquals("AM", DateUtils.getAMPMString(Calendar.AM));
110         assertEquals("PM", DateUtils.getAMPMString(Calendar.PM));
111     }
112 
113     // This is to test the mapping between DateUtils' public API and
114     // libcore/icu4c's implementation. More tests, in different locales, are
115     // in libcore's CTS tests.
116     @Test
test_getRelativeTimeSpanString()117     public void test_getRelativeTimeSpanString() {
118         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
119             return;
120         }
121 
122         final long ONE_SECOND_IN_MS = 1000;
123         assertEquals("0 minutes ago",
124                 DateUtils.getRelativeTimeSpanString(mBaseTime - ONE_SECOND_IN_MS));
125         assertEquals("In 0 minutes",
126                 DateUtils.getRelativeTimeSpanString(mBaseTime + ONE_SECOND_IN_MS));
127 
128         final long ONE_MINUTE_IN_MS = 60 * ONE_SECOND_IN_MS;
129         assertEquals("1 minute ago", DateUtils.getRelativeTimeSpanString(0, ONE_MINUTE_IN_MS,
130                 DateUtils.MINUTE_IN_MILLIS));
131         assertEquals("In 1 minute", DateUtils.getRelativeTimeSpanString(ONE_MINUTE_IN_MS, 0,
132                 DateUtils.MINUTE_IN_MILLIS));
133 
134         final long ONE_HOUR_IN_MS = 60 * 60 * 1000;
135         final long TWO_HOURS_IN_MS = 2 * ONE_HOUR_IN_MS;
136         assertEquals("2 hours ago", DateUtils.getRelativeTimeSpanString(mBaseTime - TWO_HOURS_IN_MS,
137                 mBaseTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_NUMERIC_DATE));
138         assertEquals("In 2 hours", DateUtils.getRelativeTimeSpanString(mBaseTime + TWO_HOURS_IN_MS,
139                 mBaseTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_NUMERIC_DATE));
140     }
141 
142     @Test
test_getRelativeTimeSpanString_withContext()143     public void test_getRelativeTimeSpanString_withContext() {
144         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
145             return;
146         }
147 
148         final GregorianCalendar cal = new GregorianCalendar();
149         cal.setTimeInMillis(mBaseTime);
150         cal.set(Calendar.HOUR_OF_DAY, 10);
151         cal.set(Calendar.MINUTE, 0);
152         final long today10am = cal.getTimeInMillis();
153 
154         final CharSequence withPrep = DateUtils.getRelativeTimeSpanString(mContext, today10am,
155                 true /* with preposition */);
156         final CharSequence noPrep = DateUtils.getRelativeTimeSpanString(mContext, today10am,
157                 false /* no preposition */);
158         assertEquals(noPrep, DateUtils.getRelativeTimeSpanString(mContext, today10am));
159 
160         if (android.text.format.DateFormat.is24HourFormat(mContext)) {
161             assertEquals("at 10:00", withPrep);
162             assertEquals("10:00", noPrep);
163         } else {
164             assertEquals("at 10:00 AM", withPrep);
165             assertEquals("10:00 AM", noPrep);
166         }
167     }
168 
169     // Similar to test_getRelativeTimeSpanString(). The function here is to
170     // test the mapping between DateUtils's public API and libcore/icu4c's
171     // implementation. More tests, in different locales, are in libcore's
172     // CTS tests.
173     @Test
test_getRelativeDateTimeString()174     public void test_getRelativeDateTimeString() {
175         final long DAY_DURATION = 5 * 24 * 60 * 60 * 1000;
176         assertNotNull(DateUtils.getRelativeDateTimeString(mContext, mBaseTime - DAY_DURATION,
177                 DateUtils.MINUTE_IN_MILLIS, DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_NUMERIC_DATE));
178     }
179 
180     @Test
test_formatElapsedTime()181     public void test_formatElapsedTime() {
182         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
183             return;
184         }
185 
186         long MINUTES = 60;
187         long HOURS = 60 * MINUTES;
188         verifyFormatElapsedTime("02:01", 2 * MINUTES + 1);
189         verifyFormatElapsedTime("3:02:01", 3 * HOURS + 2 * MINUTES + 1);
190         // http://code.google.com/p/android/issues/detail?id=41401
191         verifyFormatElapsedTime("123:02:01", 123 * HOURS + 2 * MINUTES + 1);
192     }
193 
verifyFormatElapsedTime(String expected, long elapsedTime)194     private void verifyFormatElapsedTime(String expected, long elapsedTime) {
195         assertEquals(expected, DateUtils.formatElapsedTime(elapsedTime));
196         StringBuilder sb = new StringBuilder();
197         assertEquals(expected, DateUtils.formatElapsedTime(sb, elapsedTime));
198         assertEquals(expected, sb.toString());
199     }
200 
201     // This is just to exercise the wrapper that calls the libcore/icu4c implementation.
202     // Full testing, in multiple locales, is in libcore's CTS tests.
203     @Test
testFormatDateRange()204     public void testFormatDateRange() {
205         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
206             return;
207         }
208 
209         final Date date = new Date(109, 0, 19, 3, 30, 15);
210         final long fixedTime = date.getTime();
211         final long hourDuration = 2 * 60 * 60 * 1000;
212         assertEquals("Monday", DateUtils.formatDateRange(mContext, fixedTime,
213                 fixedTime + hourDuration, DateUtils.FORMAT_SHOW_WEEKDAY));
214     }
215 
216     @Test
testFormatDateRange_withFormatter()217     public void testFormatDateRange_withFormatter() {
218         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
219             return;
220         }
221 
222         final Date date = new Date(109, 0, 19, 3, 30, 15);
223         final long fixedTime = date.getTime();
224         final long hourDuration = 2 * 60 * 60 * 1000;
225         final Formatter formatter = new Formatter();
226         final Formatter result = DateUtils.formatDateRange(mContext, formatter, fixedTime,
227                 fixedTime + hourDuration, DateUtils.FORMAT_SHOW_WEEKDAY);
228         assertEquals("Monday", result.toString());
229         assertSame(result, formatter);
230     }
231 
232     @Test
testFormatDateRange_withFormatterAndTimezone()233     public void testFormatDateRange_withFormatterAndTimezone() {
234         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
235             return;
236         }
237 
238         final Date date = new Date(109, 0, 19, 3, 30, 15);
239         final long fixedTime = date.getTime();
240         final long hourDuration = 2 * 60 * 60 * 1000;
241         final Formatter formatter = new Formatter();
242         final Formatter result = DateUtils.formatDateRange(mContext, formatter, fixedTime,
243                 fixedTime + hourDuration, DateUtils.FORMAT_SHOW_WEEKDAY, null /* local */);
244         assertEquals("Monday", result.toString());
245         assertSame(result, formatter);
246     }
247 
248     @Test
testFormatDateTime()249     public void testFormatDateTime() {
250         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
251             return;
252         }
253 
254         final Date date = new Date(109, 0, 19, 3, 30, 15);
255         final long fixedTime = date.getTime();
256         assertEquals("Monday", DateUtils.formatDateTime(mContext, fixedTime,
257                 DateUtils.FORMAT_SHOW_WEEKDAY));
258     }
259 
260     @Test
testIsToday()261     public void testIsToday() {
262         // This test assumes TimeZone.getDefault() returns GMT. See setup() and comments below for
263         // details.
264 
265         final int ONE_HOUR_IN_MS = 60 * 60 * 1000;
266         final int ONE_DAY_IN_MS = 24 * ONE_HOUR_IN_MS;
267 
268         // mBaseTime < System.currentTimeMillis(), so subtracting 24 hours is guaranteed to
269         // be yesterday because this test uses GMT, i.e. no DST to consider.
270         assertFalse(DateUtils.isToday(mBaseTime - ONE_DAY_IN_MS));
271 
272         // We can assume mBaseTime is within a few seconds of the current system clock so adding
273         // one day plus one hour is more than sufficient to ensure isToday() == false.
274         assertFalse(DateUtils.isToday(mBaseTime + ONE_DAY_IN_MS + ONE_HOUR_IN_MS));
275 
276         // This assertion is flaky because the method under test uses the system clock. If mBaseTime
277         // is set just before midnight (GMT) and isToday() is run just after midnight (GMT), this
278         // assertion will fail.
279         assertTrue("mBaseTime=" + mBaseTime + ", System.currentTimeMillis() after failure="
280                 + System.currentTimeMillis(), DateUtils.isToday(mBaseTime));
281     }
282 
283     @Test
test_bug_7548161()284     public void test_bug_7548161() {
285         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
286             return;
287         }
288 
289         long now = System.currentTimeMillis();
290         long today = now;
291         long tomorrow = now + DateUtils.DAY_IN_MILLIS;
292         long yesterday = now - DateUtils.DAY_IN_MILLIS;
293         assertEquals("Tomorrow", DateUtils.getRelativeTimeSpanString(tomorrow, now,
294                 DateUtils.DAY_IN_MILLIS, 0));
295         assertEquals("Yesterday", DateUtils.getRelativeTimeSpanString(yesterday, now,
296                 DateUtils.DAY_IN_MILLIS, 0));
297         assertEquals("Today", DateUtils.getRelativeTimeSpanString(today, now,
298                 DateUtils.DAY_IN_MILLIS, 0));
299     }
300 }
301