|
||||
File indexing completed on 2025-01-18 10:13:16
0001 // © 2016 and later: Unicode, Inc. and others. 0002 // License & terms of use: http://www.unicode.org/copyright.html 0003 /* 0004 ******************************************************************************* 0005 * Copyright (C) 2004 - 2008, International Business Machines Corporation and 0006 * others. All Rights Reserved. 0007 ******************************************************************************* 0008 */ 0009 0010 #ifndef UTMSCALE_H 0011 #define UTMSCALE_H 0012 0013 #include "unicode/utypes.h" 0014 0015 #if !UCONFIG_NO_FORMATTING 0016 0017 /** 0018 * \file 0019 * \brief C API: Universal Time Scale 0020 * 0021 * There are quite a few different conventions for binary datetime, depending on different 0022 * platforms and protocols. Some of these have severe drawbacks. For example, people using 0023 * Unix time (seconds since Jan 1, 1970) think that they are safe until near the year 2038. 0024 * But cases can and do arise where arithmetic manipulations causes serious problems. Consider 0025 * the computation of the average of two datetimes, for example: if one calculates them with 0026 * <code>averageTime = (time1 + time2)/2</code>, there will be overflow even with dates 0027 * around the present. Moreover, even if these problems don't occur, there is the issue of 0028 * conversion back and forth between different systems. 0029 * 0030 * <p> 0031 * Binary datetimes differ in a number of ways: the datatype, the unit, 0032 * and the epoch (origin). We'll refer to these as time scales. For example: 0033 * 0034 * <table border="1" cellspacing="0" cellpadding="4"> 0035 * <caption>Table 1: Binary Time Scales</caption> 0036 * <tr> 0037 * <th align="left">Source</th> 0038 * <th align="left">Datatype</th> 0039 * <th align="left">Unit</th> 0040 * <th align="left">Epoch</th> 0041 * </tr> 0042 * 0043 * <tr> 0044 * <td>UDTS_JAVA_TIME</td> 0045 * <td>int64_t</td> 0046 * <td>milliseconds</td> 0047 * <td>Jan 1, 1970</td> 0048 * </tr> 0049 * <tr> 0050 * 0051 * <td>UDTS_UNIX_TIME</td> 0052 * <td>int32_t or int64_t</td> 0053 * <td>seconds</td> 0054 * <td>Jan 1, 1970</td> 0055 * </tr> 0056 * <tr> 0057 * <td>UDTS_ICU4C_TIME</td> 0058 * 0059 * <td>double</td> 0060 * <td>milliseconds</td> 0061 * <td>Jan 1, 1970</td> 0062 * </tr> 0063 * <tr> 0064 * <td>UDTS_WINDOWS_FILE_TIME</td> 0065 * <td>int64_t</td> 0066 * 0067 * <td>ticks (100 nanoseconds)</td> 0068 * <td>Jan 1, 1601</td> 0069 * </tr> 0070 * <tr> 0071 * <td>UDTS_DOTNET_DATE_TIME</td> 0072 * <td>int64_t</td> 0073 * <td>ticks (100 nanoseconds)</td> 0074 * 0075 * <td>Jan 1, 0001</td> 0076 * </tr> 0077 * <tr> 0078 * <td>UDTS_MAC_OLD_TIME</td> 0079 * <td>int32_t or int64_t</td> 0080 * <td>seconds</td> 0081 * <td>Jan 1, 1904</td> 0082 * 0083 * </tr> 0084 * <tr> 0085 * <td>UDTS_MAC_TIME</td> 0086 * <td>double</td> 0087 * <td>seconds</td> 0088 * <td>Jan 1, 2001</td> 0089 * </tr> 0090 * 0091 * <tr> 0092 * <td>UDTS_EXCEL_TIME</td> 0093 * <td>?</td> 0094 * <td>days</td> 0095 * <td>Dec 31, 1899</td> 0096 * </tr> 0097 * <tr> 0098 * 0099 * <td>UDTS_DB2_TIME</td> 0100 * <td>?</td> 0101 * <td>days</td> 0102 * <td>Dec 31, 1899</td> 0103 * </tr> 0104 * 0105 * <tr> 0106 * <td>UDTS_UNIX_MICROSECONDS_TIME</td> 0107 * <td>int64_t</td> 0108 * <td>microseconds</td> 0109 * <td>Jan 1, 1970</td> 0110 * </tr> 0111 * </table> 0112 * 0113 * <p> 0114 * All of the epochs start at 00:00 am (the earliest possible time on the day in question), 0115 * and are assumed to be UTC. 0116 * 0117 * <p> 0118 * The ranges for different datatypes are given in the following table (all values in years). 0119 * The range of years includes the entire range expressible with positive and negative 0120 * values of the datatype. The range of years for double is the range that would be allowed 0121 * without losing precision to the corresponding unit. 0122 * 0123 * <table border="1" cellspacing="0" cellpadding="4"> 0124 * <tr> 0125 * <th align="left">Units</th> 0126 * <th align="left">int64_t</th> 0127 * <th align="left">double</th> 0128 * <th align="left">int32_t</th> 0129 * </tr> 0130 * 0131 * <tr> 0132 * <td>1 sec</td> 0133 * <td align="right">5.84542x10<sup>11</sup></td> 0134 * <td align="right">285,420,920.94</td> 0135 * <td align="right">136.10</td> 0136 * </tr> 0137 * <tr> 0138 * 0139 * <td>1 millisecond</td> 0140 * <td align="right">584,542,046.09</td> 0141 * <td align="right">285,420.92</td> 0142 * <td align="right">0.14</td> 0143 * </tr> 0144 * <tr> 0145 * <td>1 microsecond</td> 0146 * 0147 * <td align="right">584,542.05</td> 0148 * <td align="right">285.42</td> 0149 * <td align="right">0.00</td> 0150 * </tr> 0151 * <tr> 0152 * <td>100 nanoseconds (tick)</td> 0153 * <td align="right">58,454.20</td> 0154 * <td align="right">28.54</td> 0155 * <td align="right">0.00</td> 0156 * </tr> 0157 * <tr> 0158 * <td>1 nanosecond</td> 0159 * <td align="right">584.5420461</td> 0160 * <td align="right">0.2854</td> 0161 * <td align="right">0.00</td> 0162 * </tr> 0163 * </table> 0164 * 0165 * <p> 0166 * These functions implement a universal time scale which can be used as a 'pivot', 0167 * and provide conversion functions to and from all other major time scales. 0168 * This datetimes to be converted to the pivot time, safely manipulated, 0169 * and converted back to any other datetime time scale. 0170 * 0171 *<p> 0172 * So what to use for this pivot? Java time has plenty of range, but cannot represent 0173 * .NET <code>System.DateTime</code> values without severe loss of precision. ICU4C time addresses this by using a 0174 * <code>double</code> that is otherwise equivalent to the Java time. However, there are disadvantages 0175 * with <code>doubles</code>. They provide for much more graceful degradation in arithmetic operations. 0176 * But they only have 53 bits of accuracy, which means that they will lose precision when 0177 * converting back and forth to ticks. What would really be nice would be a 0178 * <code>long double</code> (80 bits -- 64 bit mantissa), but that is not supported on most systems. 0179 * 0180 *<p> 0181 * The Unix extended time uses a structure with two components: time in seconds and a 0182 * fractional field (microseconds). However, this is clumsy, slow, and 0183 * prone to error (you always have to keep track of overflow and underflow in the 0184 * fractional field). <code>BigDecimal</code> would allow for arbitrary precision and arbitrary range, 0185 * but we do not want to use this as the normal type, because it is slow and does not 0186 * have a fixed size. 0187 * 0188 *<p> 0189 * Because of these issues, we ended up concluding that the .NET framework's 0190 * <code>System.DateTime</code> would be the best pivot. However, we use the full range 0191 * allowed by the datatype, allowing for datetimes back to 29,000 BC and up to 29,000 AD. 0192 * This time scale is very fine grained, does not lose precision, and covers a range that 0193 * will meet almost all requirements. It will not handle the range that Java times do, 0194 * but frankly, being able to handle dates before 29,000 BC or after 29,000 AD is of very limited interest. 0195 * 0196 */ 0197 0198 /** 0199 * <code>UDateTimeScale</code> values are used to specify the time scale used for 0200 * conversion into or out if the universal time scale. 0201 * 0202 * @stable ICU 3.2 0203 */ 0204 typedef enum UDateTimeScale { 0205 /** 0206 * Used in the JDK. Data is a Java <code>long</code> (<code>int64_t</code>). Value 0207 * is milliseconds since January 1, 1970. 0208 * 0209 * @stable ICU 3.2 0210 */ 0211 UDTS_JAVA_TIME = 0, 0212 0213 /** 0214 * Used on Unix systems. Data is <code>int32_t</code> or <code>int64_t</code>. Value 0215 * is seconds since January 1, 1970. 0216 * 0217 * @stable ICU 3.2 0218 */ 0219 UDTS_UNIX_TIME, 0220 0221 /** 0222 * Used in IUC4C. Data is a <code>double</code>. Value 0223 * is milliseconds since January 1, 1970. 0224 * 0225 * @stable ICU 3.2 0226 */ 0227 UDTS_ICU4C_TIME, 0228 0229 /** 0230 * Used in Windows for file times. Data is an <code>int64_t</code>. Value 0231 * is ticks (1 tick == 100 nanoseconds) since January 1, 1601. 0232 * 0233 * @stable ICU 3.2 0234 */ 0235 UDTS_WINDOWS_FILE_TIME, 0236 0237 /** 0238 * Used in the .NET framework's <code>System.DateTime</code> structure. Data is an <code>int64_t</code>. Value 0239 * is ticks (1 tick == 100 nanoseconds) since January 1, 0001. 0240 * 0241 * @stable ICU 3.2 0242 */ 0243 UDTS_DOTNET_DATE_TIME, 0244 0245 /** 0246 * Used in older Macintosh systems. Data is <code>int32_t</code> or <code>int64_t</code>. Value 0247 * is seconds since January 1, 1904. 0248 * 0249 * @stable ICU 3.2 0250 */ 0251 UDTS_MAC_OLD_TIME, 0252 0253 /** 0254 * Used in newer Macintosh systems. Data is a <code>double</code>. Value 0255 * is seconds since January 1, 2001. 0256 * 0257 * @stable ICU 3.2 0258 */ 0259 UDTS_MAC_TIME, 0260 0261 /** 0262 * Used in Excel. Data is an <code>?unknown?</code>. Value 0263 * is days since December 31, 1899. 0264 * 0265 * @stable ICU 3.2 0266 */ 0267 UDTS_EXCEL_TIME, 0268 0269 /** 0270 * Used in DB2. Data is an <code>?unknown?</code>. Value 0271 * is days since December 31, 1899. 0272 * 0273 * @stable ICU 3.2 0274 */ 0275 UDTS_DB2_TIME, 0276 0277 /** 0278 * Data is a <code>long</code>. Value is microseconds since January 1, 1970. 0279 * Similar to Unix time (linear value from 1970) and struct timeval 0280 * (microseconds resolution). 0281 * 0282 * @stable ICU 3.8 0283 */ 0284 UDTS_UNIX_MICROSECONDS_TIME, 0285 0286 #ifndef U_HIDE_DEPRECATED_API 0287 /** 0288 * The first unused time scale value. The limit of this enum 0289 * @deprecated ICU 59 The numeric value may change over time, see ICU ticket #12420. 0290 */ 0291 UDTS_MAX_SCALE 0292 #endif /* U_HIDE_DEPRECATED_API */ 0293 0294 } UDateTimeScale; 0295 0296 /** 0297 * <code>UTimeScaleValue</code> values are used to specify the time scale values 0298 * to <code>utmscale_getTimeScaleValue</code>. 0299 * 0300 * @see utmscale_getTimeScaleValue 0301 * 0302 * @stable ICU 3.2 0303 */ 0304 typedef enum UTimeScaleValue { 0305 /** 0306 * The constant used to select the units vale 0307 * for a time scale. 0308 * 0309 * @see utmscale_getTimeScaleValue 0310 * 0311 * @stable ICU 3.2 0312 */ 0313 UTSV_UNITS_VALUE = 0, 0314 0315 /** 0316 * The constant used to select the epoch offset value 0317 * for a time scale. 0318 * 0319 * @see utmscale_getTimeScaleValue 0320 * 0321 * @stable ICU 3.2 0322 */ 0323 UTSV_EPOCH_OFFSET_VALUE=1, 0324 0325 /** 0326 * The constant used to select the minimum from value 0327 * for a time scale. 0328 * 0329 * @see utmscale_getTimeScaleValue 0330 * 0331 * @stable ICU 3.2 0332 */ 0333 UTSV_FROM_MIN_VALUE=2, 0334 0335 /** 0336 * The constant used to select the maximum from value 0337 * for a time scale. 0338 * 0339 * @see utmscale_getTimeScaleValue 0340 * 0341 * @stable ICU 3.2 0342 */ 0343 UTSV_FROM_MAX_VALUE=3, 0344 0345 /** 0346 * The constant used to select the minimum to value 0347 * for a time scale. 0348 * 0349 * @see utmscale_getTimeScaleValue 0350 * 0351 * @stable ICU 3.2 0352 */ 0353 UTSV_TO_MIN_VALUE=4, 0354 0355 /** 0356 * The constant used to select the maximum to value 0357 * for a time scale. 0358 * 0359 * @see utmscale_getTimeScaleValue 0360 * 0361 * @stable ICU 3.2 0362 */ 0363 UTSV_TO_MAX_VALUE=5, 0364 0365 #ifndef U_HIDE_INTERNAL_API 0366 /** 0367 * The constant used to select the epoch plus one value 0368 * for a time scale. 0369 * 0370 * NOTE: This is an internal value. DO NOT USE IT. May not 0371 * actually be equal to the epoch offset value plus one. 0372 * 0373 * @see utmscale_getTimeScaleValue 0374 * 0375 * @internal ICU 3.2 0376 */ 0377 UTSV_EPOCH_OFFSET_PLUS_1_VALUE=6, 0378 0379 /** 0380 * The constant used to select the epoch plus one value 0381 * for a time scale. 0382 * 0383 * NOTE: This is an internal value. DO NOT USE IT. May not 0384 * actually be equal to the epoch offset value plus one. 0385 * 0386 * @see utmscale_getTimeScaleValue 0387 * 0388 * @internal ICU 3.2 0389 */ 0390 UTSV_EPOCH_OFFSET_MINUS_1_VALUE=7, 0391 0392 /** 0393 * The constant used to select the units round value 0394 * for a time scale. 0395 * 0396 * NOTE: This is an internal value. DO NOT USE IT. 0397 * 0398 * @see utmscale_getTimeScaleValue 0399 * 0400 * @internal ICU 3.2 0401 */ 0402 UTSV_UNITS_ROUND_VALUE=8, 0403 0404 /** 0405 * The constant used to select the minimum safe rounding value 0406 * for a time scale. 0407 * 0408 * NOTE: This is an internal value. DO NOT USE IT. 0409 * 0410 * @see utmscale_getTimeScaleValue 0411 * 0412 * @internal ICU 3.2 0413 */ 0414 UTSV_MIN_ROUND_VALUE=9, 0415 0416 /** 0417 * The constant used to select the maximum safe rounding value 0418 * for a time scale. 0419 * 0420 * NOTE: This is an internal value. DO NOT USE IT. 0421 * 0422 * @see utmscale_getTimeScaleValue 0423 * 0424 * @internal ICU 3.2 0425 */ 0426 UTSV_MAX_ROUND_VALUE=10, 0427 0428 #endif /* U_HIDE_INTERNAL_API */ 0429 0430 #ifndef U_HIDE_DEPRECATED_API 0431 /** 0432 * The number of time scale values, in other words limit of this enum. 0433 * 0434 * @see utmscale_getTimeScaleValue 0435 * @deprecated ICU 59 The numeric value may change over time, see ICU ticket #12420. 0436 */ 0437 UTSV_MAX_SCALE_VALUE=11 0438 #endif /* U_HIDE_DEPRECATED_API */ 0439 0440 } UTimeScaleValue; 0441 0442 /** 0443 * Get a value associated with a particular time scale. 0444 * 0445 * @param timeScale The time scale 0446 * @param value A constant representing the value to get 0447 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if arguments are invalid. 0448 * @return - the value. 0449 * 0450 * @stable ICU 3.2 0451 */ 0452 U_CAPI int64_t U_EXPORT2 0453 utmscale_getTimeScaleValue(UDateTimeScale timeScale, UTimeScaleValue value, UErrorCode *status); 0454 0455 /* Conversion to 'universal time scale' */ 0456 0457 /** 0458 * Convert a <code>int64_t</code> datetime from the given time scale to the universal time scale. 0459 * 0460 * @param otherTime The <code>int64_t</code> datetime 0461 * @param timeScale The time scale to convert from 0462 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range. 0463 * 0464 * @return The datetime converted to the universal time scale 0465 * 0466 * @stable ICU 3.2 0467 */ 0468 U_CAPI int64_t U_EXPORT2 0469 utmscale_fromInt64(int64_t otherTime, UDateTimeScale timeScale, UErrorCode *status); 0470 0471 /* Conversion from 'universal time scale' */ 0472 0473 /** 0474 * Convert a datetime from the universal time scale to a <code>int64_t</code> in the given time scale. 0475 * 0476 * @param universalTime The datetime in the universal time scale 0477 * @param timeScale The time scale to convert to 0478 * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range. 0479 * 0480 * @return The datetime converted to the given time scale 0481 * 0482 * @stable ICU 3.2 0483 */ 0484 U_CAPI int64_t U_EXPORT2 0485 utmscale_toInt64(int64_t universalTime, UDateTimeScale timeScale, UErrorCode *status); 0486 0487 #endif /* #if !UCONFIG_NO_FORMATTING */ 0488 0489 #endif 0490
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |