1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * Copyright (c) 1997-2016, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 ********************************************************************/
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
12 #include "unicode/simpletz.h"
13 #include "unicode/smpdtfmt.h"
14 #include "unicode/strenum.h"
15 #include "unicode/gregocal.h"
20 // *****************************************************************************
21 // class TimeZoneRegressionTest
22 // *****************************************************************************
23 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
26 TimeZoneRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
28 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
41 CASE(10, Test4154542
);
42 CASE(11, Test4154650
);
43 CASE(12, Test4154525
);
44 CASE(13, Test4162593
);
47 CASE(16, TestJDK12API
);
48 CASE(17, Test4176686
);
49 CASE(18, Test4184229
);
50 CASE(19, TestNegativeDaylightSaving
);
51 default: name
= ""; break;
56 TimeZoneRegressionTest::failure(UErrorCode status
, const char* msg
)
58 if(U_FAILURE(status
)) {
59 errln(UnicodeString("FAIL: ") + msg
+ " failed, error " + u_errorName(status
));
69 void TimeZoneRegressionTest:: Test4052967() {
70 // {sfb} not applicable in C++ ?
71 /*logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
72 logln("user.timezone:" + System.getProperty("user.timezone", "<not set>"));
73 logln(new Date().toString());
74 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");*/
80 void TimeZoneRegressionTest:: Test4073209() {
81 TimeZone
*z1
= TimeZone::createTimeZone("PST");
82 TimeZone
*z2
= TimeZone::createTimeZone("PST");
84 errln("Fail: TimeZone should return clones");
89 UDate
TimeZoneRegressionTest::findTransitionBinary(const SimpleTimeZone
& tz
, UDate min
, UDate max
) {
90 UErrorCode status
= U_ZERO_ERROR
;
91 UBool startsInDST
= tz
.inDaylightTime(min
, status
);
92 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
93 if (tz
.inDaylightTime(max
, status
) == startsInDST
) {
94 logln((UnicodeString
)"Error: inDaylightTime() != " + ((!startsInDST
)?"TRUE":"FALSE"));
97 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
98 while ((max
- min
) > 100) { // Min accuracy in ms
99 UDate mid
= (min
+ max
) / 2;
100 if (tz
.inDaylightTime(mid
, status
) == startsInDST
) {
105 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
107 return (min
+ max
) / 2;
110 UDate
TimeZoneRegressionTest::findTransitionStepwise(const SimpleTimeZone
& tz
, UDate min
, UDate max
) {
111 UErrorCode status
= U_ZERO_ERROR
;
112 UBool startsInDST
= tz
.inDaylightTime(min
, status
);
113 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
115 if (tz
.inDaylightTime(min
, status
) != startsInDST
) {
118 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
119 min
+= (UDate
)24*60*60*1000; // one day
127 // {sfb} will this work using a Calendar?
128 void TimeZoneRegressionTest:: Test4073215()
130 UErrorCode status
= U_ZERO_ERROR
;
131 UnicodeString str
, str2
;
132 SimpleTimeZone
*z
= new SimpleTimeZone(0, "GMT");
133 if (z
->useDaylightTime())
134 errln("Fail: Fix test to start with non-DST zone");
135 z
->setStartRule(UCAL_FEBRUARY
, 1, UCAL_SUNDAY
, 0, status
);
136 failure(status
, "z->setStartRule()");
137 z
->setEndRule(UCAL_MARCH
, -1, UCAL_SUNDAY
, 0, status
);
138 failure(status
, "z->setStartRule()");
139 if (!z
->useDaylightTime())
140 errln("Fail: DST not active");
142 GregorianCalendar
cal(1997, UCAL_JANUARY
, 31, status
);
143 if(U_FAILURE(status
)) {
144 dataerrln("Error creating calendar %s", u_errorName(status
));
147 failure(status
, "new GregorianCalendar");
148 cal
.adoptTimeZone(z
);
150 SimpleDateFormat
sdf((UnicodeString
)"E d MMM yyyy G HH:mm", status
);
151 if(U_FAILURE(status
)) {
152 dataerrln("Error creating date format %s", u_errorName(status
));
155 sdf
.setCalendar(cal
);
156 failure(status
, "new SimpleDateFormat");
158 UDate jan31
, mar1
, mar31
;
160 UBool indt
= z
->inDaylightTime(jan31
=cal
.getTime(status
), status
);
161 failure(status
, "inDaylightTime or getTime call on Jan 31");
163 errln("Fail: Jan 31 inDaylightTime=TRUE, exp FALSE");
165 cal
.set(1997, UCAL_MARCH
, 1);
166 indt
= z
->inDaylightTime(mar1
=cal
.getTime(status
), status
);
167 failure(status
, "inDaylightTime or getTime call on Mar 1");
170 sdf
.format(cal
.getTime(status
), str
);
171 failure(status
, "getTime");
172 errln((UnicodeString
)"Fail: " + str
+ " inDaylightTime=FALSE, exp TRUE");
174 cal
.set(1997, UCAL_MARCH
, 31);
175 indt
= z
->inDaylightTime(mar31
=cal
.getTime(status
), status
);
176 failure(status
, "inDaylightTime or getTime call on Mar 31");
178 errln("Fail: Mar 31 inDaylightTime=TRUE, exp FALSE");
182 cal.set(1997, Calendar::DECEMBER, 31);
183 UDate dec31 = cal.getTime(status);
184 failure(status, "getTime");
185 UDate trans = findTransitionStepwise(*z, jan31, dec31);
186 logln((UnicodeString)"Stepwise from " +
187 sdf.format(jan31, str.remove()) + "; transition at " +
188 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
189 trans = findTransitionStepwise(*z, mar1, dec31);
190 logln((UnicodeString)"Stepwise from " +
191 sdf.format(mar1, str.remove()) + "; transition at " +
192 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
193 trans = findTransitionStepwise(*z, mar31, dec31);
194 logln((UnicodeString)"Stepwise from " +
195 sdf.format(mar31, str.remove()) + "; transition at " +
196 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
202 * The expected behavior of TimeZone around the boundaries is:
203 * (Assume transition time of 2:00 AM)
204 * day of onset 1:59 AM STD = display name 1:59 AM ST
205 * 2:00 AM STD = display name 3:00 AM DT
206 * day of end 0:59 AM STD = display name 1:59 AM DT
207 * 1:00 AM STD = display name 1:00 AM ST
209 void TimeZoneRegressionTest:: Test4084933() {
210 UErrorCode status
= U_ZERO_ERROR
;
211 TimeZone
*tz
= TimeZone::createTimeZone("PST");
213 int32_t offset1
= tz
->getOffset(1,
214 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
215 int32_t offset2
= tz
->getOffset(1,
216 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000)-1, status
);
218 int32_t offset3
= tz
->getOffset(1,
219 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (1*60*60*1000), status
);
220 int32_t offset4
= tz
->getOffset(1,
221 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (1*60*60*1000)-1, status
);
224 * The following was added just for consistency. It shows that going *to* Daylight
225 * Savings Time (PDT) does work at 2am.
227 int32_t offset5
= tz
->getOffset(1,
228 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (2*60*60*1000), status
);
229 int32_t offset6
= tz
->getOffset(1,
230 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (2*60*60*1000)-1, status
);
231 int32_t offset5a
= tz
->getOffset(1,
232 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (3*60*60*1000), status
);
233 int32_t offset6a
= tz
->getOffset(1,
234 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (3*60*60*1000)-1, status
);
235 int32_t offset7
= tz
->getOffset(1,
236 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (1*60*60*1000), status
);
237 int32_t offset8
= tz
->getOffset(1,
238 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (1*60*60*1000)-1, status
);
239 int32_t SToffset
= (int32_t)(-8 * 60*60*1000L);
240 int32_t DToffset
= (int32_t)(-7 * 60*60*1000L);
242 #define ERR_IF_FAIL(x) if(x) { dataerrln("FAIL: TimeZone misbehaving - %s", #x); }
244 ERR_IF_FAIL(U_FAILURE(status
))
245 ERR_IF_FAIL(offset1
!= SToffset
)
246 ERR_IF_FAIL(offset2
!= SToffset
)
247 ERR_IF_FAIL(offset3
!= SToffset
)
248 ERR_IF_FAIL(offset4
!= DToffset
)
249 ERR_IF_FAIL(offset5
!= DToffset
)
250 ERR_IF_FAIL(offset6
!= SToffset
)
251 ERR_IF_FAIL(offset5a
!= DToffset
)
252 ERR_IF_FAIL(offset6a
!= DToffset
)
253 ERR_IF_FAIL(offset7
!= SToffset
)
254 ERR_IF_FAIL(offset8
!= SToffset
)
264 void TimeZoneRegressionTest:: Test4096952() {
265 // {sfb} serialization not applicable
267 UnicodeString ZONES [] = { UnicodeString("GMT"), UnicodeString("MET"), UnicodeString("IST") };
270 for (int32_t i=0; i < ZONES.length; ++i) {
271 TimeZone *zone = TimeZone::createTimeZone(ZONES[i]);
273 if (zone->getID(id) != ZONES[i])
274 errln("Fail: Test broken; zones not instantiating");
276 ByteArrayOutputStream baos;
277 ObjectOutputStream ostream =
278 new ObjectOutputStream(baos = new
279 ByteArrayOutputStream());
280 ostream.writeObject(zone);
283 ObjectInputStream istream =
284 new ObjectInputStream(new
285 ByteArrayInputStream(baos.toByteArray()));
286 TimeZone frankenZone = (TimeZone) istream.readObject();
287 //logln("Zone: " + zone);
288 //logln("FrankenZone: " + frankenZone);
289 if (!zone.equals(frankenZone)) {
290 logln("TimeZone " + zone.getID() +
291 " not equal to serialized/deserialized one");
295 if (!pass) errln("Fail: TimeZone serialization/equality bug");
297 catch (IOException e) {
299 e.print32_tStackTrace();
301 catch (ClassNotFoundException e) {
303 e.print32_tStackTrace();
311 void TimeZoneRegressionTest:: Test4109314() {
312 UErrorCode status
= U_ZERO_ERROR
;
313 GregorianCalendar
*testCal
= (GregorianCalendar
*)Calendar::createInstance(status
);
314 if(U_FAILURE(status
)) {
315 dataerrln("Error creating calendar %s", u_errorName(status
));
319 failure(status
, "Calendar::createInstance");
320 TimeZone
*PST
= TimeZone::createTimeZone("PST");
321 /*Object[] testData = {
322 PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
323 PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
325 UDate testData
[] = {
326 CalendarRegressionTest::makeDate(98,UCAL_APRIL
,4,22,0),
327 CalendarRegressionTest::makeDate(98, UCAL_APRIL
,5,6,0),
328 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER
,24,22,0),
329 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER
,25,6,0)
332 for (int32_t i
= 0; i
< 4; i
+=2) {
333 //testCal->setTimeZone((TimeZone) testData[i]);
334 testCal
->setTimeZone(*PST
);
335 UDate t
= testData
[i
];
336 UDate end
= testData
[i
+1];
337 while(testCal
->getTime(status
) < end
) {
338 testCal
->setTime(t
, status
);
339 if ( ! checkCalendar314(testCal
, PST
))
345 errln("Fail: TZ API inconsistent");
352 TimeZoneRegressionTest::checkCalendar314(GregorianCalendar
*testCal
, TimeZone
*testTZ
)
354 UErrorCode status
= U_ZERO_ERROR
;
355 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
357 int32_t tzOffset
, tzRawOffset
;
358 float tzOffsetFloat
,tzRawOffsetFloat
;
359 // Here is where the user made an error. They were passing in the value of
360 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
362 UDate millis
= testCal
->get(UCAL_MILLISECOND
, status
) +
363 1000.0 * (testCal
->get(UCAL_SECOND
, status
) +
364 60.0 * (testCal
->get(UCAL_MINUTE
, status
) +
365 60.0 * (testCal
->get(UCAL_HOUR_OF_DAY
, status
)))) -
366 testCal
->get(UCAL_DST_OFFSET
, status
);
368 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE
369 * BEGINNING OR END OF A MONTH. We must add this code because
370 * getOffset() has been changed to be more strict about the parameters
371 * it receives -- it turns out that this test was passing in illegal
373 int32_t date
= testCal
->get(UCAL_DATE
, status
);
374 int32_t dow
= testCal
->get(UCAL_DAY_OF_WEEK
, status
);
376 millis
+= U_MILLIS_PER_DAY
;
378 dow
= UCAL_SUNDAY
+ ((dow
- UCAL_SUNDAY
+ 6) % 7);
380 while (millis
>= U_MILLIS_PER_DAY
) {
381 millis
-= U_MILLIS_PER_DAY
;
383 dow
= UCAL_SUNDAY
+ ((dow
- UCAL_SUNDAY
+ 1) % 7);
386 tzOffset
= testTZ
->getOffset((uint8_t)testCal
->get(UCAL_ERA
, status
),
387 testCal
->get(UCAL_YEAR
, status
),
388 testCal
->get(UCAL_MONTH
, status
),
393 tzRawOffset
= testTZ
->getRawOffset();
394 tzOffsetFloat
= (float)tzOffset
/(float)3600000;
395 tzRawOffsetFloat
= (float)tzRawOffset
/(float)3600000;
397 UDate testDate
= testCal
->getTime(status
);
399 UBool inDaylightTime
= testTZ
->inDaylightTime(testDate
, status
);
400 SimpleDateFormat
*sdf
= new SimpleDateFormat((UnicodeString
)"MM/dd/yyyy HH:mm", status
);
401 sdf
->setCalendar(*testCal
);
402 UnicodeString inDaylightTimeString
;
408 inDaylightTimeString
= " DST ";
409 passed
= (tzOffset
== (tzRawOffset
+ 3600000));
413 inDaylightTimeString
= " ";
414 passed
= (tzOffset
== tzRawOffset
);
417 UnicodeString output
;
418 FieldPosition
pos(FieldPosition::DONT_CARE
);
419 output
= testTZ
->getID(output
) + " " + sdf
->format(testDate
, output
, pos
) +
420 " Offset(" + tzOffsetFloat
+ ")" +
421 " RawOffset(" + tzRawOffsetFloat
+ ")" +
422 " " + millis
/(float)3600000 + " " +
423 inDaylightTimeString
;
443 * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never
444 * should have been made public. It's simply too hard to use correctly.
446 * The original test code failed to do the following:
447 * (1) Call Calendar::setTime() before getting the fields!
448 * (2) Use the right millis (as usual) for getOffset(); they were passing
449 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
450 * When you fix these two problems, the test passes, as expected.
452 void TimeZoneRegressionTest:: Test4126678()
454 UErrorCode status
= U_ZERO_ERROR
;
455 Calendar
*cal
= Calendar::createInstance(status
);
456 if(U_FAILURE(status
)) {
457 dataerrln("Error creating calendar %s", u_errorName(status
));
461 failure(status
, "Calendar::createInstance");
462 TimeZone
*tz
= TimeZone::createTimeZone("PST");
463 cal
->adoptTimeZone(tz
);
465 cal
->set(1998, UCAL_APRIL
, 5, 10, 0);
467 if (! tz
->useDaylightTime() || U_FAILURE(status
))
468 dataerrln("We're not in Daylight Savings Time and we should be. - %s", u_errorName(status
));
471 int32_t era
= cal
->get(UCAL_ERA
, status
);
472 int32_t year
= cal
->get(UCAL_YEAR
, status
);
473 int32_t month
= cal
->get(UCAL_MONTH
, status
);
474 int32_t day
= cal
->get(UCAL_DATE
, status
);
475 int32_t dayOfWeek
= cal
->get(UCAL_DAY_OF_WEEK
, status
);
476 int32_t millis
= cal
->get(UCAL_MILLISECOND
, status
) +
477 (cal
->get(UCAL_SECOND
, status
) +
478 (cal
->get(UCAL_MINUTE
, status
) +
479 (cal
->get(UCAL_HOUR
, status
) * 60) * 60) * 1000) -
480 cal
->get(UCAL_DST_OFFSET
, status
);
482 failure(status
, "cal->get");
483 int32_t offset
= tz
->getOffset((uint8_t)era
, year
, month
, day
, (uint8_t)dayOfWeek
, millis
, status
);
484 int32_t raw_offset
= tz
->getRawOffset();
486 if (offset
== raw_offset
)
487 dataerrln("Offsets should match");
494 * TimeZone::getAvailableIDs(int32_t) throws exception for certain values,
495 * due to a faulty constant in TimeZone::java.
497 void TimeZoneRegressionTest:: Test4151406() {
499 for (int32_t h
=-28; h
<=30; ++h
) {
500 // h is in half-hours from GMT; rawoffset is in millis
501 int32_t rawoffset
= h
* 1800000;
502 int32_t hh
= (h
<0) ? -h
: h
;
503 UnicodeString hname
= UnicodeString((h
<0) ? "GMT-" : "GMT+") +
504 ((hh
/2 < 10) ? "0" : "") +
506 ((hh%2
==0) ? "00" : "30");
508 UErrorCode ec
= U_ZERO_ERROR
;
510 StringEnumeration
* ids
= TimeZone::createEnumeration(rawoffset
);
512 dataerrln("Fail: TimeZone::createEnumeration(rawoffset)");
515 count
= ids
->count(ec
);
519 logln(hname
+ ' ' + (UnicodeString
)count
+ (UnicodeString
)" e.g. " + *ids
->snext(ec
));
521 logln(hname
+ ' ' + count
);
523 // weiv 11/27/2002: why uprv_free? This should be a delete
527 /*} catch (Exception e) {
528 errln(hname + ' ' + "Fail: " + e);
531 logln("Maximum zones per offset = %d", max
);
537 void TimeZoneRegressionTest:: Test4151429() {
538 // {sfb} silly test in C++, since we are using an enum and not an int
540 /*TimeZone *tz = TimeZone::createTimeZone("GMT");
542 tz->getDisplayName(TRUE, TimeZone::LONG,
543 Locale.getDefault(), name);
544 errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/
545 //} catch(IllegalArgumentException e) {}
550 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST
551 * and different DST parameters.
553 void TimeZoneRegressionTest:: Test4154537() {
554 UErrorCode status
= U_ZERO_ERROR
;
555 // tz1 and tz2 have no DST and different rule parameters
556 SimpleTimeZone
*tz1
= new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status
);
557 SimpleTimeZone
*tz2
= new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status
);
558 // tza and tzA have the same rule params
559 SimpleTimeZone
*tza
= new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status
);
560 SimpleTimeZone
*tzA
= new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status
);
561 // tzb differs from tza
562 SimpleTimeZone
*tzb
= new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status
);
564 if(U_FAILURE(status
))
565 errln("Couldn't create TimeZones");
567 if (tz1
->useDaylightTime() || tz2
->useDaylightTime() ||
568 !tza
->useDaylightTime() || !tzA
->useDaylightTime() ||
569 !tzb
->useDaylightTime()) {
570 errln("Test is broken -- rewrite it");
572 if (!tza
->hasSameRules(*tzA
) || tza
->hasSameRules(*tzb
)) {
573 errln("Fail: hasSameRules() broken for zones with rules");
575 if (!tz1
->hasSameRules(*tz2
)) {
576 errln("Fail: hasSameRules() returns false for zones without rules");
577 //errln("zone 1 = " + tz1);
578 //errln("zone 2 = " + tz2);
590 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't
591 * check for out-of-range arguments.
593 void TimeZoneRegressionTest:: Test4154542()
595 const int32_t GOOD
= 1;
596 const int32_t BAD
= 0;
598 const int32_t GOOD_MONTH
= UCAL_JANUARY
;
599 const int32_t GOOD_DAY
= 1;
600 const int32_t GOOD_DAY_OF_WEEK
= UCAL_SUNDAY
;
601 const int32_t GOOD_TIME
= 0;
604 GOOD
, INT32_MIN
, 0, INT32_MAX
, INT32_MIN
,
605 GOOD
, UCAL_JANUARY
, -5, UCAL_SUNDAY
, 0,
606 GOOD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, 24*60*60*1000,
607 BAD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, 24*60*60*1000+1,
608 BAD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, -1,
609 BAD
, UCAL_JANUARY
, -6, UCAL_SUNDAY
, 0,
610 BAD
, UCAL_DECEMBER
, 6, UCAL_SATURDAY
, 24*60*60*1000,
611 GOOD
, UCAL_DECEMBER
, 1, 0, 0,
612 GOOD
, UCAL_DECEMBER
, 31, 0, 0,
613 BAD
, UCAL_APRIL
, 31, 0, 0,
614 BAD
, UCAL_DECEMBER
, 32, 0, 0,
615 BAD
, UCAL_JANUARY
-1, 1, UCAL_SUNDAY
, 0,
616 BAD
, UCAL_DECEMBER
+1, 1, UCAL_SUNDAY
, 0,
617 GOOD
, UCAL_DECEMBER
, 31, -UCAL_SUNDAY
, 0,
618 GOOD
, UCAL_DECEMBER
, 31, -UCAL_SATURDAY
, 0,
619 BAD
, UCAL_DECEMBER
, 32, -UCAL_SATURDAY
, 0,
620 BAD
, UCAL_DECEMBER
, -32, -UCAL_SATURDAY
, 0,
621 BAD
, UCAL_DECEMBER
, 31, -UCAL_SATURDAY
-1, 0,
623 SimpleTimeZone
*zone
= new SimpleTimeZone(0, "Z");
624 for (int32_t i
=0; i
< 18*5; i
+=5) {
625 UBool shouldBeGood
= (DATA
[i
] == GOOD
);
626 int32_t month
= DATA
[i
+1];
627 int32_t day
= DATA
[i
+2];
628 int32_t dayOfWeek
= DATA
[i
+3];
629 int32_t time
= DATA
[i
+4];
631 UErrorCode status
= U_ZERO_ERROR
;
633 //Exception ex = null;
635 zone
->setStartRule(month
, day
, dayOfWeek
, time
, status
);
636 //} catch (IllegalArgumentException e) {
639 if (U_SUCCESS(status
) != shouldBeGood
) {
640 errln(UnicodeString("setStartRule(month=") + month
+ ", day=" + day
+
641 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
642 (shouldBeGood
? (") should work")
643 : ") should fail but doesn't"));
648 status
= U_ZERO_ERROR
;
649 zone
->setEndRule(month
, day
, dayOfWeek
, time
, status
);
650 //} catch (IllegalArgumentException e) {
653 if (U_SUCCESS(status
) != shouldBeGood
) {
654 errln(UnicodeString("setEndRule(month=") + month
+ ", day=" + day
+
655 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
656 (shouldBeGood
? (") should work")
657 : ") should fail but doesn't"));
662 // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion)
663 status
= U_ZERO_ERROR
;
664 SimpleTimeZone
*temp
= new SimpleTimeZone(0, "Z",
665 (int8_t)month
, (int8_t)day
, (int8_t)dayOfWeek
, time
,
666 (int8_t)GOOD_MONTH
, (int8_t)GOOD_DAY
, (int8_t)GOOD_DAY_OF_WEEK
,
668 //} catch (IllegalArgumentException e) {
671 if (U_SUCCESS(status
) != shouldBeGood
) {
672 errln(UnicodeString("SimpleTimeZone(month=") + month
+ ", day=" + day
+
673 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
674 (shouldBeGood
? (", <end>) should work")// + ex)
675 : ", <end>) should fail but doesn't"));
681 status
= U_ZERO_ERROR
;
682 temp
= new SimpleTimeZone(0, "Z",
683 (int8_t)GOOD_MONTH
, (int8_t)GOOD_DAY
, (int8_t)GOOD_DAY_OF_WEEK
,
685 (int8_t)month
, (int8_t)day
, (int8_t)dayOfWeek
, time
,status
);
686 //} catch (IllegalArgumentException e) {
689 if (U_SUCCESS(status
) != shouldBeGood
) {
690 errln(UnicodeString("SimpleTimeZone(<start>, month=") + month
+ ", day=" + day
+
691 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
692 (shouldBeGood
? (") should work")// + ex)
693 : ") should fail but doesn't"));
703 * SimpleTimeZone accepts illegal DST savings values. These values
704 * must be non-zero. There is no upper limit at this time.
707 TimeZoneRegressionTest::Test4154525()
709 const int32_t GOOD
= 1, BAD
= 0;
714 -1, GOOD
, // #13566 updates SimpleTimeZone to support negative DST saving amount
716 INT32_MAX
, GOOD
, // no upper limit on DST savings at this time
717 INT32_MIN
, GOOD
// no lower limit as well
720 UErrorCode status
= U_ZERO_ERROR
;
721 for(int32_t i
= 0; i
< 10; i
+=2) {
722 int32_t savings
= DATA
[i
];
723 UBool valid
= DATA
[i
+1] == GOOD
;
724 UnicodeString method
;
725 for(int32_t j
=0; j
< 2; ++j
) {
726 SimpleTimeZone
*z
=NULL
;
729 method
= "constructor";
730 z
= new SimpleTimeZone(0, "id",
731 UCAL_JANUARY
, 1, 0, 0,
733 savings
, status
); // <- what we're interested in
736 method
= "setDSTSavings()";
737 z
= new SimpleTimeZone(0, "GMT");
738 z
->setDSTSavings(savings
, status
);
742 if(U_FAILURE(status
)) {
744 errln(UnicodeString("Fail: DST savings of ") + savings
+ " to " + method
+ " gave " + u_errorName(status
));
747 logln(UnicodeString("Pass: DST savings of ") + savings
+ " to " + method
+ " gave " + u_errorName(status
));
752 logln(UnicodeString("Pass: DST savings of ") + savings
+ " accepted by " + method
);
755 errln(UnicodeString("Fail: DST savings of ") + savings
+ " accepted by " + method
);
758 status
= U_ZERO_ERROR
;
766 * SimpleTimeZone.getOffset accepts illegal arguments.
769 TimeZoneRegressionTest::Test4154650()
771 const int32_t GOOD
= 1, BAD
= 0;
772 const int32_t GOOD_ERA
= GregorianCalendar::AD
, GOOD_YEAR
= 1998, GOOD_MONTH
= UCAL_AUGUST
;
773 const int32_t GOOD_DAY
= 2, GOOD_DOW
= UCAL_SUNDAY
, GOOD_TIME
= 16*3600000;
776 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
778 GOOD
, GregorianCalendar::BC
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
779 GOOD
, GregorianCalendar::AD
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
780 BAD
, GregorianCalendar::BC
-1, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
781 BAD
, GregorianCalendar::AD
+1, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
783 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
784 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_DECEMBER
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
785 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
-1, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
786 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_DECEMBER
+1, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
788 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 1, GOOD_DOW
, GOOD_TIME
,
789 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 31, GOOD_DOW
, GOOD_TIME
,
790 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 0, GOOD_DOW
, GOOD_TIME
,
791 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 32, GOOD_DOW
, GOOD_TIME
,
793 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SUNDAY
, GOOD_TIME
,
794 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SATURDAY
, GOOD_TIME
,
795 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SUNDAY
-1, GOOD_TIME
,
796 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SATURDAY
+1, GOOD_TIME
,
798 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 0,
799 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 24*3600000-1,
800 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, -1,
801 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 24*3600000,
804 int32_t dataLen
= UPRV_LENGTHOF(DATA
);
806 UErrorCode status
= U_ZERO_ERROR
;
807 TimeZone
*tz
= TimeZone::createDefault();
808 for(int32_t i
= 0; i
< dataLen
; i
+= 7) {
809 UBool good
= DATA
[i
] == GOOD
;
810 //IllegalArgumentException e = null;
812 /*int32_t offset = */
813 tz
->getOffset((uint8_t)DATA
[i
+1], DATA
[i
+2], DATA
[i
+3],
814 DATA
[i
+4], (uint8_t)DATA
[i
+5], DATA
[i
+6], status
);
815 //} catch (IllegalArgumentException ex) {
818 if(good
!= U_SUCCESS(status
)) {
819 UnicodeString errMsg
;
821 errMsg
= (UnicodeString(") threw ") + u_errorName(status
));
824 errMsg
= UnicodeString(") accepts invalid args", "");
826 errln(UnicodeString("Fail: getOffset(") +
827 DATA
[i
+1] + ", " + DATA
[i
+2] + ", " + DATA
[i
+3] + ", " +
828 DATA
[i
+4] + ", " + DATA
[i
+5] + ", " + DATA
[i
+6] +
831 status
= U_ZERO_ERROR
; // reset
838 * TimeZone broken at midnight. The TimeZone code fails to handle
839 * transitions at midnight correctly.
842 TimeZoneRegressionTest::Test4162593()
844 UErrorCode status
= U_ZERO_ERROR
;
845 SimpleDateFormat
*fmt
= new SimpleDateFormat("z", Locale::getUS(), status
);
846 if(U_FAILURE(status
)) {
847 dataerrln("Error creating calendar %s", u_errorName(status
));
851 const int32_t ONE_HOUR
= 60*60*1000;
853 SimpleTimeZone
*asuncion
= new SimpleTimeZone(-4*ONE_HOUR
, "America/Asuncion" /*PY%sT*/,
854 UCAL_OCTOBER
, 1, 0 /*DOM*/, 0*ONE_HOUR
,
855 UCAL_MARCH
, 1, 0 /*DOM*/, 0*ONE_HOUR
, 1*ONE_HOUR
, status
);
859 * Transition expected between start+1H and start+2H
861 TimeZone
*DATA_TZ
[] = {
864 int32_t DATA_INT
[] [5] = {
865 // These years must be AFTER the Gregorian cutover
866 {1998, UCAL_SEPTEMBER
, 30, 22, 0},
867 {2000, UCAL_FEBRUARY
, 28, 22, 0},
868 {2000, UCAL_FEBRUARY
, 29, 22, 0},
871 UBool DATA_BOOL
[] = {
877 UnicodeString zone
[4];// = new String[4];
879 new SimpleTimeZone(2*ONE_HOUR
, "Asia/Damascus" /*EE%sT*/,
880 UCAL_APRIL
, 1, 0 /*DOM*/, 0*ONE_HOUR
,
881 UCAL_OCTOBER
, 1, 0 /*DOM*/, 0*ONE_HOUR
, 1*ONE_HOUR
, status
);
882 DATA_TZ
[1] = asuncion
; DATA_TZ
[2] = asuncion
;
884 for(int32_t j
= 0; j
< 3; j
++) {
885 TimeZone
*tz
= (TimeZone
*)DATA_TZ
[j
];
886 TimeZone::setDefault(*tz
);
887 fmt
->setTimeZone(*tz
);
889 // Must construct the Date object AFTER setting the default zone
890 int32_t *p
= (int32_t*)DATA_INT
[j
];
891 UDate d
= CalendarRegressionTest::makeDate(p
[0], p
[1], p
[2], p
[3], p
[4]);
892 UBool transitionExpected
= DATA_BOOL
[j
];
895 logln(tz
->getID(temp
) + ":");
896 for (int32_t i
= 0; i
< 4; ++i
) {
897 FieldPosition
pos(FieldPosition::DONT_CARE
);
899 zone
[i
] = fmt
->format(d
+ i
*ONE_HOUR
, zone
[i
], pos
);
900 logln(UnicodeString("") + i
+ ": " + d
+ " / " + zone
[i
]);
901 //d += (double) ONE_HOUR;
903 if(zone
[0] == zone
[1] &&
904 (zone
[1] == zone
[2]) != transitionExpected
&&
905 zone
[2] == zone
[3]) {
906 logln(UnicodeString("Ok: transition ") + transitionExpected
);
909 errln("Fail: boundary transition incorrect");
918 * getDisplayName doesn't work with unusual savings/offsets.
920 void TimeZoneRegressionTest::Test4176686() {
921 // Construct a zone that does not observe DST but
922 // that does have a DST savings (which should be ignored).
923 UErrorCode status
= U_ZERO_ERROR
;
924 int32_t offset
= 90 * 60000; // 1:30
925 SimpleTimeZone
* z1
= new SimpleTimeZone(offset
, "_std_zone_");
926 z1
->setDSTSavings(45 * 60000, status
); // 0:45
928 // Construct a zone that observes DST for the first 6 months.
929 SimpleTimeZone
* z2
= new SimpleTimeZone(offset
, "_dst_zone_");
930 z2
->setDSTSavings(45 * 60000, status
); // 0:45
931 z2
->setStartRule(UCAL_JANUARY
, 1, 0, status
);
932 z2
->setEndRule(UCAL_JULY
, 1, 0, status
);
934 // Also check DateFormat
935 DateFormat
* fmt1
= new SimpleDateFormat(UnicodeString("z"), status
);
936 if (U_FAILURE(status
)) {
937 dataerrln("Failure trying to construct: %s", u_errorName(status
));
940 fmt1
->setTimeZone(*z1
); // Format uses standard zone
941 DateFormat
* fmt2
= new SimpleDateFormat(UnicodeString("z"), status
);
942 if(!assertSuccess("trying to construct", status
))return;
943 fmt2
->setTimeZone(*z2
); // Format uses DST zone
944 Calendar
* tempcal
= Calendar::createInstance(status
);
946 tempcal
->set(1970, UCAL_FEBRUARY
, 1);
947 UDate dst
= tempcal
->getTime(status
); // Time in DST
948 tempcal
->set(1970, UCAL_AUGUST
, 1);
949 UDate std
= tempcal
->getTime(status
); // Time in standard
951 // Description, Result, Expected Result
952 UnicodeString a
,b
,c
,d
,e
,f
,g
,h
,i
,j
,k
,l
;
953 UnicodeString DATA
[] = {
954 "z1->getDisplayName(false, SHORT)/std zone",
955 z1
->getDisplayName(FALSE
, TimeZone::SHORT
, a
), "GMT+1:30",
956 "z1->getDisplayName(false, LONG)/std zone",
957 z1
->getDisplayName(FALSE
, TimeZone::LONG
, b
), "GMT+01:30",
958 "z1->getDisplayName(true, SHORT)/std zone",
959 z1
->getDisplayName(TRUE
, TimeZone::SHORT
, c
), "GMT+1:30",
960 "z1->getDisplayName(true, LONG)/std zone",
961 z1
->getDisplayName(TRUE
, TimeZone::LONG
, d
), "GMT+01:30",
962 "z2->getDisplayName(false, SHORT)/dst zone",
963 z2
->getDisplayName(FALSE
, TimeZone::SHORT
, e
), "GMT+1:30",
964 "z2->getDisplayName(false, LONG)/dst zone",
965 z2
->getDisplayName(FALSE
, TimeZone::LONG
, f
), "GMT+01:30",
966 "z2->getDisplayName(true, SHORT)/dst zone",
967 z2
->getDisplayName(TRUE
, TimeZone::SHORT
, g
), "GMT+2:15",
968 "z2->getDisplayName(true, LONG)/dst zone",
969 z2
->getDisplayName(TRUE
, TimeZone::LONG
, h
), "GMT+02:15",
970 "DateFormat.format(std)/std zone", fmt1
->format(std
, i
), "GMT+1:30",
971 "DateFormat.format(dst)/std zone", fmt1
->format(dst
, j
), "GMT+1:30",
972 "DateFormat.format(std)/dst zone", fmt2
->format(std
, k
), "GMT+1:30",
973 "DateFormat.format(dst)/dst zone", fmt2
->format(dst
, l
), "GMT+2:15",
976 for (int32_t idx
=0; idx
<UPRV_LENGTHOF(DATA
); idx
+=3) {
977 if (DATA
[idx
+1]!=(DATA
[idx
+2])) {
978 errln("FAIL: " + DATA
[idx
] + " -> " + DATA
[idx
+1] + ", exp " + DATA
[idx
+2]);
989 * Make sure setStartRule and setEndRule set the DST savings to nonzero
992 void TimeZoneRegressionTest::TestJ186() {
993 UErrorCode status
= U_ZERO_ERROR
;
994 // NOTE: Setting the DST savings to zero is illegal, so we
995 // are limited in the testing we can do here. This is why
996 // lines marked //~ are commented out.
997 SimpleTimeZone
z(0, "ID");
998 //~z.setDSTSavings(0, status); // Must do this!
999 z
.setStartRule(UCAL_FEBRUARY
, 1, UCAL_SUNDAY
, 0, status
);
1000 failure(status
, "setStartRule()");
1001 if (z
.useDaylightTime()) {
1002 errln("Fail: useDaylightTime true with start rule only");
1004 //~if (z.getDSTSavings() != 0) {
1005 //~ errln("Fail: dst savings != 0 with start rule only");
1007 z
.setEndRule(UCAL_MARCH
, -1, UCAL_SUNDAY
, 0, status
);
1008 failure(status
, "setStartRule()");
1009 if (!z
.useDaylightTime()) {
1010 errln("Fail: useDaylightTime false with rules set");
1012 if (z
.getDSTSavings() == 0) {
1013 errln("Fail: dst savings == 0 with rules set");
1018 * Test to see if DateFormat understands zone equivalency groups. It
1019 * might seem that this should be a DateFormat test, but it's really a
1020 * TimeZone test -- the changes to DateFormat are minor.
1022 * We use two known, stable zones that shouldn't change much over time
1023 * -- America/Vancouver and America/Los_Angeles. However, they MAY
1024 * change at some point -- if that happens, replace them with any two
1025 * zones in an equivalency group where one zone has localized name
1026 * data, and the other doesn't, in some locale.
1028 void TimeZoneRegressionTest::TestJ449() {
1029 UErrorCode status
= U_ZERO_ERROR
;
1032 // Modify the following three as necessary. The two IDs must
1033 // specify two zones in the same equivalency group. One must have
1034 // locale data in 'loc'; the other must not.
1035 const char* idWithLocaleData
= "America/Los_Angeles";
1036 const char* idWithoutLocaleData
= "US/Pacific";
1037 const Locale
loc("en", "", "");
1039 TimeZone
*zoneWith
= TimeZone::createTimeZone(idWithLocaleData
);
1040 TimeZone
*zoneWithout
= TimeZone::createTimeZone(idWithoutLocaleData
);
1041 // Make sure we got valid zones
1042 if (zoneWith
->getID(str
) != UnicodeString(idWithLocaleData
) ||
1043 zoneWithout
->getID(str
) != UnicodeString(idWithoutLocaleData
)) {
1044 dataerrln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData
+ ", got " + zoneWith
->getID(str
) + ", and wanted " + idWithoutLocaleData
+ " but got " + zoneWithout
->getID(str
));
1046 GregorianCalendar
calWith(*zoneWith
, status
);
1047 GregorianCalendar
calWithout(*zoneWithout
, status
);
1048 SimpleDateFormat
fmt("MMM d yyyy hh:mm a zzz", loc
, status
);
1049 if (U_FAILURE(status
)) {
1050 errln("Fail: Unable to create GregorianCalendar/SimpleDateFormat");
1053 UnicodeString strWith
, strWithout
;
1054 fmt
.setCalendar(calWith
);
1055 fmt
.format(date
, strWith
);
1056 fmt
.setCalendar(calWithout
);
1057 fmt
.format(date
, strWithout
);
1058 if (strWith
== strWithout
) {
1059 logln((UnicodeString
)"Ok: " + idWithLocaleData
+ " -> " +
1060 strWith
+ "; " + idWithoutLocaleData
+ " -> " +
1063 errln((UnicodeString
)"FAIL: " + idWithLocaleData
+ " -> " +
1064 strWith
+ "; " + idWithoutLocaleData
+ " -> " +
1074 // test new API for JDK 1.2 8/31 putback
1076 TimeZoneRegressionTest::TestJDK12API()
1078 // TimeZone *pst = TimeZone::createTimeZone("PST");
1079 // TimeZone *cst1 = TimeZone::createTimeZone("CST");
1080 UErrorCode ec
= U_ZERO_ERROR
;
1081 //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60
1082 TimeZone
*pst
= new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND
,
1084 3,1,-1,120*U_MILLIS_PER_MINUTE
,
1085 SimpleTimeZone::WALL_TIME
,
1086 9,-1,1,120*U_MILLIS_PER_MINUTE
,
1087 SimpleTimeZone::WALL_TIME
,
1088 60*U_MILLIS_PER_MINUTE
,ec
);
1089 //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60
1090 TimeZone
*cst1
= new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND
,
1092 3,1,-1,120*U_MILLIS_PER_MINUTE
,
1093 SimpleTimeZone::WALL_TIME
,
1094 9,-1,1,120*U_MILLIS_PER_MINUTE
,
1095 SimpleTimeZone::WALL_TIME
,
1096 60*U_MILLIS_PER_MINUTE
,ec
);
1097 if (U_FAILURE(ec
)) {
1098 errln("FAIL: SimpleTimeZone constructor");
1102 SimpleTimeZone
*cst
= dynamic_cast<SimpleTimeZone
*>(cst1
);
1104 if(pst
->hasSameRules(*cst
)) {
1105 errln("FAILURE: PST and CST have same rules");
1108 UErrorCode status
= U_ZERO_ERROR
;
1109 int32_t offset1
= pst
->getOffset(1,
1110 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
1111 failure(status
, "getOffset() failed");
1114 int32_t offset2
= cst
->getOffset(1,
1115 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), 31, status
);
1116 failure(status
, "getOffset() failed");
1118 if(offset1
== offset2
)
1119 errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST");
1121 // verify error checking
1123 1997, UCAL_FIELD_COUNT
+1, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
1124 if(U_SUCCESS(status
))
1125 errln("FAILURE: getOffset() succeeded with -1 for month");
1127 status
= U_ZERO_ERROR
;
1128 cst
->setDSTSavings(60*60*1000, status
);
1129 failure(status
, "setDSTSavings() failed");
1131 int32_t savings
= cst
->getDSTSavings();
1132 if(savings
!= 60*60*1000) {
1133 errln("setDSTSavings() failed");
1140 * SimpleTimeZone allows invalid DOM values.
1142 void TimeZoneRegressionTest::Test4184229() {
1143 SimpleTimeZone
* zone
= NULL
;
1144 UErrorCode status
= U_ZERO_ERROR
;
1145 zone
= new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, status
);
1146 if(U_SUCCESS(status
)){
1147 errln("Failed. No exception has been thrown for DOM -1 startDay");
1149 logln("(a) " + UnicodeString( u_errorName(status
)));
1151 status
= U_ZERO_ERROR
;
1154 zone
= new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, status
);
1155 if(U_SUCCESS(status
)){
1156 errln("Failed. No exception has been thrown for DOM -1 endDay");
1158 logln("(b) " + UnicodeString(u_errorName(status
)));
1160 status
= U_ZERO_ERROR
;
1163 zone
= new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 1000, status
);
1164 if(U_SUCCESS(status
)){
1165 errln("Failed. No exception has been thrown for DOM -1 startDay+savings");
1167 logln("(c) " + UnicodeString(u_errorName(status
)));
1169 status
= U_ZERO_ERROR
;
1171 zone
= new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000, status
);
1172 if(U_SUCCESS(status
)){
1173 errln("Failed. No exception has been thrown for DOM -1 endDay+ savings");
1175 logln("(d) " + UnicodeString(u_errorName(status
)));
1177 status
= U_ZERO_ERROR
;
1179 // Make a valid constructor call for subsequent tests.
1180 zone
= new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0, status
);
1182 zone
->setStartRule(0, -1, 0, 0, status
);
1183 if(U_SUCCESS(status
)){
1184 errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
1186 logln("(e) " + UnicodeString(u_errorName(status
)));
1188 zone
->setStartRule(0, -1, 0, status
);
1189 if(U_SUCCESS(status
)){
1190 errln("Failed. No exception has been thrown for DOM -1 setStartRule");
1192 logln("(f) " + UnicodeString(u_errorName(status
)));
1195 zone
->setEndRule(0, -1, 0, 0, status
);
1196 if(U_SUCCESS(status
)){
1197 errln("Failed. No exception has been thrown for DOM -1 setEndRule+savings");
1199 logln("(g) " + UnicodeString(u_errorName(status
)));
1202 zone
->setEndRule(0, -1, 0, status
);
1203 if(U_SUCCESS(status
)){
1204 errln("Failed. No exception has been thrown for DOM -1 setEndRule");
1206 logln("(h) " + UnicodeString(u_errorName(status
)));
1211 void TimeZoneRegressionTest::TestNegativeDaylightSaving() {
1212 UErrorCode status
= U_ZERO_ERROR
;
1213 int32_t stdOff
= 1 * 60*60*1000; // Standard offset UTC+1
1214 int save
= -1 * 60*60*1000; // DST saving amount -1 hour
1215 SimpleTimeZone
stzDublin(stdOff
, "Dublin-2018",
1216 UCAL_OCTOBER
, -1, -UCAL_SUNDAY
, 2*60*60*1000,
1217 UCAL_MARCH
, -1, -UCAL_SUNDAY
, 1*60*60*1000,
1219 failure(status
, "SimpleTimeZone constructor");
1221 if (save
!= stzDublin
.getDSTSavings()) {
1222 errln((UnicodeString
)"FAIL: DST saving is not " + save
);
1225 GregorianCalendar
cal(* TimeZone::getGMT(), status
);
1226 failure(status
, "GregorianCalendar constructor");
1232 cal
.set(2018, UCAL_JANUARY
, 15, 0, 0, 0);
1233 testDate
= cal
.getTime(status
);
1234 failure(status
, "calendar getTime() - Jan 15");
1236 if (!stzDublin
.inDaylightTime(testDate
, status
)) {
1237 errln("FAIL: The test date (Jan 15) must be in DST.");
1239 failure(status
, "inDaylightTime() - Jan 15");
1241 stzDublin
.getOffset(testDate
, FALSE
, rawOffset
, dstOffset
, status
);
1242 failure(status
, "getOffset() - Jan 15");
1243 if (rawOffset
!= stdOff
|| dstOffset
!= save
) {
1244 errln((UnicodeString
)"FAIL: Expected [stdoff=" + stdOff
+ ",save=" + save
1245 + "] on the test date (Jan 15), actual[stdoff=" + rawOffset
1246 + ",save=" + dstOffset
+ "]");
1249 cal
.set(2018, UCAL_JULY
, 15, 0, 0, 0);
1250 testDate
= cal
.getTime(status
);
1251 failure(status
, "calendar getTime() - Jul 15");
1253 if (stzDublin
.inDaylightTime(testDate
, status
)) {
1254 errln("FAIL: The test date (Jul 15) must be in DST.");
1256 failure(status
, "inDaylightTime() - Jul 15");
1258 stzDublin
.getOffset(testDate
, FALSE
, rawOffset
, dstOffset
, status
);
1259 failure(status
, "getOffset() - Jul 15");
1260 if (rawOffset
!= stdOff
|| dstOffset
!= 0) {
1261 errln((UnicodeString
)"FAIL: Expected [stdoff=" + stdOff
+ ",save=" + 0
1262 + "] on the test date (Jul 15), actual[stdoff=" + rawOffset
1263 + ",save=" + dstOffset
+ "]");
1268 #endif /* #if !UCONFIG_NO_FORMATTING */