]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tsdate.cpp
ICU-62135.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / tsdate.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /***********************************************************************
4 * Copyright (c) 1997-2009, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ***********************************************************************/
7
8 #include "unicode/utypes.h"
9
10 #if !UCONFIG_NO_FORMATTING
11
12 #include "unicode/datefmt.h"
13 #include "unicode/smpdtfmt.h"
14 #include "tsdate.h"
15 #include "putilimp.h"
16 #include "cstring.h"
17
18 #include <float.h>
19 #include <stdlib.h>
20 #include <math.h>
21
22 const double IntlTestDateFormat::ONEYEAR = 365.25 * ONEDAY; // Approximate
23
24 IntlTestDateFormat::~IntlTestDateFormat() {}
25
26 /**
27 * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
28 * DateFormat.
29 */
30 // par is ignored throughout this file
31 void IntlTestDateFormat::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
32 {
33 if (exec) logln("TestSuite DateFormat");
34 switch (index) {
35 case 0: name = "GenericTest";
36 if (exec) {
37 logln(name);
38 fFormat = DateFormat::createInstance();
39 fTestName = "createInstance";
40 fLimit = 3;
41 testFormat(/* par */);
42 }
43 break;
44 case 1: name = "DefaultLocale";
45 if (exec) {
46 logln(name);
47 testLocale(/*par, */Locale::getDefault(), "Default Locale");
48 }
49 break;
50
51 case 2: name = "TestAvailableLocales";
52 if (exec) {
53 logln(name);
54 testAvailableLocales(/* par */);
55 }
56 break;
57
58 case 3: name = "MonsterTest";
59 if (exec) {
60 logln(name);
61 monsterTest(/*par*/);
62 }
63 break;
64
65 default: name = ""; break;
66 }
67 }
68
69 void
70 IntlTestDateFormat::testLocale(/*char* par, */const Locale& locale, const UnicodeString& localeName)
71 {
72 DateFormat::EStyle timeStyle, dateStyle;
73
74 // For patterns including only time information and a timezone, it may take
75 // up to three iterations, since the timezone may shift as the year number
76 // is determined. For other patterns, 2 iterations should suffice.
77 fLimit = 3;
78
79 for(timeStyle = (DateFormat::EStyle)0;
80 timeStyle < (DateFormat::EStyle)4;
81 timeStyle = (DateFormat::EStyle) (timeStyle+1))
82 {
83 fTestName = (UnicodeString) "Time test " + (int32_t) timeStyle + " (" + localeName + ")";
84 fFormat = DateFormat::createTimeInstance(timeStyle, locale);
85 testFormat(/* par */);
86 }
87
88 fLimit = 2;
89
90 for(dateStyle = (DateFormat::EStyle)0;
91 dateStyle < (DateFormat::EStyle)4;
92 dateStyle = (DateFormat::EStyle) (dateStyle+1))
93 {
94 fTestName = (UnicodeString) "Date test " + (int32_t) dateStyle + " (" + localeName + ")";
95 fFormat = DateFormat::createDateInstance(dateStyle, locale);
96 testFormat(/* par */);
97 }
98
99 for(dateStyle = (DateFormat::EStyle)0;
100 dateStyle < (DateFormat::EStyle)4;
101 dateStyle = (DateFormat::EStyle) (dateStyle+1))
102 {
103 for(timeStyle = (DateFormat::EStyle)0;
104 timeStyle < (DateFormat::EStyle)4;
105 timeStyle = (DateFormat::EStyle) (timeStyle+1))
106 {
107 fTestName = (UnicodeString) "DateTime test " + (int32_t) dateStyle + "/" + (int32_t) timeStyle + " (" + localeName + ")";
108 fFormat = DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale);
109 testFormat(/* par */);
110 }
111 }
112 }
113
114 void IntlTestDateFormat::testFormat(/* char* par */)
115 {
116 if (fFormat == 0)
117 {
118 dataerrln("FAIL: DateFormat creation failed");
119 return;
120 }
121
122 describeTest();
123
124 UDate now = Calendar::getNow();
125 tryDate(0);
126 tryDate(1278161801778.0);
127 tryDate(5264498352317.0); // Sunday, October 28, 2136 8:39:12 AM PST
128 tryDate(9516987689250.0); // In the year 2271
129 tryDate(now);
130 // Shift 6 months into the future, AT THE SAME TIME OF DAY.
131 // This will test the DST handling.
132 tryDate(now + 6.0*30*ONEDAY);
133
134 UDate limit = now * 10; // Arbitrary limit
135 for (int32_t i=0; i<3; ++i)
136 tryDate(uprv_floor(randDouble() * limit));
137
138 delete fFormat;
139 }
140
141 void
142 IntlTestDateFormat::describeTest()
143 {
144 // Assume it's a SimpleDateFormat and get some info
145 SimpleDateFormat *s = (SimpleDateFormat*)fFormat;
146 UnicodeString str;
147 logln(fTestName + " Pattern " + s->toPattern(str));
148 }
149
150 void IntlTestDateFormat::tryDate(UDate theDate)
151 {
152 const int32_t DEPTH = 10;
153 UDate date[DEPTH];
154 UnicodeString string[DEPTH];
155
156 int32_t dateMatch = 0;
157 int32_t stringMatch = 0;
158 UBool dump = FALSE;
159 #if defined (U_CAL_DEBUG)
160 dump = TRUE;
161 #endif
162 int32_t i;
163
164 date[0] = theDate;
165 fFormat->format(theDate, string[0]);
166
167 for (i=1; i<DEPTH; ++i)
168 {
169 UErrorCode status = U_ZERO_ERROR;
170 date[i] = fFormat->parse(string[i-1], status);
171 if (U_FAILURE(status))
172 {
173 describeTest();
174 errln("**** FAIL: Parse of " + prettify(string[i-1], FALSE) + " failed.");
175 dump = TRUE;
176 break;
177 }
178 fFormat->format(date[i], string[i]);
179 if (dateMatch == 0 && date[i] == date[i-1])
180 dateMatch = i;
181 else if (dateMatch > 0 && date[i] != date[i-1])
182 {
183 describeTest();
184 errln("**** FAIL: Date mismatch after match for " + string[i]);
185 dump = TRUE;
186 break;
187 }
188 if (stringMatch == 0 && string[i] == string[i-1])
189 stringMatch = i;
190 else if (stringMatch > 0 && string[i] != string[i-1])
191 {
192 describeTest();
193 errln("**** FAIL: String mismatch after match for " + string[i]);
194 dump = TRUE;
195 break;
196 }
197 if (dateMatch > 0 && stringMatch > 0)
198 break;
199 }
200 if (i == DEPTH)
201 --i;
202
203 if (stringMatch > fLimit || dateMatch > fLimit)
204 {
205 describeTest();
206 errln((UnicodeString)"**** FAIL: No string and/or date match within " + fLimit
207 + " iterations for the Date " + string[0] + "\t(" + theDate + ").");
208 dump = TRUE;
209 }
210
211 if (dump)
212 {
213 for (int32_t k=0; k<=i; ++k)
214 {
215 logln((UnicodeString)"" + k + ": " + date[k] + " F> " +
216 string[k] + " P> ");
217 }
218 }
219 }
220
221 // Return a random double from 0.01 to 1, inclusive
222 double IntlTestDateFormat::randDouble()
223 {
224 // Assume 8-bit (or larger) rand values. Also assume
225 // that the system rand() function is very poor, which it always is.
226 double d=0.0;
227 uint32_t i;
228 char* poke = (char*)&d;
229 do {
230 do {
231 for (i=0; i < sizeof(double); ++i)
232 {
233 poke[i] = (char)(rand() & 0xFF);
234 }
235 } while (uprv_isNaN(d) || uprv_isInfinite(d));
236
237 if (d < 0.0)
238 d = -d;
239 if (d > 0.0)
240 {
241 double e = uprv_floor(log10(d));
242 if (e < -2.0)
243 d *= uprv_pow10((int32_t)(-e-2));
244 else if (e > -1.0)
245 d /= uprv_pow10((int32_t)(e+1));
246 }
247 // While this is not a real normalized number make another one.
248 } while (uprv_isNaN(d) || uprv_isInfinite(d)
249 || !((-DBL_MAX < d && d < DBL_MAX) || (d < -DBL_MIN && DBL_MIN < d)));
250 return d;
251 }
252
253 void IntlTestDateFormat::testAvailableLocales(/* char* par */)
254 {
255 int32_t count = 0;
256 const Locale* locales = DateFormat::getAvailableLocales(count);
257 logln((UnicodeString)"" + count + " available locales");
258 if (locales && count)
259 {
260 UnicodeString name;
261 UnicodeString all;
262 for (int32_t i=0; i<count; ++i)
263 {
264 if (i!=0) all += ", ";
265 all += locales[i].getName();
266 }
267 logln(all);
268 }
269 else dataerrln((UnicodeString)"**** FAIL: Zero available locales or null array pointer");
270 }
271
272 void IntlTestDateFormat::monsterTest(/*char *par*/)
273 {
274 int32_t count;
275 const Locale* locales = DateFormat::getAvailableLocales(count);
276 if (locales && count)
277 {
278 if (quick && count > 3) {
279 logln("quick test: testing just 3 locales!");
280 count = 3;
281 }
282 for (int32_t i=0; i<count; ++i)
283 {
284 UnicodeString name = UnicodeString(locales[i].getName(), "");
285 logln((UnicodeString)"Testing " + name + "...");
286 testLocale(/*par, */locales[i], name);
287 }
288 }
289 }
290
291 #endif /* #if !UCONFIG_NO_FORMATTING */