Home | History | Annotate | Download | only in unicode
      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  */
    202 typedef 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  */
    298 typedef 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  */
    443 U_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  */
    459 U_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  */
    475 U_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