]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | **************************************************************************** | |
3 | * Copyright (c) 1997-2013, International Business Machines Corporation and * | |
4 | * others. All Rights Reserved. * | |
5 | **************************************************************************** | |
6 | */ | |
7 | ||
8 | #include "unicode/utypes.h" | |
9 | ||
10 | #if !UCONFIG_NO_FORMATTING | |
11 | ||
12 | #include "unicode/utmscale.h" | |
13 | #include "unicode/ucal.h" | |
14 | ||
15 | #include "cintltst.h" | |
16 | ||
17 | #include <stdlib.h> | |
18 | #include <time.h> | |
19 | ||
20 | #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) | |
21 | ||
22 | #define LOOP_COUNT 10000 | |
23 | ||
24 | static void TestAPI(void); | |
25 | static void TestData(void); | |
26 | static void TestMonkey(void); | |
27 | static void TestDotNet(void); | |
28 | ||
29 | void addUtmsTest(TestNode** root); | |
30 | ||
31 | void addUtmsTest(TestNode** root) | |
32 | { | |
33 | addTest(root, &TestAPI, "tsformat/utmstest/TestAPI"); | |
34 | addTest(root, &TestData, "tsformat/utmstest/TestData"); | |
35 | addTest(root, &TestMonkey, "tsformat/utmstest/TestMonkey"); | |
36 | addTest(root, &TestDotNet, "tsformat/utmstest/TestDotNet"); | |
37 | } | |
38 | ||
39 | /** | |
40 | * Return a random int64_t where U_INT64_MIN <= ran <= U_INT64_MAX. | |
41 | */ | |
42 | static uint64_t randomInt64(void) | |
43 | { | |
44 | int64_t ran = 0; | |
45 | int32_t i; | |
46 | static UBool initialized = FALSE; | |
47 | ||
48 | if (!initialized) { | |
49 | srand((unsigned)time(NULL)); | |
50 | initialized = TRUE; | |
51 | } | |
52 | ||
53 | /* Assume rand has at least 12 bits of precision */ | |
54 | for (i = 0; i < sizeof(ran); i += 1) { | |
55 | ((char*)&ran)[i] = (char)((rand() & 0x0FF0) >> 4); | |
56 | } | |
57 | ||
58 | return ran; | |
59 | } | |
60 | ||
61 | static int64_t ranInt; | |
62 | static int64_t ranMin; | |
63 | static int64_t ranMax; | |
64 | ||
65 | static void initRandom(int64_t min, int64_t max) | |
66 | { | |
67 | uint64_t interval = max - min; | |
68 | ||
69 | ranMin = min; | |
70 | ranMax = max; | |
71 | ranInt = 0; | |
72 | ||
73 | /* Verify that we don't have a huge interval. */ | |
74 | if (interval < (uint64_t)U_INT64_MAX) { | |
75 | ranInt = interval; | |
76 | } | |
77 | } | |
78 | ||
79 | static int64_t randomInRange(void) | |
80 | { | |
81 | int64_t value; | |
82 | ||
83 | if (ranInt != 0) { | |
84 | value = randomInt64() % ranInt; | |
85 | ||
86 | if (value < 0) { | |
87 | value = -value; | |
88 | } | |
89 | ||
90 | value += ranMin; | |
91 | } else { | |
92 | do { | |
93 | value = randomInt64(); | |
94 | } while (value < ranMin || value > ranMax); | |
95 | } | |
96 | ||
97 | return value; | |
98 | } | |
99 | ||
100 | static void roundTripTest(int64_t value, UDateTimeScale scale) | |
101 | { | |
102 | UErrorCode status = U_ZERO_ERROR; | |
103 | int64_t rt = utmscale_toInt64(utmscale_fromInt64(value, scale, &status), scale, &status); | |
104 | ||
105 | if (rt != value) { | |
106 | log_err("Round-trip error: time scale = %d, value = %lld, round-trip = %lld.\n", scale, value, rt); | |
107 | } | |
108 | } | |
109 | ||
110 | static void toLimitTest(int64_t toLimit, int64_t fromLimit, UDateTimeScale scale) | |
111 | { | |
112 | UErrorCode status = U_ZERO_ERROR; | |
113 | int64_t result = utmscale_toInt64(toLimit, scale, &status); | |
114 | ||
115 | if (result != fromLimit) { | |
116 | log_err("toLimit failure: scale = %d, toLimit = %lld , utmscale_toInt64(toLimit, scale, &status) = %lld, fromLimit = %lld.\n", | |
117 | scale, toLimit, result, fromLimit); | |
118 | } | |
119 | } | |
120 | ||
121 | static void epochOffsetTest(int64_t epochOffset, int64_t units, UDateTimeScale scale) | |
122 | { | |
123 | UErrorCode status = U_ZERO_ERROR; | |
124 | int64_t universal = 0; | |
125 | int64_t universalEpoch = epochOffset * units; | |
126 | int64_t local = utmscale_toInt64(universalEpoch, scale, &status); | |
127 | ||
128 | if (local != 0) { | |
129 | log_err("utmscale_toInt64(epochOffset, scale, &status): scale = %d epochOffset = %lld, result = %lld.\n", scale, epochOffset, local); | |
130 | } | |
131 | ||
132 | local = utmscale_toInt64(0, scale, &status); | |
133 | ||
134 | if (local != -epochOffset) { | |
135 | log_err("utmscale_toInt64(0, scale): scale = %d, result = %lld.\n", scale, local); | |
136 | } | |
137 | ||
138 | universal = utmscale_fromInt64(-epochOffset, scale, &status); | |
139 | ||
140 | if (universal != 0) { | |
141 | log_err("from(-epochOffest, scale): scale = %d, epochOffset = %lld, result = %lld.\n", scale, epochOffset, universal); | |
142 | } | |
143 | ||
144 | universal = utmscale_fromInt64(0, scale, &status); | |
145 | ||
146 | if (universal != universalEpoch) { | |
147 | log_err("utmscale_fromInt64(0, scale): scale = %d, result = %lld.\n", scale, universal); | |
148 | } | |
149 | } | |
150 | ||
151 | static void TestEpochOffsets(void) | |
152 | { | |
153 | UErrorCode status = U_ZERO_ERROR; | |
154 | int32_t scale; | |
155 | ||
156 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
157 | int64_t units = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_UNITS_VALUE, &status); | |
158 | int64_t epochOffset = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_EPOCH_OFFSET_VALUE, &status); | |
159 | ||
160 | epochOffsetTest(epochOffset, units, (UDateTimeScale)scale); | |
161 | } | |
162 | } | |
163 | ||
164 | static void TestFromLimits(void) | |
165 | { | |
166 | UErrorCode status = U_ZERO_ERROR; | |
167 | int32_t scale; | |
168 | ||
169 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
170 | int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); | |
171 | int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); | |
172 | ||
173 | roundTripTest(fromMin, (UDateTimeScale)scale); | |
174 | roundTripTest(fromMax, (UDateTimeScale)scale); | |
175 | } | |
176 | } | |
177 | ||
178 | static void TestToLimits(void) | |
179 | { | |
180 | UErrorCode status = U_ZERO_ERROR; | |
181 | int32_t scale; | |
182 | ||
183 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
184 | int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); | |
185 | int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); | |
186 | int64_t toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status); | |
187 | int64_t toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status); | |
188 | ||
189 | toLimitTest(toMin, fromMin, (UDateTimeScale)scale); | |
190 | toLimitTest(toMax, fromMax, (UDateTimeScale)scale); | |
191 | } | |
192 | } | |
193 | ||
194 | static void TestFromInt64(void) | |
195 | { | |
196 | int32_t scale; | |
197 | int64_t result; | |
198 | UErrorCode status = U_ZERO_ERROR; | |
199 | ||
200 | result = utmscale_fromInt64(0, -1, &status); | |
201 | (void)result; /* Suppress set but not used warning. */ | |
202 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
203 | log_err("utmscale_fromInt64(0, -1, status) did not set status to U_ILLEGAL_ARGUMENT_ERROR.\n"); | |
204 | } | |
205 | ||
206 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
207 | int64_t fromMin, fromMax; | |
208 | ||
209 | status = U_ZERO_ERROR; | |
210 | fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); | |
211 | fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); | |
212 | ||
213 | status = U_ZERO_ERROR; | |
214 | result = utmscale_fromInt64(0, (UDateTimeScale)scale, &status); | |
215 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
216 | log_err("utmscale_fromInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
217 | } | |
218 | ||
219 | status = U_ZERO_ERROR; | |
220 | result = utmscale_fromInt64(fromMin, (UDateTimeScale)scale, &status); | |
221 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
222 | log_err("utmscale_fromInt64(fromMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
223 | } | |
224 | ||
225 | if (fromMin > U_INT64_MIN) { | |
226 | status = U_ZERO_ERROR; | |
227 | result = utmscale_fromInt64(fromMin - 1, (UDateTimeScale)scale, &status); | |
228 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
229 | log_err("utmscale_fromInt64(fromMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
230 | } | |
231 | } | |
232 | ||
233 | status = U_ZERO_ERROR; | |
234 | result = utmscale_fromInt64(fromMax, (UDateTimeScale)scale, &status); | |
235 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
236 | log_err("utmscale_fromInt64(fromMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
237 | } | |
238 | ||
239 | if (fromMax < U_INT64_MAX) { | |
240 | status = U_ZERO_ERROR; | |
241 | result = utmscale_fromInt64(fromMax + 1, (UDateTimeScale)scale, &status); | |
242 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
243 | log_err("utmscale_fromInt64(fromMax + 1, %d, &status) didn't generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
248 | status = U_ZERO_ERROR; | |
249 | result = utmscale_fromInt64(0, UDTS_MAX_SCALE, &status); | |
250 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
251 | log_err("utmscale_fromInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); | |
252 | } | |
253 | } | |
254 | ||
255 | static void TestToInt64(void) | |
256 | { | |
257 | int32_t scale; | |
258 | int64_t result; | |
259 | UErrorCode status = U_ZERO_ERROR; | |
260 | ||
261 | result = utmscale_toInt64(0, -1, &status); | |
262 | (void)result; /* suppress set but not used warning. */ | |
263 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
264 | log_err("utmscale_toInt64(0, -1, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); | |
265 | } | |
266 | ||
267 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
268 | int64_t toMin, toMax; | |
269 | ||
270 | status = U_ZERO_ERROR; | |
271 | toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status); | |
272 | toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status); | |
273 | ||
274 | status = U_ZERO_ERROR; | |
275 | result = utmscale_toInt64(0, (UDateTimeScale)scale, &status); | |
276 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
277 | log_err("utmscale_toInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
278 | } | |
279 | ||
280 | status = U_ZERO_ERROR; | |
281 | result = utmscale_toInt64(toMin, (UDateTimeScale)scale, &status); | |
282 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
283 | log_err("utmscale_toInt64(toMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
284 | } | |
285 | ||
286 | if (toMin > U_INT64_MIN) { | |
287 | status = U_ZERO_ERROR; | |
288 | result = utmscale_toInt64(toMin - 1, (UDateTimeScale)scale, &status); | |
289 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
290 | log_err("utmscale_toInt64(toMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
291 | } | |
292 | } | |
293 | ||
294 | ||
295 | status = U_ZERO_ERROR; | |
296 | result = utmscale_toInt64(toMax, (UDateTimeScale)scale, &status); | |
297 | if (status == U_ILLEGAL_ARGUMENT_ERROR) { | |
298 | log_err("utmscale_toInt64(toMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
299 | } | |
300 | ||
301 | if (toMax < U_INT64_MAX) { | |
302 | status = U_ZERO_ERROR; | |
303 | result = utmscale_toInt64(toMax + 1, (UDateTimeScale)scale, &status); | |
304 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
305 | log_err("utmscale_toInt64(toMax + 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); | |
306 | } | |
307 | } | |
308 | } | |
309 | ||
310 | status = U_ZERO_ERROR; | |
311 | result = utmscale_toInt64(0, UDTS_MAX_SCALE, &status); | |
312 | if (status != U_ILLEGAL_ARGUMENT_ERROR) { | |
313 | log_err("utmscale_toInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); | |
314 | } | |
315 | } | |
316 | ||
317 | static void TestAPI(void) | |
318 | { | |
319 | TestFromInt64(); | |
320 | TestToInt64(); | |
321 | } | |
322 | ||
323 | static void TestData(void) | |
324 | { | |
325 | TestEpochOffsets(); | |
326 | TestFromLimits(); | |
327 | TestToLimits(); | |
328 | } | |
329 | ||
330 | static void TestMonkey(void) | |
331 | { | |
332 | int32_t scale; | |
333 | UErrorCode status = U_ZERO_ERROR; | |
334 | ||
335 | for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { | |
336 | int64_t fromMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MIN_VALUE, &status); | |
337 | int64_t fromMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_FROM_MAX_VALUE, &status); | |
338 | int32_t i; | |
339 | ||
340 | initRandom(fromMin, fromMax); | |
341 | ||
342 | for (i = 0; i < LOOP_COUNT; i += 1) { | |
343 | int64_t value = randomInRange(); | |
344 | ||
345 | roundTripTest(value, (UDateTimeScale)scale); | |
346 | } | |
347 | } | |
348 | } | |
349 | ||
350 | struct DotNetDateTimeTicks { | |
351 | int32_t year; | |
352 | int32_t month; | |
353 | int32_t day; | |
354 | int64_t ticks; | |
355 | }; | |
356 | typedef struct DotNetDateTimeTicks DotNetDateTimeTicks; | |
357 | ||
358 | /* | |
359 | * This data was generated by C++.Net code like | |
360 | * Console::WriteLine(L" {{ {0}, 1, 1, INT64_C({1}) }},", year, DateTime(year, 1, 1).Ticks); | |
361 | * with the DateTime constructor taking int values for year, month, and date. | |
362 | */ | |
363 | static const DotNetDateTimeTicks dotNetDateTimeTicks[]={ | |
364 | /* year, month, day, ticks */ | |
365 | { 100, 1, 1, INT64_C(31241376000000000) }, | |
366 | { 100, 3, 1, INT64_C(31292352000000000) }, | |
367 | { 200, 1, 1, INT64_C(62798112000000000) }, | |
368 | { 200, 3, 1, INT64_C(62849088000000000) }, | |
369 | { 300, 1, 1, INT64_C(94354848000000000) }, | |
370 | { 300, 3, 1, INT64_C(94405824000000000) }, | |
371 | { 400, 1, 1, INT64_C(125911584000000000) }, | |
372 | { 400, 3, 1, INT64_C(125963424000000000) }, | |
373 | { 500, 1, 1, INT64_C(157469184000000000) }, | |
374 | { 500, 3, 1, INT64_C(157520160000000000) }, | |
375 | { 600, 1, 1, INT64_C(189025920000000000) }, | |
376 | { 600, 3, 1, INT64_C(189076896000000000) }, | |
377 | { 700, 1, 1, INT64_C(220582656000000000) }, | |
378 | { 700, 3, 1, INT64_C(220633632000000000) }, | |
379 | { 800, 1, 1, INT64_C(252139392000000000) }, | |
380 | { 800, 3, 1, INT64_C(252191232000000000) }, | |
381 | { 900, 1, 1, INT64_C(283696992000000000) }, | |
382 | { 900, 3, 1, INT64_C(283747968000000000) }, | |
383 | { 1000, 1, 1, INT64_C(315253728000000000) }, | |
384 | { 1000, 3, 1, INT64_C(315304704000000000) }, | |
385 | { 1100, 1, 1, INT64_C(346810464000000000) }, | |
386 | { 1100, 3, 1, INT64_C(346861440000000000) }, | |
387 | { 1200, 1, 1, INT64_C(378367200000000000) }, | |
388 | { 1200, 3, 1, INT64_C(378419040000000000) }, | |
389 | { 1300, 1, 1, INT64_C(409924800000000000) }, | |
390 | { 1300, 3, 1, INT64_C(409975776000000000) }, | |
391 | { 1400, 1, 1, INT64_C(441481536000000000) }, | |
392 | { 1400, 3, 1, INT64_C(441532512000000000) }, | |
393 | { 1500, 1, 1, INT64_C(473038272000000000) }, | |
394 | { 1500, 3, 1, INT64_C(473089248000000000) }, | |
395 | { 1600, 1, 1, INT64_C(504595008000000000) }, | |
396 | { 1600, 3, 1, INT64_C(504646848000000000) }, | |
397 | { 1700, 1, 1, INT64_C(536152608000000000) }, | |
398 | { 1700, 3, 1, INT64_C(536203584000000000) }, | |
399 | { 1800, 1, 1, INT64_C(567709344000000000) }, | |
400 | { 1800, 3, 1, INT64_C(567760320000000000) }, | |
401 | { 1900, 1, 1, INT64_C(599266080000000000) }, | |
402 | { 1900, 3, 1, INT64_C(599317056000000000) }, | |
403 | { 2000, 1, 1, INT64_C(630822816000000000) }, | |
404 | { 2000, 3, 1, INT64_C(630874656000000000) }, | |
405 | { 2100, 1, 1, INT64_C(662380416000000000) }, | |
406 | { 2100, 3, 1, INT64_C(662431392000000000) }, | |
407 | { 2200, 1, 1, INT64_C(693937152000000000) }, | |
408 | { 2200, 3, 1, INT64_C(693988128000000000) }, | |
409 | { 2300, 1, 1, INT64_C(725493888000000000) }, | |
410 | { 2300, 3, 1, INT64_C(725544864000000000) }, | |
411 | { 2400, 1, 1, INT64_C(757050624000000000) }, | |
412 | { 2400, 3, 1, INT64_C(757102464000000000) }, | |
413 | { 2500, 1, 1, INT64_C(788608224000000000) }, | |
414 | { 2500, 3, 1, INT64_C(788659200000000000) }, | |
415 | { 2600, 1, 1, INT64_C(820164960000000000) }, | |
416 | { 2600, 3, 1, INT64_C(820215936000000000) }, | |
417 | { 2700, 1, 1, INT64_C(851721696000000000) }, | |
418 | { 2700, 3, 1, INT64_C(851772672000000000) }, | |
419 | { 2800, 1, 1, INT64_C(883278432000000000) }, | |
420 | { 2800, 3, 1, INT64_C(883330272000000000) }, | |
421 | { 2900, 1, 1, INT64_C(914836032000000000) }, | |
422 | { 2900, 3, 1, INT64_C(914887008000000000) }, | |
423 | { 3000, 1, 1, INT64_C(946392768000000000) }, | |
424 | { 3000, 3, 1, INT64_C(946443744000000000) }, | |
425 | { 1, 1, 1, INT64_C(0) }, | |
426 | { 1601, 1, 1, INT64_C(504911232000000000) }, | |
427 | { 1899, 12, 31, INT64_C(599265216000000000) }, | |
428 | { 1904, 1, 1, INT64_C(600527520000000000) }, | |
429 | { 1970, 1, 1, INT64_C(621355968000000000) }, | |
430 | { 2001, 1, 1, INT64_C(631139040000000000) }, | |
431 | { 9900, 3, 1, INT64_C(3123873216000000000) }, | |
432 | { 9999, 12, 31, INT64_C(3155378112000000000) } | |
433 | }; | |
434 | ||
435 | /* | |
436 | * ICU's Universal Time Scale is designed to be tick-for-tick compatible with | |
437 | * .Net System.DateTime. Verify that this is so for the | |
438 | * .Net-supported date range (years 1-9999 AD). | |
439 | * This requires a proleptic Gregorian calendar because that's what .Net uses. | |
440 | * Proleptic: No Julian/Gregorian switchover, or a switchover before | |
441 | * any date that we test, that is, before 0001 AD. | |
442 | */ | |
443 | static void | |
444 | TestDotNet() { | |
445 | static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */ | |
446 | const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */ | |
447 | const int64_t dayTicks = 86400 * INT64_C(10000000); | |
448 | const DotNetDateTimeTicks *dt; | |
449 | UCalendar *cal; | |
450 | UErrorCode errorCode; | |
451 | UDate icuDate; | |
452 | int64_t ticks, millis; | |
453 | int32_t i; | |
454 | ||
455 | /* Open a proleptic Gregorian calendar. */ | |
456 | errorCode = U_ZERO_ERROR; | |
457 | cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode); | |
458 | ucal_setGregorianChange(cal, -1000000 * (dayMillis * (UDate)1), &errorCode); | |
459 | if(U_FAILURE(errorCode)) { | |
460 | log_data_err("ucal_open(UTC/proleptic Gregorian) failed: %s - (Are you missing data?)\n", u_errorName(errorCode)); | |
461 | ucal_close(cal); | |
462 | return; | |
463 | } | |
464 | for(i = 0; i < LENGTHOF(dotNetDateTimeTicks); ++i) { | |
465 | /* Test conversion from .Net/Universal time to ICU time. */ | |
466 | dt = dotNetDateTimeTicks + i; | |
467 | millis = utmscale_toInt64(dt->ticks, UDTS_ICU4C_TIME, &errorCode); | |
468 | ucal_clear(cal); | |
469 | ucal_setDate(cal, dt->year, dt->month - 1, dt->day, &errorCode); /* Java & ICU use January = month 0. */ | |
470 | icuDate = ucal_getMillis(cal, &errorCode); | |
471 | if(millis != icuDate) { | |
472 | /* Print days not millis to stay within printf() range. */ | |
473 | log_err("utmscale_toInt64(ticks[%d], ICU4C)=%dd != %dd=ucal_getMillis(%04d-%02d-%02d)\n", | |
474 | (int)i, (int)(millis/dayMillis), (int)(icuDate/dayMillis), (int)dt->year, (int)dt->month, (int)dt->day); | |
475 | } | |
476 | ||
477 | /* Test conversion from ICU time to .Net/Universal time. */ | |
478 | ticks = utmscale_fromInt64((int64_t)icuDate, UDTS_ICU4C_TIME, &errorCode); | |
479 | if(ticks != dt->ticks) { | |
480 | /* Print days not ticks to stay within printf() range. */ | |
481 | log_err("utmscale_fromInt64(date[%d], ICU4C)=%dd != %dd=.Net System.DateTime(%04d-%02d-%02d).Ticks\n", | |
482 | (int)i, (int)(ticks/dayTicks), (int)(dt->ticks/dayTicks), (int)dt->year, (int)dt->month, (int)dt->day); | |
483 | } | |
484 | } | |
485 | ||
486 | ucal_close(cal); | |
487 | } | |
488 | ||
489 | #endif /* #if !UCONFIG_NO_FORMATTING */ |