]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/unicode/utmscale.h
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / i18n / unicode / utmscale.h
CommitLineData
374ca955
A
1/*
2*******************************************************************************
3* Copyright (C) 2004, International Business Machines Corporation and
4* others. All Rights Reserved.
5*******************************************************************************
6*/
7
8#ifndef UTMSCALE_H
9#define UTMSCALE_H
10
11#include "unicode/utypes.h"
12
13#if !UCONFIG_NO_FORMATTING
14
15/**
16 * \file
17 * \brief C API: Universal Time Scale
18 *
19 * There are quite a few different conventions for binary datetime, depending on different
20 * platforms and protocols. Some of these have severe drawbacks. For example, people using
21 * Unix time (seconds since Jan 1, 1970) think that they are safe until near the year 2038.
22 * But cases can and do arise where arithmetic manipulations causes serious problems. Consider
23 * the computation of the average of two datetimes, for example: if one calculates them with
24 * <code>averageTime = (time1 + time2)/2</code>, there will be overflow even with dates
25 * around the present. Moreover, even if these problems don't occur, there is the issue of
26 * conversion back and forth between different systems.
27 *
28 * <p>
29 * Binary datetimes differ in a number of ways: the datatype, the unit,
30 * and the epoch (origin). We'll refer to these as time scales. For example:
31 *
32 * <table border="1" cellspacing="0" cellpadding="4">
33 * <caption>Table 1: Binary Time Scales</caption>
34 * <tr>
35 * <th align="left">Source</th>
36 * <th align="left">Datatype</th>
37 * <th align="left">Unit</th>
38 * <th align="left">Epoch</th>
39 * </tr>
40 *
41 * <tr>
42 * <td>JAVA_TIME</td>
43 * <td>int64_t</td>
44 * <td>milliseconds</td>
45 * <td>Jan 1, 1970</td>
46 * </tr>
47 * <tr>
48 *
49 * <td>UNIX_TIME</td>
50 * <td>int32_t or int64_t</td>
51 * <td>seconds</td>
52 * <td>Jan 1, 1970</td>
53 * </tr>
54 * <tr>
55 * <td>ICU4C_TIME</td>
56 *
57 * <td>double</td>
58 * <td>milliseconds</td>
59 * <td>Jan 1, 1970</td>
60 * </tr>
61 * <tr>
62 * <td>WINDOWS_FILE_TIME</td>
63 * <td>int64_t</td>
64 *
65 * <td>ticks (100 nanoseconds)</td>
66 * <td>Jan 1, 1601</td>
67 * </tr>
68 * <tr>
69 * <td>WINDOWS_DATE_TIME</td>
70 * <td>int64_t</td>
71 * <td>ticks (100 nanoseconds)</td>
72 *
73 * <td>Jan 1, 0001</td>
74 * </tr>
75 * <tr>
76 * <td>MAC_OLD_TIME</td>
77 * <td>int32_t</td>
78 * <td>seconds</td>
79 * <td>Jan 1, 1904</td>
80 *
81 * </tr>
82 * <tr>
83 * <td>MAC_TIME</td>
84 * <td>double</td>
85 * <td>seconds</td>
86 * <td>Jan 1, 2001</td>
87 * </tr>
88 *
89 * <tr>
90 * <td>EXCEL_TIME</td>
91 * <td>?</td>
92 * <td>days</td>
93 * <td>Dec 31, 1899</td>
94 * </tr>
95 * <tr>
96 *
97 * <td>DB2_TIME</td>
98 * <td>?</td>
99 * <td>days</td>
100 * <td>Dec 31, 1899</td>
101 * </tr>
102 * </table>
103 *
104 * <p>
105 * All of the epochs start at 00:00 am (the earliest possible time on the day in question),
106 * and are assumed to be UTC.
107 *
108 * <p>
109 * The ranges for different datatypes are given in the following table (all values in years).
110 * The range of years includes the entire range expressible with positive and negative
111 * values of the datatype. The range of years for double is the range that would be allowed
112 * without losing precision to the corresponding unit.
113 *
114 * <table border="1" cellspacing="0" cellpadding="4">
115 * <tr>
116 * <th align="left">Units</th>
117 * <th align="left">int64_t</th>
118 * <th align="left">double</th>
119 * <th align="left">int32_t</th>
120 * </tr>
121 *
122 * <tr>
123 * <td>1 sec</td>
124 * <td align="right">5.84542x10<sup>11</sup></td>
125 * <td align="right">285,420,920.94</td>
126 * <td align="right">136.10</td>
127 * </tr>
128 * <tr>
129 *
130 * <td>1 millisecond</td>
131 * <td align="right">584,542,046.09</td>
132 * <td align="right">285,420.92</td>
133 * <td align="right">0.14</td>
134 * </tr>
135 * <tr>
136 * <td>1 microsecond</td>
137 *
138 * <td align="right">584,542.05</td>
139 * <td align="right">285.42</td>
140 * <td align="right">0.00</td>
141 * </tr>
142 * <tr>
143 * <td>100 nanoseconds (tick)</td>
144 * <td align="right">58,454.20</td>
145 * <td align="right">28.54</td>
146 * <td align="right">0.00</td>
147 * </tr>
148 * <tr>
149 * <td>1 nanosecond</td>
150 * <td align="right">584.5420461</td>
151 * <td align="right">0.2854</td>
152 * <td align="right">0.00</td>
153 * </tr>
154 * </table>
155 *
156 * <p>
157 * These functions implement a universal time scale which can be used as a 'pivot',
158 * and provide conversion functions to and from all other major time scales.
159 * This datetimes to be converted to the pivot time, safely manipulated,
160 * and converted back to any other datetime time scale.
161 *
162 *<p>
163 * So what to use for this pivot? Java time has plenty of range, but cannot represent
164 * Windows datetimes without severe loss of precision. ICU4C time addresses this by using a
165 * <code>double</code> that is otherwise equivalent to the Java time. However, there are disadvantages
166 * with <code>doubles</code>. They provide for much more graceful degradation in arithmetic operations.
167 * But they only have 53 bits of accuracy, which means that they will lose precision when
168 * converting back and forth to ticks. What would really be nice would be a
169 * long double (80 bits -- 64 bit mantissa), but that is not supported on most systems.
170 *
171 *<p>
172 * The Unix extended time uses a structure with two components: time in seconds and a
173 * fractional field (microseconds). However, this is clumsy, slow, and
174 * prone to error (you always have to keep track of overflow and underflow in the
175 * fractional field). <code>BigDecimal</code> would allow for arbitrary precision and arbitrary range,
176 * but we do not want to use this as the normal type, because it is slow and does not
177 * have a fixed size.
178 *
179 *<p>
180 * Because of these issues, we ended up concluding that the Windows datetime would be the
181 * best pivot. However, we use the full range allowed by the datatype, allowing for
182 * datetimes back to 29,000 BC and up to 29,000 AD. This time scale is very fine grained,
183 * does not lose precision, and covers a range that will meet almost all requirements.
184 * It will not handle the range that Java times do, but frankly, being able to handle dates
185 * before 29,000 BC or after 29,000 AD is of very limited interest.
186 *
187 */
188
189/**
190 * <code>UDateTimeScale</code> values are used to specify the time scale used for
191 * conversion into or out if the universal time scale.
192 *
193 * @draft ICU 3.2
194 */
195typedef enum UDateTimeScale {
196 /**
197 * Used in the JDK. Data is a Java <code>long</code> (<code>int64_t</code>). Value
198 * is milliseconds since January 1, 1970.
199 *
200 * @draft ICU 3.2
201 */
202 UDTS_JAVA_TIME = 0,
203
204 /**
205 * Used on Unix systems. Data is <code>int32_t</code> or <code>int64_t</code>. Value
206 * is seconds since January 1, 1970.
207 *
208 * @draft ICU 3.2
209 */
210 UDTS_UNIX_TIME,
211
212 /**
213 * Used in IUC4C. Data is a <code>double</code>. Value
214 * is milliseconds since January 1, 1970.
215 *
216 * @draft ICU 3.2
217 */
218 UDTS_ICU4C_TIME,
219
220 /**
221 * Used in Windows for file times. Data is an <code>int64_t</code>. Value
222 * is ticks (1 tick == 100 nanoseconds) since January 1, 1601.
223 *
224 * @draft ICU 3.2
225 */
226 UDTS_WINDOWS_FILE_TIME,
227
228 /**
229 * Used in Windows for dates and times (?). Data is an <code>int64_t</code>. Value
230 * is ticks (1 tick == 100 nanoseconds) since January 1, 0001.
231 *
232 * @draft ICU 3.2
233 */
234 UDTS_WINDOWS_DATE_TIME,
235
236 /**
237 * Used in older Macintosh systems. Data is an <code>int32_t</code>. Value
238 * is seconds since January 1, 1904.
239 *
240 * @draft ICU 3.2
241 */
242 UDTS_MAC_OLD_TIME,
243
244 /**
245 * Used in newer Macintosh systems. Data is a <code>double</code>. Value
246 * is seconds since January 1, 2001.
247 *
248 * @draft ICU 3.2
249 */
250 UDTS_MAC_TIME,
251
252 /**
253 * Used in Excel. Data is an <code>?unknown?</code>. Value
254 * is days since December 31, 1899.
255 *
256 * @draft ICU 3.2
257 */
258 UDTS_EXCEL_TIME,
259
260 /**
261 * Used in DB2. Data is an <code>?unknown?</code>. Value
262 * is days since December 31, 1899.
263 *
264 * @draft ICU 3.2
265 */
266 UDTS_DB2_TIME,
267
268 /**
269 * The first unused time scale value.
270 *
271 * @draft ICU 3.2
272 */
273 UDTS_MAX_SCALE
274} UDateTimeScale;
275
276typedef enum UTimeScaleValue {
277 /**
278 * The constant used to select the units vale
279 * for a time scale.
280 *
281 * @see utms_getTimeScaleValue
282 *
283 * @draft ICU 3.2
284 */
285 UTSV_UNITS_VALUE = 0,
286
287 /**
288 * The constant used to select the epoch offset value
289 * for a time scale.
290 *
291 * @see utms_getTimeScaleValue
292 *
293 * @draft ICU 3.2
294 */
295 UTSV_EPOCH_OFFSET_VALUE,
296
297 /**
298 * The constant used to select the minimum from value
299 * for a time scale.
300 *
301 * @see utms_getTimeScaleValue
302 *
303 * @draft ICU 3.2
304 */
305 UTSV_FROM_MIN_VALUE,
306
307 /**
308 * The constant used to select the maximum from value
309 * for a time scale.
310 *
311 * @see utms_getTimeScaleValue
312 *
313 * @draft ICU 3.2
314 */
315 UTSV_FROM_MAX_VALUE,
316
317 /**
318 * The constant used to select the minimum to value
319 * for a time scale.
320 *
321 * @see utms_getTimeScaleValue
322 *
323 * @draft ICU 3.2
324 */
325 UTSV_TO_MIN_VALUE,
326
327 /**
328 * The constant used to select the maximum to value
329 * for a time scale.
330 *
331 * @see utms_getTimeScaleValue
332 *
333 * @draft ICU 3.2
334 */
335 UTSV_TO_MAX_VALUE,
336
337 /**
338 * The constant used to select the epoch plus one value
339 * for a time scale.
340 *
341 * NOTE: This is an internal value. DO NOT USE IT. May not
342 * actually be equal to the epoch offset value plus one.
343 *
344 * @see utms_getTimeScaleValue
345 *
346 * @draft ICU 3.2
347 */
348 UTSV_EPOCH_OFFSET_PLUS_1_VALUE,
349
350 /**
351 * The constant used to select the epoch plus one value
352 * for a time scale.
353 *
354 * NOTE: This is an internal value. DO NOT USE IT. May not
355 * actually be equal to the epoch offset value plus one.
356 *
357 * @see utms_getTimeScaleValue
358 *
359 * @draft ICU 3.2
360 */
361 UTSV_EPOCH_OFFSET_MINUS_1_VALUE,
362
363 /**
364 * The constant used to select the units round value
365 * for a time scale.
366 *
367 * NOTE: This is an internal value. DO NOT USE IT.
368 *
369 * @see utms_getTimeScaleValue
370 *
371 * @internal
372 */
373 UTSV_UNITS_ROUND_VALUE,
374
375 /**
376 * The constant used to select the minimum safe rounding value
377 * for a time scale.
378 *
379 * NOTE: This is an internal value. DO NOT USE IT.
380 *
381 * @see utms_getTimeScaleValue
382 *
383 * @internal
384 */
385 UTSV_MIN_ROUND_VALUE,
386
387 /**
388 * The constant used to select the maximum safe rounding value
389 * for a time scale.
390 *
391 * NOTE: This is an internal value. DO NOT USE IT.
392 *
393 * @see utms_getTimeScaleValue
394 *
395 * @internal
396 */
397 UTSV_MAX_ROUND_VALUE,
398
399 /**
400 * The number of time scale values.
401 *
402 * NOTE: This is an internal value. DO NOT USE IT.
403 *
404 * @see utms_getTimeScaleValue
405 *
406 * @internal
407 */
408 UTSV_MAX_SCALE_VALUE
409} UTimeScaleValue;
410
411/**
412 * Get a value associated with a particular time scale.
413 *
414 * @param timeScale The time scale
415 * @param value A constant representing the value to get
416 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if arguments are invalid.
417 * @return - the value.
418 *
419 * @draft ICU 3.2
420 */
421U_DRAFT int64_t U_EXPORT2
422 utmscale_getTimeScaleValue(UDateTimeScale timeScale, UTimeScaleValue value, UErrorCode *status);
423
424/* Conversion to 'universal time scale' */
425
426/**
427 * Convert a <code>int64_t</code> datetime from the given time scale to the universal time scale.
428 *
429 * @param otherTime The <code>int64_t</code> datetime
430 * @param timeScale The time scale to convert from
431 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range.
432 *
433 * @return The datetime converted to the universal time scale
434 *
435 * @draft ICU 3.2
436 */
437U_DRAFT int64_t U_EXPORT2
438 utmscale_fromInt64(int64_t otherTime, UDateTimeScale timeScale, UErrorCode *status);
439
440/* Conversion from 'universal time scale' */
441
442/**
443 * Convert a datetime from the universal time scale to a <code>int64_t</code> in the given time scale.
444 *
445 * @param universalTime The datetime in the universal time scale
446 * @param timeScale The time scale to convert to
447 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range.
448 *
449 * @return The datetime converted to the given time scale
450 *
451 * @draft ICU 3.2
452 */
453U_DRAFT int64_t U_EXPORT2
454 utmscale_toInt64(int64_t universalTime, UDateTimeScale timeScale, UErrorCode *status);
455
456#endif /* #if !UCONFIG_NO_FORMATTING */
457
458#endif
459