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