1/* 2******************************************************************************* 3* Copyright (C) 2004 - 2008, 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>UDTS_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>UDTS_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>UDTS_ICU4C_TIME</td> 56 * 57 * <td>double</td> 58 * <td>milliseconds</td> 59 * <td>Jan 1, 1970</td> 60 * </tr> 61 * <tr> 62 * <td>UDTS_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>UDTS_DOTNET_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>UDTS_MAC_OLD_TIME</td> 77 * <td>int32_t or int64_t</td> 78 * <td>seconds</td> 79 * <td>Jan 1, 1904</td> 80 * 81 * </tr> 82 * <tr> 83 * <td>UDTS_MAC_TIME</td> 84 * <td>double</td> 85 * <td>seconds</td> 86 * <td>Jan 1, 2001</td> 87 * </tr> 88 * 89 * <tr> 90 * <td>UDTS_EXCEL_TIME</td> 91 * <td>?</td> 92 * <td>days</td> 93 * <td>Dec 31, 1899</td> 94 * </tr> 95 * <tr> 96 * 97 * <td>UDTS_DB2_TIME</td> 98 * <td>?</td> 99 * <td>days</td> 100 * <td>Dec 31, 1899</td> 101 * </tr> 102 * 103 * <tr> 104 * <td>UDTS_UNIX_MICROSECONDS_TIME</td> 105 * <td>int64_t</td> 106 * <td>microseconds</td> 107 * <td>Jan 1, 1970</td> 108 * </tr> 109 * </table> 110 * 111 * <p> 112 * All of the epochs start at 00:00 am (the earliest possible time on the day in question), 113 * and are assumed to be UTC. 114 * 115 * <p> 116 * The ranges for different datatypes are given in the following table (all values in years). 117 * The range of years includes the entire range expressible with positive and negative 118 * values of the datatype. The range of years for double is the range that would be allowed 119 * without losing precision to the corresponding unit. 120 * 121 * <table border="1" cellspacing="0" cellpadding="4"> 122 * <tr> 123 * <th align="left">Units</th> 124 * <th align="left">int64_t</th> 125 * <th align="left">double</th> 126 * <th align="left">int32_t</th> 127 * </tr> 128 * 129 * <tr> 130 * <td>1 sec</td> 131 * <td align="right">5.84542x10<sup>11</sup></td> 132 * <td align="right">285,420,920.94</td> 133 * <td align="right">136.10</td> 134 * </tr> 135 * <tr> 136 * 137 * <td>1 millisecond</td> 138 * <td align="right">584,542,046.09</td> 139 * <td align="right">285,420.92</td> 140 * <td align="right">0.14</td> 141 * </tr> 142 * <tr> 143 * <td>1 microsecond</td> 144 * 145 * <td align="right">584,542.05</td> 146 * <td align="right">285.42</td> 147 * <td align="right">0.00</td> 148 * </tr> 149 * <tr> 150 * <td>100 nanoseconds (tick)</td> 151 * <td align="right">58,454.20</td> 152 * <td align="right">28.54</td> 153 * <td align="right">0.00</td> 154 * </tr> 155 * <tr> 156 * <td>1 nanosecond</td> 157 * <td align="right">584.5420461</td> 158 * <td align="right">0.2854</td> 159 * <td align="right">0.00</td> 160 * </tr> 161 * </table> 162 * 163 * <p> 164 * These functions implement a universal time scale which can be used as a 'pivot', 165 * and provide conversion functions to and from all other major time scales. 166 * This datetimes to be converted to the pivot time, safely manipulated, 167 * and converted back to any other datetime time scale. 168 * 169 *<p> 170 * So what to use for this pivot? Java time has plenty of range, but cannot represent 171 * .NET <code>System.DateTime</code> values without severe loss of precision. ICU4C time addresses this by using a 172 * <code>double</code> that is otherwise equivalent to the Java time. However, there are disadvantages 173 * with <code>doubles</code>. They provide for much more graceful degradation in arithmetic operations. 174 * But they only have 53 bits of accuracy, which means that they will lose precision when 175 * converting back and forth to ticks. What would really be nice would be a 176 * <code>long double</code> (80 bits -- 64 bit mantissa), but that is not supported on most systems. 177 * 178 *<p> 179 * The Unix extended time uses a structure with two components: time in seconds and a 180 * fractional field (microseconds). However, this is clumsy, slow, and 181 * prone to error (you always have to keep track of overflow and underflow in the 182 * fractional field). <code>BigDecimal</code> would allow for arbitrary precision and arbitrary range, 183 * but we do not want to use this as the normal type, because it is slow and does not 184 * have a fixed size. 185 * 186 *<p> 187 * Because of these issues, we ended up concluding that the .NET framework's 188 * <code>System.DateTime</code> would be the best pivot. However, we use the full range 189 * allowed by the datatype, allowing for datetimes back to 29,000 BC and up to 29,000 AD. 190 * This time scale is very fine grained, does not lose precision, and covers a range that 191 * will meet almost all requirements. It will not handle the range that Java times do, 192 * but frankly, being able to handle dates before 29,000 BC or after 29,000 AD is of very limited interest. 193 * 194 */ 195 196/** 197 * <code>UDateTimeScale</code> values are used to specify the time scale used for 198 * conversion into or out if the universal time scale. 199 * 200 * @stable ICU 3.2 201 */ 202typedef enum UDateTimeScale { 203 /** 204 * Used in the JDK. Data is a Java <code>long</code> (<code>int64_t</code>). Value 205 * is milliseconds since January 1, 1970. 206 * 207 * @stable ICU 3.2 208 */ 209 UDTS_JAVA_TIME = 0, 210 211 /** 212 * Used on Unix systems. Data is <code>int32_t</code> or <code>int64_t</code>. Value 213 * is seconds since January 1, 1970. 214 * 215 * @stable ICU 3.2 216 */ 217 UDTS_UNIX_TIME, 218 219 /** 220 * Used in IUC4C. Data is a <code>double</code>. Value 221 * is milliseconds since January 1, 1970. 222 * 223 * @stable ICU 3.2 224 */ 225 UDTS_ICU4C_TIME, 226 227 /** 228 * Used in Windows for file times. Data is an <code>int64_t</code>. Value 229 * is ticks (1 tick == 100 nanoseconds) since January 1, 1601. 230 * 231 * @stable ICU 3.2 232 */ 233 UDTS_WINDOWS_FILE_TIME, 234 235 /** 236 * Used in the .NET framework's <code>System.DateTime</code> structure. Data is an <code>int64_t</code>. Value 237 * is ticks (1 tick == 100 nanoseconds) since January 1, 0001. 238 * 239 * @stable ICU 3.2 240 */ 241 UDTS_DOTNET_DATE_TIME, 242 243 /** 244 * Used in older Macintosh systems. Data is <code>int32_t</code> or <code>int64_t</code>. Value 245 * is seconds since January 1, 1904. 246 * 247 * @stable ICU 3.2 248 */ 249 UDTS_MAC_OLD_TIME, 250 251 /** 252 * Used in newer Macintosh systems. Data is a <code>double</code>. Value 253 * is seconds since January 1, 2001. 254 * 255 * @stable ICU 3.2 256 */ 257 UDTS_MAC_TIME, 258 259 /** 260 * Used in Excel. Data is an <code>?unknown?</code>. Value 261 * is days since December 31, 1899. 262 * 263 * @stable ICU 3.2 264 */ 265 UDTS_EXCEL_TIME, 266 267 /** 268 * Used in DB2. Data is an <code>?unknown?</code>. Value 269 * is days since December 31, 1899. 270 * 271 * @stable ICU 3.2 272 */ 273 UDTS_DB2_TIME, 274 275 /** 276 * Data is a <code>long</code>. Value is microseconds since January 1, 1970. 277 * Similar to Unix time (linear value from 1970) and struct timeval 278 * (microseconds resolution). 279 * 280 * @stable ICU 3.8 281 */ 282 UDTS_UNIX_MICROSECONDS_TIME, 283 284 /** 285 * The first unused time scale value. The limit of this enum 286 */ 287 UDTS_MAX_SCALE 288} UDateTimeScale; 289 290/** 291 * <code>UTimeScaleValue</code> values are used to specify the time scale values 292 * to <code>utmscale_getTimeScaleValue</code>. 293 * 294 * @see utmscale_getTimeScaleValue 295 * 296 * @stable ICU 3.2 297 */ 298typedef enum UTimeScaleValue { 299 /** 300 * The constant used to select the units vale 301 * for a time scale. 302 * 303 * @see utmscale_getTimeScaleValue 304 * 305 * @stable ICU 3.2 306 */ 307 UTSV_UNITS_VALUE = 0, 308 309 /** 310 * The constant used to select the epoch offset value 311 * for a time scale. 312 * 313 * @see utmscale_getTimeScaleValue 314 * 315 * @stable ICU 3.2 316 */ 317 UTSV_EPOCH_OFFSET_VALUE=1, 318 319 /** 320 * The constant used to select the minimum from value 321 * for a time scale. 322 * 323 * @see utmscale_getTimeScaleValue 324 * 325 * @stable ICU 3.2 326 */ 327 UTSV_FROM_MIN_VALUE=2, 328 329 /** 330 * The constant used to select the maximum from value 331 * for a time scale. 332 * 333 * @see utmscale_getTimeScaleValue 334 * 335 * @stable ICU 3.2 336 */ 337 UTSV_FROM_MAX_VALUE=3, 338 339 /** 340 * The constant used to select the minimum to value 341 * for a time scale. 342 * 343 * @see utmscale_getTimeScaleValue 344 * 345 * @stable ICU 3.2 346 */ 347 UTSV_TO_MIN_VALUE=4, 348 349 /** 350 * The constant used to select the maximum to value 351 * for a time scale. 352 * 353 * @see utmscale_getTimeScaleValue 354 * 355 * @stable ICU 3.2 356 */ 357 UTSV_TO_MAX_VALUE=5, 358 359#ifndef U_HIDE_INTERNAL_API 360 /** 361 * The constant used to select the epoch plus one value 362 * for a time scale. 363 * 364 * NOTE: This is an internal value. DO NOT USE IT. May not 365 * actually be equal to the epoch offset value plus one. 366 * 367 * @see utmscale_getTimeScaleValue 368 * 369 * @internal ICU 3.2 370 */ 371 UTSV_EPOCH_OFFSET_PLUS_1_VALUE=6, 372 373 /** 374 * The constant used to select the epoch plus one value 375 * for a time scale. 376 * 377 * NOTE: This is an internal value. DO NOT USE IT. May not 378 * actually be equal to the epoch offset value plus one. 379 * 380 * @see utmscale_getTimeScaleValue 381 * 382 * @internal ICU 3.2 383 */ 384 UTSV_EPOCH_OFFSET_MINUS_1_VALUE=7, 385 386 /** 387 * The constant used to select the units round value 388 * for a time scale. 389 * 390 * NOTE: This is an internal value. DO NOT USE IT. 391 * 392 * @see utmscale_getTimeScaleValue 393 * 394 * @internal ICU 3.2 395 */ 396 UTSV_UNITS_ROUND_VALUE=8, 397 398 /** 399 * The constant used to select the minimum safe rounding value 400 * for a time scale. 401 * 402 * NOTE: This is an internal value. DO NOT USE IT. 403 * 404 * @see utmscale_getTimeScaleValue 405 * 406 * @internal ICU 3.2 407 */ 408 UTSV_MIN_ROUND_VALUE=9, 409 410 /** 411 * The constant used to select the maximum safe rounding value 412 * for a time scale. 413 * 414 * NOTE: This is an internal value. DO NOT USE IT. 415 * 416 * @see utmscale_getTimeScaleValue 417 * 418 * @internal ICU 3.2 419 */ 420 UTSV_MAX_ROUND_VALUE=10, 421 422#endif /* U_HIDE_INTERNAL_API */ 423 424 /** 425 * The number of time scale values, in other words limit of this enum. 426 * 427 * @see utmscale_getTimeScaleValue 428 */ 429 UTSV_MAX_SCALE_VALUE=11 430 431} UTimeScaleValue; 432 433/** 434 * Get a value associated with a particular time scale. 435 * 436 * @param timeScale The time scale 437 * @param value A constant representing the value to get 438 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if arguments are invalid. 439 * @return - the value. 440 * 441 * @stable ICU 3.2 442 */ 443U_STABLE int64_t U_EXPORT2 444 utmscale_getTimeScaleValue(UDateTimeScale timeScale, UTimeScaleValue value, UErrorCode *status); 445 446/* Conversion to 'universal time scale' */ 447 448/** 449 * Convert a <code>int64_t</code> datetime from the given time scale to the universal time scale. 450 * 451 * @param otherTime The <code>int64_t</code> datetime 452 * @param timeScale The time scale to convert from 453 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range. 454 * 455 * @return The datetime converted to the universal time scale 456 * 457 * @stable ICU 3.2 458 */ 459U_STABLE int64_t U_EXPORT2 460 utmscale_fromInt64(int64_t otherTime, UDateTimeScale timeScale, UErrorCode *status); 461 462/* Conversion from 'universal time scale' */ 463 464/** 465 * Convert a datetime from the universal time scale to a <code>int64_t</code> in the given time scale. 466 * 467 * @param universalTime The datetime in the universal time scale 468 * @param timeScale The time scale to convert to 469 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range. 470 * 471 * @return The datetime converted to the given time scale 472 * 473 * @stable ICU 3.2 474 */ 475U_STABLE int64_t U_EXPORT2 476 utmscale_toInt64(int64_t universalTime, UDateTimeScale timeScale, UErrorCode *status); 477 478#endif /* #if !UCONFIG_NO_FORMATTING */ 479 480#endif 481 482