Home | History | Annotate | Download | only in unicode
      1 //  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 #ifndef U_HIDE_DEPRECATED_API
    287     /**
    288      * The first unused time scale value. The limit of this enum
    289      * @deprecated ICU 59 The numeric value may change over time, see ICU ticket #12420.
    290      */
    291     UDTS_MAX_SCALE
    292 #endif  /* U_HIDE_DEPRECATED_API */
    293 
    294 } UDateTimeScale;
    295 
    296 /**
    297  * <code>UTimeScaleValue</code> values are used to specify the time scale values
    298  * to <code>utmscale_getTimeScaleValue</code>.
    299  *
    300  * @see utmscale_getTimeScaleValue
    301  *
    302  * @stable ICU 3.2
    303  */
    304 typedef enum UTimeScaleValue {
    305     /**
    306      * The constant used to select the units vale
    307      * for a time scale.
    308      *
    309      * @see utmscale_getTimeScaleValue
    310      *
    311      * @stable ICU 3.2
    312      */
    313     UTSV_UNITS_VALUE = 0,
    314 
    315     /**
    316      * The constant used to select the epoch offset value
    317      * for a time scale.
    318      *
    319      * @see utmscale_getTimeScaleValue
    320      *
    321      * @stable ICU 3.2
    322      */
    323     UTSV_EPOCH_OFFSET_VALUE=1,
    324 
    325     /**
    326      * The constant used to select the minimum from value
    327      * for a time scale.
    328      *
    329      * @see utmscale_getTimeScaleValue
    330      *
    331      * @stable ICU 3.2
    332      */
    333     UTSV_FROM_MIN_VALUE=2,
    334 
    335     /**
    336      * The constant used to select the maximum from value
    337      * for a time scale.
    338      *
    339      * @see utmscale_getTimeScaleValue
    340      *
    341      * @stable ICU 3.2
    342      */
    343     UTSV_FROM_MAX_VALUE=3,
    344 
    345     /**
    346      * The constant used to select the minimum to value
    347      * for a time scale.
    348      *
    349      * @see utmscale_getTimeScaleValue
    350      *
    351      * @stable ICU 3.2
    352      */
    353     UTSV_TO_MIN_VALUE=4,
    354 
    355     /**
    356      * The constant used to select the maximum to value
    357      * for a time scale.
    358      *
    359      * @see utmscale_getTimeScaleValue
    360      *
    361      * @stable ICU 3.2
    362      */
    363     UTSV_TO_MAX_VALUE=5,
    364 
    365 #ifndef U_HIDE_INTERNAL_API
    366     /**
    367      * The constant used to select the epoch plus one value
    368      * for a time scale.
    369      *
    370      * NOTE: This is an internal value. DO NOT USE IT. May not
    371      * actually be equal to the epoch offset value plus one.
    372      *
    373      * @see utmscale_getTimeScaleValue
    374      *
    375      * @internal ICU 3.2
    376      */
    377     UTSV_EPOCH_OFFSET_PLUS_1_VALUE=6,
    378 
    379     /**
    380      * The constant used to select the epoch plus one value
    381      * for a time scale.
    382      *
    383      * NOTE: This is an internal value. DO NOT USE IT. May not
    384      * actually be equal to the epoch offset value plus one.
    385      *
    386      * @see utmscale_getTimeScaleValue
    387      *
    388      * @internal ICU 3.2
    389      */
    390     UTSV_EPOCH_OFFSET_MINUS_1_VALUE=7,
    391 
    392     /**
    393      * The constant used to select the units round value
    394      * for a time scale.
    395      *
    396      * NOTE: This is an internal value. DO NOT USE IT.
    397      *
    398      * @see utmscale_getTimeScaleValue
    399      *
    400      * @internal ICU 3.2
    401      */
    402     UTSV_UNITS_ROUND_VALUE=8,
    403 
    404     /**
    405      * The constant used to select the minimum safe rounding value
    406      * for a time scale.
    407      *
    408      * NOTE: This is an internal value. DO NOT USE IT.
    409      *
    410      * @see utmscale_getTimeScaleValue
    411      *
    412      * @internal ICU 3.2
    413      */
    414     UTSV_MIN_ROUND_VALUE=9,
    415 
    416     /**
    417      * The constant used to select the maximum safe rounding value
    418      * for a time scale.
    419      *
    420      * NOTE: This is an internal value. DO NOT USE IT.
    421      *
    422      * @see utmscale_getTimeScaleValue
    423      *
    424      * @internal ICU 3.2
    425      */
    426     UTSV_MAX_ROUND_VALUE=10,
    427 
    428 #endif /* U_HIDE_INTERNAL_API */
    429 
    430 #ifndef U_HIDE_DEPRECATED_API
    431     /**
    432      * The number of time scale values, in other words limit of this enum.
    433      *
    434      * @see utmscale_getTimeScaleValue
    435      * @deprecated ICU 59 The numeric value may change over time, see ICU ticket #12420.
    436      */
    437     UTSV_MAX_SCALE_VALUE=11
    438 #endif  /* U_HIDE_DEPRECATED_API */
    439 
    440 } UTimeScaleValue;
    441 
    442 /**
    443  * Get a value associated with a particular time scale.
    444  *
    445  * @param timeScale The time scale
    446  * @param value A constant representing the value to get
    447  * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if arguments are invalid.
    448  * @return - the value.
    449  *
    450  * @stable ICU 3.2
    451  */
    452 U_STABLE int64_t U_EXPORT2
    453     utmscale_getTimeScaleValue(UDateTimeScale timeScale, UTimeScaleValue value, UErrorCode *status);
    454 
    455 /* Conversion to 'universal time scale' */
    456 
    457 /**
    458  * Convert a <code>int64_t</code> datetime from the given time scale to the universal time scale.
    459  *
    460  * @param otherTime The <code>int64_t</code> datetime
    461  * @param timeScale The time scale to convert from
    462  * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range.
    463  *
    464  * @return The datetime converted to the universal time scale
    465  *
    466  * @stable ICU 3.2
    467  */
    468 U_STABLE int64_t U_EXPORT2
    469     utmscale_fromInt64(int64_t otherTime, UDateTimeScale timeScale, UErrorCode *status);
    470 
    471 /* Conversion from 'universal time scale' */
    472 
    473 /**
    474  * Convert a datetime from the universal time scale to a <code>int64_t</code> in the given time scale.
    475  *
    476  * @param universalTime The datetime in the universal time scale
    477  * @param timeScale The time scale to convert to
    478  * @param status The status code. Set to <code>U_ILLEGAL_ARGUMENT_ERROR</code> if the conversion is out of range.
    479  *
    480  * @return The datetime converted to the given time scale
    481  *
    482  * @stable ICU 3.2
    483  */
    484 U_STABLE int64_t U_EXPORT2
    485     utmscale_toInt64(int64_t universalTime, UDateTimeScale timeScale, UErrorCode *status);
    486 
    487 #endif /* #if !UCONFIG_NO_FORMATTING */
    488 
    489 #endif
    490 
    491