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