1 /* 2 * Copyright (C) 2020 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 com.android.calendarcommon2; 17 18 import android.test.suitebuilder.annotation.MediumTest; 19 import android.test.suitebuilder.annotation.SmallTest; 20 import android.util.TimeFormatException; 21 22 import junit.framework.TestCase; 23 24 /** 25 * Tests for com.android.calendarcommon2.Time. 26 * 27 * Some of these tests are borrowed from android.text.format.TimeTest. 28 */ 29 public class TimeTest extends TestCase { 30 31 @SmallTest testNullTimezone()32 public void testNullTimezone() { 33 try { 34 Time t = new Time(null); 35 fail("expected a null timezone to throw an exception."); 36 } catch (NullPointerException npe) { 37 // expected. 38 } 39 } 40 41 @SmallTest testTimezone()42 public void testTimezone() { 43 Time t = new Time(Time.TIMEZONE_UTC); 44 assertEquals(Time.TIMEZONE_UTC, t.getTimezone()); 45 } 46 47 @SmallTest testSwitchTimezone()48 public void testSwitchTimezone() { 49 Time t = new Time(Time.TIMEZONE_UTC); 50 String newTimezone = "America/Los_Angeles"; 51 t.switchTimezone(newTimezone); 52 assertEquals(newTimezone, t.getTimezone()); 53 } 54 55 @SmallTest testGetActualMaximum()56 public void testGetActualMaximum() { 57 Time t = new Time(Time.TIMEZONE_UTC); 58 t.set(1, 0, 2020); 59 assertEquals(59, t.getActualMaximum(Time.SECOND)); 60 assertEquals(59, t.getActualMaximum(Time.MINUTE)); 61 assertEquals(23, t.getActualMaximum(Time.HOUR)); 62 assertEquals(31, t.getActualMaximum(Time.MONTH_DAY)); 63 assertEquals(11, t.getActualMaximum(Time.MONTH)); 64 assertEquals(7, t.getActualMaximum(Time.WEEK_DAY)); 65 assertEquals(366, t.getActualMaximum(Time.YEAR_DAY)); // 2020 is a leap year 66 t.set(1, 0, 2019); 67 assertEquals(365, t.getActualMaximum(Time.YEAR_DAY)); 68 } 69 70 @SmallTest testAdd()71 public void testAdd() { 72 Time t = new Time(Time.TIMEZONE_UTC); 73 t.set(0, 0, 0, 1, 0, 2020); 74 t.add(Time.SECOND, 1); 75 assertEquals(1, t.getSecond()); 76 t.add(Time.MINUTE, 1); 77 assertEquals(1, t.getMinute()); 78 t.add(Time.HOUR, 1); 79 assertEquals(1, t.getHour()); 80 t.add(Time.MONTH_DAY, 1); 81 assertEquals(2, t.getDay()); 82 t.add(Time.MONTH, 1); 83 assertEquals(1, t.getMonth()); 84 t.add(Time.YEAR, 1); 85 assertEquals(2021, t.getYear()); 86 } 87 88 @SmallTest testClear()89 public void testClear() { 90 Time t = new Time(Time.TIMEZONE_UTC); 91 t.clear(Time.TIMEZONE_UTC); 92 93 assertEquals(Time.TIMEZONE_UTC, t.getTimezone()); 94 assertFalse(t.isAllDay()); 95 assertEquals(0, t.getSecond()); 96 assertEquals(0, t.getMinute()); 97 assertEquals(0, t.getHour()); 98 assertEquals(1, t.getDay()); // default for Calendar is 1 99 assertEquals(0, t.getMonth()); 100 assertEquals(1970, t.getYear()); 101 assertEquals(4, t.getWeekDay()); // 1970 Jan 1 --> Thursday 102 assertEquals(0, t.getYearDay()); 103 assertEquals(0, t.getGmtOffset()); 104 } 105 106 @SmallTest testCompare()107 public void testCompare() { 108 Time a = new Time(Time.TIMEZONE_UTC); 109 Time b = new Time("America/Los_Angeles"); 110 assertTrue(a.compareTo(b) < 0); 111 112 Time c = new Time("Asia/Calcutta"); 113 assertTrue(a.compareTo(c) > 0); 114 115 Time d = new Time(Time.TIMEZONE_UTC); 116 assertEquals(0, a.compareTo(d)); 117 } 118 119 @SmallTest testFormat2445()120 public void testFormat2445() { 121 Time t = new Time(); 122 assertEquals("19700101T000000", t.format2445()); 123 t.setTimezone(Time.TIMEZONE_UTC); 124 assertEquals("19700101T000000Z", t.format2445()); 125 t.setAllDay(true); 126 assertEquals("19700101", t.format2445()); 127 } 128 129 @SmallTest testFormat3339()130 public void testFormat3339() { 131 Time t = new Time(Time.TIMEZONE_UTC); 132 assertEquals("1970-01-01", t.format3339(true)); 133 t.set(29, 1, 2020); 134 assertEquals("2020-02-29", t.format3339(true)); 135 } 136 137 @SmallTest testToMillis()138 public void testToMillis() { 139 Time t = new Time(Time.TIMEZONE_UTC); 140 t.set(1, 0, 0, 1, 0, 1970); 141 assertEquals(1000L, t.toMillis()); 142 143 t.set(0, 0, 0, 1, 1, 2020); 144 assertEquals(1580515200000L, t.toMillis()); 145 t.set(1, 0, 0, 1, 1, 2020); 146 assertEquals(1580515201000L, t.toMillis()); 147 148 t.set(1, 0, 2020); 149 assertEquals(1577836800000L, t.toMillis()); 150 t.set(1, 1, 2020); 151 assertEquals(1580515200000L, t.toMillis()); 152 } 153 154 @SmallTest testToMillis_overflow()155 public void testToMillis_overflow() { 156 Time t = new Time(Time.TIMEZONE_UTC); 157 t.set(32, 0, 2020); 158 assertEquals(1580515200000L, t.toMillis()); 159 assertEquals(1, t.getDay()); 160 assertEquals(1, t.getMonth()); 161 } 162 163 @SmallTest testParse()164 public void testParse() { 165 Time t = new Time(Time.TIMEZONE_UTC); 166 t.parse("20201010T160000Z"); 167 assertEquals(2020, t.getYear()); 168 assertEquals(9, t.getMonth()); 169 assertEquals(10, t.getDay()); 170 assertEquals(16, t.getHour()); 171 assertEquals(0, t.getMinute()); 172 assertEquals(0, t.getSecond()); 173 174 t.parse("20200220"); 175 assertEquals(2020, t.getYear()); 176 assertEquals(1, t.getMonth()); 177 assertEquals(20, t.getDay()); 178 assertEquals(0, t.getHour()); 179 assertEquals(0, t.getMinute()); 180 assertEquals(0, t.getSecond()); 181 182 try { 183 t.parse("invalid"); 184 fail(); 185 } catch (IllegalArgumentException e) { 186 // expected 187 } 188 189 try { 190 t.parse("20201010Z160000"); 191 fail(); 192 } catch (IllegalArgumentException e) { 193 // expected 194 } 195 } 196 197 @SmallTest testParse3339()198 public void testParse3339() { 199 Time t = new Time(Time.TIMEZONE_UTC); 200 201 t.parse3339("1980-05-23"); 202 if (!t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23) { 203 fail("Did not parse all-day date correctly"); 204 } 205 206 t.parse3339("1980-05-23T09:50:50"); 207 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 208 || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 209 || t.getGmtOffset() != 0) { 210 fail("Did not parse timezone-offset-less date correctly"); 211 } 212 213 t.parse3339("1980-05-23T09:50:50Z"); 214 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 215 || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 216 || t.getGmtOffset() != 0) { 217 fail("Did not parse UTC date correctly"); 218 } 219 220 t.parse3339("1980-05-23T09:50:50.0Z"); 221 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 222 || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 223 || t.getGmtOffset() != 0) { 224 fail("Did not parse UTC date correctly"); 225 } 226 227 t.parse3339("1980-05-23T09:50:50.12Z"); 228 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 229 || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 230 || t.getGmtOffset() != 0) { 231 fail("Did not parse UTC date correctly"); 232 } 233 234 t.parse3339("1980-05-23T09:50:50.123Z"); 235 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 236 || t.getHour() != 9 || t.getMinute() != 50 || t.getSecond() != 50 237 || t.getGmtOffset() != 0) { 238 fail("Did not parse UTC date correctly"); 239 } 240 241 // the time should be normalized to UTC 242 t.parse3339("1980-05-23T09:50:50-01:05"); 243 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 244 || t.getHour() != 10 || t.getMinute() != 55 || t.getSecond() != 50 245 || t.getGmtOffset() != 0) { 246 fail("Did not parse timezone-offset date correctly"); 247 } 248 249 // the time should be normalized to UTC 250 t.parse3339("1980-05-23T09:50:50.123-01:05"); 251 if (t.isAllDay() || t.getYear() != 1980 || t.getMonth() != 4 || t.getDay() != 23 252 || t.getHour() != 10 || t.getMinute() != 55 || t.getSecond() != 50 253 || t.getGmtOffset() != 0) { 254 fail("Did not parse timezone-offset date correctly"); 255 } 256 257 try { 258 t.parse3339("1980"); 259 fail("Did not throw error on truncated input length"); 260 } catch (TimeFormatException e) { 261 // successful 262 } 263 264 try { 265 t.parse3339("1980-05-23T09:50:50.123+"); 266 fail("Did not throw error on truncated timezone offset"); 267 } catch (TimeFormatException e1) { 268 // successful 269 } 270 271 try { 272 t.parse3339("1980-05-23T09:50:50.123+05:0"); 273 fail("Did not throw error on truncated timezone offset"); 274 } catch (TimeFormatException e1) { 275 // successful 276 } 277 } 278 279 @SmallTest testSet_millis()280 public void testSet_millis() { 281 Time t = new Time(Time.TIMEZONE_UTC); 282 283 t.set(1000L); 284 assertEquals(1970, t.getYear()); 285 assertEquals(1, t.getSecond()); 286 287 t.set(2000L); 288 assertEquals(2, t.getSecond()); 289 assertEquals(0, t.getMinute()); 290 291 t.set(1000L * 60); 292 assertEquals(1, t.getMinute()); 293 assertEquals(0, t.getHour()); 294 295 t.set(1000L * 60 * 60); 296 assertEquals(1, t.getHour()); 297 assertEquals(1, t.getDay()); 298 299 t.set((1000L * 60 * 60 * 24) + 1000L); 300 assertEquals(2, t.getDay()); 301 assertEquals(1970, t.getYear()); 302 } 303 304 @SmallTest testSet_dayMonthYear()305 public void testSet_dayMonthYear() { 306 Time t = new Time(Time.TIMEZONE_UTC); 307 t.set(1, 2, 2021); 308 assertEquals(1, t.getDay()); 309 assertEquals(2, t.getMonth()); 310 assertEquals(2021, t.getYear()); 311 } 312 313 @SmallTest testSet_secondMinuteHour()314 public void testSet_secondMinuteHour() { 315 Time t = new Time(Time.TIMEZONE_UTC); 316 t.set(1, 2, 3, 4, 5, 2021); 317 assertEquals(1, t.getSecond()); 318 assertEquals(2, t.getMinute()); 319 assertEquals(3, t.getHour()); 320 assertEquals(4, t.getDay()); 321 assertEquals(5, t.getMonth()); 322 assertEquals(2021, t.getYear()); 323 } 324 325 @SmallTest testSet_overflow()326 public void testSet_overflow() { 327 // Jan 32nd --> Feb 1st 328 Time t = new Time(Time.TIMEZONE_UTC); 329 t.set(32, 0, 2020); 330 assertEquals(1, t.getDay()); 331 assertEquals(1, t.getMonth()); 332 assertEquals(2020, t.getYear()); 333 334 t = new Time(Time.TIMEZONE_UTC); 335 t.set(5, 10, 15, 32, 0, 2020); 336 assertEquals(5, t.getSecond()); 337 assertEquals(10, t.getMinute()); 338 assertEquals(15, t.getHour()); 339 assertEquals(1, t.getDay()); 340 assertEquals(1, t.getMonth()); 341 assertEquals(2020, t.getYear()); 342 } 343 344 @SmallTest testSet_other()345 public void testSet_other() { 346 Time t = new Time(Time.TIMEZONE_UTC); 347 t.set(1, 2, 3, 4, 5, 2021); 348 Time t2 = new Time(); 349 t2.set(t); 350 assertEquals(Time.TIMEZONE_UTC, t2.getTimezone()); 351 assertEquals(1, t2.getSecond()); 352 assertEquals(2, t2.getMinute()); 353 assertEquals(3, t2.getHour()); 354 assertEquals(4, t2.getDay()); 355 assertEquals(5, t2.getMonth()); 356 assertEquals(2021, t2.getYear()); 357 } 358 359 @SmallTest testSetToNow()360 public void testSetToNow() { 361 long now = System.currentTimeMillis(); 362 Time t = new Time(Time.TIMEZONE_UTC); 363 t.set(now); 364 long ms = t.toMillis(); 365 // ensure time is within 1 second because of rounding errors 366 assertTrue("now: " + now + "; actual: " + ms, Math.abs(ms - now) < 1000); 367 } 368 369 @SmallTest testGetWeekNumber()370 public void testGetWeekNumber() { 371 Time t = new Time(Time.TIMEZONE_UTC); 372 t.set(1000L); 373 assertEquals(1, t.getWeekNumber()); 374 t.set(1, 1, 2020); 375 assertEquals(5, t.getWeekNumber()); 376 377 // ensure ISO 8601 standards are met: weeks start on Monday and the first week has at least 378 // 4 days in it (the year's first Thursday or Jan 4th) 379 for (int i = 1; i <= 8; i++) { 380 t.set(i, 0, 2020); 381 // Jan 6th is the first Monday in 2020 so that would be week 2 382 assertEquals(i < 6 ? 1 : 2, t.getWeekNumber()); 383 } 384 } 385 386 private static class DateTest { 387 public int year1; 388 public int month1; 389 public int day1; 390 public int hour1; 391 public int minute1; 392 393 public int offset; 394 395 public int year2; 396 public int month2; 397 public int day2; 398 public int hour2; 399 public int minute2; 400 401 public DateTest(int year1, int month1, int day1, int hour1, int minute1, 402 int offset, int year2, int month2, int day2, int hour2, int minute2) { 403 this.year1 = year1; 404 this.month1 = month1; 405 this.day1 = day1; 406 this.hour1 = hour1; 407 this.minute1 = minute1; 408 this.offset = offset; 409 this.year2 = year2; 410 this.month2 = month2; 411 this.day2 = day2; 412 this.hour2 = hour2; 413 this.minute2 = minute2; 414 } 415 416 public boolean equals(Time time) { 417 return time.getYear() == year2 && time.getMonth() == month2 && time.getDay() == day2 418 && time.getHour() == hour2 && time.getMinute() == minute2; 419 } 420 } 421 422 @SmallTest 423 public void testNormalize() { 424 Time t = new Time(Time.TIMEZONE_UTC); 425 t.parse("20060432T010203"); 426 assertEquals(1146531723000L, t.normalize()); 427 } 428 429 /* These tests assume that DST changes on Nov 4, 2007 at 2am (to 1am). */ 430 431 // The "offset" field in "dayTests" represents days. 432 // Note: the month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 433 private DateTest[] dayTests = { 434 // Nov 4, 12am + 0 day = Nov 4, 12am 435 new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), 436 // Nov 5, 12am + 0 day = Nov 5, 12am 437 new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), 438 // Nov 3, 12am + 1 day = Nov 4, 12am 439 new DateTest(2007, 10, 3, 0, 0, 1, 2007, 10, 4, 0, 0), 440 // Nov 4, 12am + 1 day = Nov 5, 12am 441 new DateTest(2007, 10, 4, 0, 0, 1, 2007, 10, 5, 0, 0), 442 // Nov 5, 12am + 1 day = Nov 6, 12am 443 new DateTest(2007, 10, 5, 0, 0, 1, 2007, 10, 6, 0, 0), 444 // Nov 3, 1am + 1 day = Nov 4, 1am 445 new DateTest(2007, 10, 3, 1, 0, 1, 2007, 10, 4, 1, 0), 446 // Nov 4, 1am + 1 day = Nov 5, 1am 447 new DateTest(2007, 10, 4, 1, 0, 1, 2007, 10, 5, 1, 0), 448 // Nov 5, 1am + 1 day = Nov 6, 1am 449 new DateTest(2007, 10, 5, 1, 0, 1, 2007, 10, 6, 1, 0), 450 // Nov 3, 2am + 1 day = Nov 4, 2am 451 new DateTest(2007, 10, 3, 2, 0, 1, 2007, 10, 4, 2, 0), 452 // Nov 4, 2am + 1 day = Nov 5, 2am 453 new DateTest(2007, 10, 4, 2, 0, 1, 2007, 10, 5, 2, 0), 454 // Nov 5, 2am + 1 day = Nov 6, 2am 455 new DateTest(2007, 10, 5, 2, 0, 1, 2007, 10, 6, 2, 0), 456 }; 457 458 // The "offset" field in "minuteTests" represents minutes. 459 // Note: the month numbers are 0-relative, so Jan=0, Feb=1,...Dec=11 460 private DateTest[] minuteTests = { 461 // Nov 4, 12am + 0 minutes = Nov 4, 12am 462 new DateTest(2007, 10, 4, 0, 0, 0, 2007, 10, 4, 0, 0), 463 // Nov 4, 12am + 60 minutes = Nov 4, 1am 464 new DateTest(2007, 10, 4, 0, 0, 60, 2007, 10, 4, 1, 0), 465 // Nov 5, 12am + 0 minutes = Nov 5, 12am 466 new DateTest(2007, 10, 5, 0, 0, 0, 2007, 10, 5, 0, 0), 467 // Nov 3, 12am + 60 minutes = Nov 3, 1am 468 new DateTest(2007, 10, 3, 0, 0, 60, 2007, 10, 3, 1, 0), 469 // Nov 4, 12am + 60 minutes = Nov 4, 1am 470 new DateTest(2007, 10, 4, 0, 0, 60, 2007, 10, 4, 1, 0), 471 // Nov 5, 12am + 60 minutes = Nov 5, 1am 472 new DateTest(2007, 10, 5, 0, 0, 60, 2007, 10, 5, 1, 0), 473 // Nov 3, 1am + 60 minutes = Nov 3, 2am 474 new DateTest(2007, 10, 3, 1, 0, 60, 2007, 10, 3, 2, 0), 475 // Nov 4, 12:59am (PDT) + 2 minutes = Nov 4, 1:01am (PDT) 476 new DateTest(2007, 10, 4, 0, 59, 2, 2007, 10, 4, 1, 1), 477 // Nov 4, 12:59am (PDT) + 62 minutes = Nov 4, 1:01am (PST) 478 new DateTest(2007, 10, 4, 0, 59, 62, 2007, 10, 4, 1, 1), 479 // Nov 4, 12:30am (PDT) + 120 minutes = Nov 4, 1:30am (PST) 480 new DateTest(2007, 10, 4, 0, 30, 120, 2007, 10, 4, 1, 30), 481 // Nov 4, 12:30am (PDT) + 90 minutes = Nov 4, 1:00am (PST) 482 new DateTest(2007, 10, 4, 0, 30, 90, 2007, 10, 4, 1, 0), 483 // Nov 4, 1am (PDT) + 30 minutes = Nov 4, 1:30am (PDT) 484 new DateTest(2007, 10, 4, 1, 0, 30, 2007, 10, 4, 1, 30), 485 // Nov 4, 1:30am (PDT) + 15 minutes = Nov 4, 1:45am (PDT) 486 new DateTest(2007, 10, 4, 1, 30, 15, 2007, 10, 4, 1, 45), 487 // Mar 11, 1:30am (PST) + 30 minutes = Mar 11, 3am (PDT) 488 new DateTest(2007, 2, 11, 1, 30, 30, 2007, 2, 11, 3, 0), 489 // Nov 4, 1:30am (PST) + 15 minutes = Nov 4, 1:45am (PST) 490 new DateTest(2007, 10, 4, 1, 30, 15, 2007, 10, 4, 1, 45), 491 // Nov 4, 1:30am (PST) + 30 minutes = Nov 4, 2:00am (PST) 492 new DateTest(2007, 10, 4, 1, 30, 30, 2007, 10, 4, 2, 0), 493 // Nov 5, 1am + 60 minutes = Nov 5, 2am 494 new DateTest(2007, 10, 5, 1, 0, 60, 2007, 10, 5, 2, 0), 495 // Nov 3, 2am + 60 minutes = Nov 3, 3am 496 new DateTest(2007, 10, 3, 2, 0, 60, 2007, 10, 3, 3, 0), 497 // Nov 4, 2am + 30 minutes = Nov 4, 2:30am 498 new DateTest(2007, 10, 4, 2, 0, 30, 2007, 10, 4, 2, 30), 499 // Nov 4, 2am + 60 minutes = Nov 4, 3am 500 new DateTest(2007, 10, 4, 2, 0, 60, 2007, 10, 4, 3, 0), 501 // Nov 5, 2am + 60 minutes = Nov 5, 3am 502 new DateTest(2007, 10, 5, 2, 0, 60, 2007, 10, 5, 3, 0), 503 // NOTE: Calendar assumes 1am PDT == 1am PST, the two are not distinct, hence why the transition boundary itself has no tests 504 }; 505 506 @MediumTest 507 public void testNormalize_dst() { 508 Time local = new Time("America/Los_Angeles"); 509 510 int len = dayTests.length; 511 for (int index = 0; index < len; index++) { 512 DateTest test = dayTests[index]; 513 local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); 514 local.add(Time.MONTH_DAY, test.offset); 515 if (!test.equals(local)) { 516 String expectedTime = String.format("%d-%02d-%02d %02d:%02d", 517 test.year2, test.month2, test.day2, test.hour2, test.minute2); 518 String actualTime = String.format("%d-%02d-%02d %02d:%02d", 519 local.getYear(), local.getMonth(), local.getDay(), local.getHour(), 520 local.getMinute()); 521 fail("Expected: " + expectedTime + "; Actual: " + actualTime); 522 } 523 524 local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); 525 local.add(Time.MONTH_DAY, test.offset); 526 if (!test.equals(local)) { 527 String expectedTime = String.format("%d-%02d-%02d %02d:%02d", 528 test.year2, test.month2, test.day2, test.hour2, test.minute2); 529 String actualTime = String.format("%d-%02d-%02d %02d:%02d", 530 local.getYear(), local.getMonth(), local.getDay(), local.getHour(), 531 local.getMinute()); 532 fail("Expected: " + expectedTime + "; Actual: " + actualTime); 533 } 534 } 535 536 len = minuteTests.length; 537 for (int index = 0; index < len; index++) { 538 DateTest test = minuteTests[index]; 539 local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); 540 local.add(Time.MINUTE, test.offset); 541 if (!test.equals(local)) { 542 String expectedTime = String.format("%d-%02d-%02d %02d:%02d", 543 test.year2, test.month2, test.day2, test.hour2, test.minute2); 544 String actualTime = String.format("%d-%02d-%02d %02d:%02d", 545 local.getYear(), local.getMonth(), local.getDay(), local.getHour(), 546 local.getMinute()); 547 fail("Expected: " + expectedTime + "; Actual: " + actualTime); 548 } 549 550 local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1); 551 local.add(Time.MINUTE, test.offset); 552 if (!test.equals(local)) { 553 String expectedTime = String.format("%d-%02d-%02d %02d:%02d", 554 test.year2, test.month2, test.day2, test.hour2, test.minute2); 555 String actualTime = String.format("%d-%02d-%02d %02d:%02d", 556 local.getYear(), local.getMonth(), local.getDay(), local.getHour(), 557 local.getMinute()); 558 fail("Expected: " + expectedTime + "; Actual: " + actualTime); 559 } 560 } 561 } 562 563 @SmallTest 564 public void testNormalize_overflow() { 565 Time t = new Time(Time.TIMEZONE_UTC); 566 t.set(32, 0, 2020); 567 t.normalize(); 568 assertEquals(1, t.getDay()); 569 assertEquals(1, t.getMonth()); 570 } 571 572 @SmallTest 573 public void testDstBehavior_addDays_ignoreDst() { 574 Time time = new Time("America/Los_Angeles"); 575 time.set(4, 10, 2007); // set to Nov 4, 2007, 12am 576 assertEquals(1194159600000L, time.normalize()); 577 time.add(Time.MONTH_DAY, 1); // changes to Nov 5, 2007, 12am 578 assertEquals(1194249600000L, time.toMillis()); 579 580 time = new Time("America/Los_Angeles"); 581 time.set(11, 2, 2007); // set to Mar 11, 2007, 12am 582 assertEquals(1173600000000L, time.normalize()); 583 time.add(Time.MONTH_DAY, 1); // changes to Mar 12, 2007, 12am 584 assertEquals(1173682800000L, time.toMillis()); 585 } 586 587 @SmallTest 588 public void testDstBehavior_addDays_applyDst() { 589 if (!Time.APPLY_DST_CHANGE_LOGIC) { 590 return; 591 } 592 Time time = new Time("America/Los_Angeles"); 593 time.set(4, 10, 2007); // set to Nov 4, 2007, 12am 594 assertEquals(1194159600000L, time.normalizeApplyDst()); 595 time.add(Time.MONTH_DAY, 1); // changes to Nov 4, 2007, 11pm (fall back) 596 assertEquals(1194246000000L, time.toMillisApplyDst()); 597 598 time = new Time("America/Los_Angeles"); 599 time.set(11, 2, 2007); // set to Mar 11, 2007, 12am 600 assertEquals(1173600000000L, time.normalizeApplyDst()); 601 time.add(Time.MONTH_DAY, 1); // changes to Mar 12, 2007, 1am (roll forward) 602 assertEquals(1173686400000L, time.toMillisApplyDst()); 603 } 604 605 @SmallTest 606 public void testDstBehavior_addHours_ignoreDst() { 607 // Note: by default, Calendar applies DST logic if adding hours or minutes but not if adding 608 // days, hence in this test, only if the APPLY_DST_CHANGE_LOGIC flag is false, then the time 609 // is adjusted with DST 610 Time time = new Time("America/Los_Angeles"); 611 time.set(4, 10, 2007); // set to Nov 4, 2007, 12am 612 assertEquals(1194159600000L, time.normalize()); 613 time.add(Time.HOUR, 24); // changes to Nov 5, 2007, 12am 614 assertEquals(Time.APPLY_DST_CHANGE_LOGIC ? 1194249600000L : 1194246000000L, 615 time.toMillis()); 616 617 time = new Time("America/Los_Angeles"); 618 time.set(11, 2, 2007); // set to Mar 11, 2007, 12am 619 assertEquals(1173600000000L, time.normalize()); 620 time.add(Time.HOUR, 24); // changes to Mar 12, 2007, 12am 621 assertEquals(Time.APPLY_DST_CHANGE_LOGIC ? 1173682800000L : 1173686400000L, 622 time.toMillis()); 623 } 624 625 @SmallTest 626 public void testDstBehavior_addHours_applyDst() { 627 if (!Time.APPLY_DST_CHANGE_LOGIC) { 628 return; 629 } 630 Time time = new Time("America/Los_Angeles"); 631 time.set(4, 10, 2007); // set to Nov 4, 2007, 12am 632 assertEquals(1194159600000L, time.normalizeApplyDst()); 633 time.add(Time.HOUR, 24); // changes to Nov 4, 2007, 11pm (fall back) 634 assertEquals(1194246000000L, time.toMillisApplyDst()); 635 636 time = new Time("America/Los_Angeles"); 637 time.set(11, 2, 2007); // set to Mar 11, 2007, 12am 638 assertEquals(1173600000000L, time.normalizeApplyDst()); 639 time.add(Time.HOUR, 24); // changes to Mar 12, 2007, 1am (roll forward) 640 assertEquals(1173686400000L, time.toMillisApplyDst()); 641 } 642 643 // Timezones that cover the world. 644 // Some GMT offsets occur more than once in case some cities decide to change their GMT offset. 645 private static final String[] mTimeZones = { 646 "Pacific/Kiritimati", 647 "Pacific/Enderbury", 648 "Pacific/Fiji", 649 "Antarctica/South_Pole", 650 "Pacific/Norfolk", 651 "Pacific/Ponape", 652 "Asia/Magadan", 653 "Australia/Lord_Howe", 654 "Australia/Sydney", 655 "Australia/Adelaide", 656 "Asia/Tokyo", 657 "Asia/Seoul", 658 "Asia/Taipei", 659 "Asia/Singapore", 660 "Asia/Hong_Kong", 661 "Asia/Saigon", 662 "Asia/Bangkok", 663 "Indian/Cocos", 664 "Asia/Rangoon", 665 "Asia/Omsk", 666 "Antarctica/Mawson", 667 "Asia/Colombo", 668 "Asia/Calcutta", 669 "Asia/Oral", 670 "Asia/Kabul", 671 "Asia/Dubai", 672 "Asia/Tehran", 673 "Europe/Moscow", 674 "Asia/Baghdad", 675 "Africa/Mogadishu", 676 "Europe/Athens", 677 "Africa/Cairo", 678 "Europe/Rome", 679 "Europe/Berlin", 680 "Europe/Amsterdam", 681 "Africa/Tunis", 682 "Europe/London", 683 "Europe/Dublin", 684 "Atlantic/St_Helena", 685 "Africa/Monrovia", 686 "Africa/Accra", 687 "Atlantic/Azores", 688 "Atlantic/South_Georgia", 689 "America/Noronha", 690 "America/Sao_Paulo", 691 "America/Cayenne", 692 "America/St_Johns", 693 "America/Puerto_Rico", 694 "America/Aruba", 695 "America/New_York", 696 "America/Chicago", 697 "America/Denver", 698 "America/Los_Angeles", 699 "America/Anchorage", 700 "Pacific/Marquesas", 701 "America/Adak", 702 "Pacific/Honolulu", 703 "Pacific/Midway", 704 }; 705 706 @MediumTest 707 public void testGetJulianDay() { 708 Time time = new Time(Time.TIMEZONE_UTC); 709 710 // for 30 random days in the year 2020 and for a random timezone, get the Julian day for 711 // 12am and then check that if we change the time we get the same Julian day. 712 for (int i = 0; i < 30; i++) { 713 int monthDay = (int) (Math.random() * 365) + 1; 714 int zoneIndex = (int) (Math.random() * mTimeZones.length); 715 time.setTimezone(mTimeZones[zoneIndex]); 716 time.set(0, 0, 0, monthDay, 0, 2020); 717 718 int julianDay = Time.getJulianDay(time.normalize(), time.getGmtOffset()); 719 720 // change the time during the day and check that we get the same Julian day. 721 for (int hour = 0; hour < 24; hour++) { 722 for (int minute = 0; minute < 60; minute += 15) { 723 time.set(0, minute, hour, monthDay, 0, 2020); 724 int day = Time.getJulianDay(time.normalize(), time.getGmtOffset()); 725 assertEquals(day, julianDay); 726 time.clear(Time.TIMEZONE_UTC); 727 } 728 } 729 } 730 } 731 732 @MediumTest 733 public void testSetJulianDay() { 734 Time time = new Time(Time.TIMEZONE_UTC); 735 736 // for each day in the year 2020, pick a random timezone, and verify that we can 737 // set the Julian day correctly. 738 for (int monthDay = 1; monthDay <= 366; monthDay++) { 739 int zoneIndex = (int) (Math.random() * mTimeZones.length); 740 // leave the "month" as zero because we are changing the "monthDay" from 1 to 366. 741 // the call to normalize() will then change the "month" (but we don't really care). 742 time.set(0, 0, 0, monthDay, 0, 2020); 743 time.setTimezone(mTimeZones[zoneIndex]); 744 long millis = time.normalize(); 745 int julianDay = Time.getJulianDay(millis, time.getGmtOffset()); 746 747 time.setJulianDay(julianDay); 748 749 // some places change daylight saving time at 12am and so there is no 12am on some days 750 // in some timezones - in those cases, the time is set to 1am. 751 // some examples: Africa/Cairo, America/Sao_Paulo, Atlantic/Azores 752 assertTrue(time.getHour() == 0 || time.getHour() == 1); 753 assertEquals(0, time.getMinute()); 754 assertEquals(0, time.getSecond()); 755 756 millis = time.toMillis(); 757 int day = Time.getJulianDay(millis, time.getGmtOffset()); 758 assertEquals(day, julianDay); 759 time.clear(Time.TIMEZONE_UTC); 760 } 761 } 762 } 763