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