1 /***********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2006, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ***********************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "callimts.h"
12 #include "caltest.h"
13 #include "unicode/calendar.h"
14 #include "unicode/gregocal.h"
15 #include "unicode/datefmt.h"
16 #include "unicode/smpdtfmt.h"
17 #include "putilimp.h"
18
19 U_NAMESPACE_USE
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)20 void CalendarLimitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
21 {
22 if (exec) logln("TestSuite TestCalendarLimit");
23 switch (index) {
24 // Re-enable this later
25 case 0:
26 name = "TestCalendarLimit";
27 if (exec) {
28 logln("TestCalendarLimit---"); logln("");
29 TestCalendarLimit();
30 }
31 break;
32 default: name = ""; break;
33 }
34 }
35
36
37 // *****************************************************************************
38 // class CalendarLimitTest
39 // *****************************************************************************
40
41 // -------------------------------------
42 void
test(UDate millis,U_NAMESPACE_QUALIFIER Calendar * cal,U_NAMESPACE_QUALIFIER DateFormat * fmt)43 CalendarLimitTest::test(UDate millis, U_NAMESPACE_QUALIFIER Calendar* cal, U_NAMESPACE_QUALIFIER DateFormat* fmt)
44 {
45 static const UDate kDrift = 1e-10;
46 UErrorCode exception = U_ZERO_ERROR;
47 UnicodeString theDate;
48 UErrorCode status = U_ZERO_ERROR;
49 cal->setTime(millis, exception);
50 if (U_SUCCESS(exception)) {
51 fmt->format(millis, theDate);
52 UDate dt = fmt->parse(theDate, status);
53 // allow a small amount of error (drift)
54 if(! withinErr(dt, millis, kDrift)) {
55 errln("FAIL:round trip for large milli, got: %.1lf wanted: %.1lf. (delta %.2lf greater than %.2lf)",
56 dt, millis, uprv_fabs(millis-dt), uprv_fabs(dt*kDrift));
57 logln(UnicodeString(" ") + theDate + " " + CalendarTest::calToStr(*cal));
58 } else {
59 logln(UnicodeString("OK: got ") + dt + ", wanted " + millis);
60 logln(UnicodeString(" ") + theDate);
61 }
62 }
63 }
64
65 // -------------------------------------
66
67 // bug 986c: deprecate nextDouble/previousDouble
68 //|double
69 //|CalendarLimitTest::nextDouble(double a)
70 //|{
71 //| return uprv_nextDouble(a, TRUE);
72 //|}
73 //|
74 //|double
75 //|CalendarLimitTest::previousDouble(double a)
76 //|{
77 //| return uprv_nextDouble(a, FALSE);
78 //|}
79
80 UBool
withinErr(double a,double b,double err)81 CalendarLimitTest::withinErr(double a, double b, double err)
82 {
83 return ( uprv_fabs(a - b) < uprv_fabs(a * err) );
84 }
85
86 void
TestCalendarLimit()87 CalendarLimitTest::TestCalendarLimit()
88 {
89 UErrorCode status = U_ZERO_ERROR;
90 Calendar *cal = Calendar::createInstance(status);
91 if (failure(status, "Calendar::createInstance")) return;
92 cal->adoptTimeZone(TimeZone::createTimeZone("GMT"));
93 DateFormat *fmt = DateFormat::createDateTimeInstance();
94 if(!fmt || !cal) {
95 dataerrln("can't open cal and/or fmt");
96 return;
97 }
98 fmt->adoptCalendar(cal);
99 ((SimpleDateFormat*) fmt)->applyPattern("HH:mm:ss.SSS zzz, EEEE, MMMM d, yyyy G");
100
101
102 // This test used to test the algorithmic limits of the dates that
103 // GregorianCalendar could handle. However, the algorithm has
104 // been rewritten completely since then and the prior limits no
105 // longer apply. Instead, we now do basic round-trip testing of
106 // some extreme (but still manageable) dates.
107 UDate m;
108 logln("checking 1e16..1e17");
109 for ( m = 1e16; m < 1e17; m *= 1.1) {
110 test(m, cal, fmt);
111 }
112 logln("checking -1e14..-1e15");
113 for ( m = -1e14; m > -1e15; m *= 1.1) {
114 test(m, cal, fmt);
115 }
116
117 // This is 2^52 - 1, the largest allowable mantissa with a 0
118 // exponent in a 64-bit double
119 UDate VERY_EARLY_MILLIS = - 4503599627370495.0;
120 UDate VERY_LATE_MILLIS = 4503599627370495.0;
121
122 // I am removing the previousDouble and nextDouble calls below for
123 // two reasons: 1. As part of jitterbug 986, I am deprecating
124 // these methods and removing calls to them. 2. This test is a
125 // non-critical boundary behavior test.
126 test(VERY_EARLY_MILLIS, cal, fmt);
127 //test(previousDouble(VERY_EARLY_MILLIS), cal, fmt);
128 test(VERY_LATE_MILLIS, cal, fmt);
129 //test(nextDouble(VERY_LATE_MILLIS), cal, fmt);
130 delete fmt;
131 }
132
133 #endif /* #if !UCONFIG_NO_FORMATTING */
134
135 // eof
136