`averageTime = (time1 + time2)/2`

, there will be overflow even with dates
* around the present. Moreover, even if these problems don't occur, there is the issue of
* conversion back and forth between different systems.
*
* * Binary datetimes differ in a number of ways: the datatype, the unit, * and the epoch (origin). We'll refer to these as time scales. For example: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Source | Datatype | Unit | Epoch |
---|---|---|---|

JAVA_TIME | long | milliseconds | Jan 1, 1970 |

UNIX_TIME | int or long | seconds | Jan 1, 1970 |

ICU4C | double | milliseconds | Jan 1, 1970 |

WINDOWS_FILE_TIME | long | ticks (100 nanoseconds) | Jan 1, 1601 |

WINDOWS_DATE_TIME | long | ticks (100 nanoseconds) | Jan 1, 0001 |

MAC_OLD_TIME | int | seconds | Jan 1, 1904 |

MAC_TIME | double | seconds | Jan 1, 2001 |

EXCEL_TIME | ? | days | Dec 31, 1899 |

DB2_TIME | ? | days | Dec 31, 1899 |

* All of the epochs start at 00:00 am (the earliest possible time on the day in question), * and are assumed to be UTC. * *

* The ranges for different datatypes are given in the following table (all values in years). * The range of years includes the entire range expressible with positive and negative * values of the datatype. The range of years for double is the range that would be allowed * without losing precision to the corresponding unit. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Units | long | double | int |
---|---|---|---|

1 sec | 5.84542ื10นน | 285,420,920.94 | 136.10 |

1 millisecond | 584,542,046.09 | 285,420.92 | 0.14 |

1 microsecond | 584,542.05 | 285.42 | 0.00 |

100 nanoseconds (tick) | 58,454.20 | 28.54 | 0.00 |

1 nanosecond | 584.5420461 | 0.2854 | 0.00 |

* These functions implement a universal time scale which can be used as a 'pivot', * and provide conversion functions to and from all other major time scales. * This datetimes to be converted to the pivot time, safely manipulated, * and converted back to any other datetime time scale. * *

* So what to use for this pivot? Java time has plenty of range, but cannot represent
* Windows datetimes without severe loss of precision. ICU4C time addresses this by using a
* double that is otherwise equivalent to the Java time. However, there are disadvantages
* with doubles. They provide for much more graceful degradation in arithmetic operations.
* But they only have 53 bits of accuracy, which means that they will lose precision when
* converting back and forth to ticks. What would really be nice would be a
* `long double`

(80 bits -- 64 bit mantissa), but that is not supported on most systems.
*
*

* The Unix extended time uses a structure with two components: time in seconds and a
* fractional field (microseconds). However, this is clumsy, slow, and
* prone to error (you always have to keep track of overflow and underflow in the
* fractional field). `BigDecimal`

would allow for arbitrary precision and arbitrary range,
* but we would not want to use this as the normal type, because it is slow and does not
* have a fixed size.
*
*

* Because of these issues, we ended up concluding that the Windows datetime would be the
* best pivot. However, we use the full range allowed by the datatype, allowing for
* datetimes back to 29,000 BC and up to 29,000 AD. This time scale is very fine grained,
* does not lose precision, and covers a range that will meet almost all requirements.
* It will not handle the range that Java times would, but frankly, being able to handle dates
* before 29,000 BC or after 29,000 AD is of very limited interest. However, for those cases,
* we also allow conversion to an optional `BigDecimal`

format that would have arbitrary
* precision and range.
*
*/
public final class UniversalTimeScale
{
/**
* Used in the JDK. Data is a `long`

. Value
* is milliseconds since January 1, 1970.
*
* @draft ICU 3.2
*/
static final int JAVA_TIME = 0;
/**
* Used in Unix systems. Data is an `int> or a `

`long`

. Value
* is seconds since January 1, 1970.
*
* @draft ICU 3.2
*/
static final int UNIX_TIME = 1;
/**
* Used in the ICU4C. Data is a `double`

. Value
* is milliseconds since January 1, 1970.
*
* @draft ICU 3.2
*/
static final int ICU4C_TIME = 2;
/**
* Used in Windows for file times. Data is a `long`

. Value
* is ticks (1 tick == 100 nanoseconds) since January 1, 1601.
*
* @draft ICU 3.2
*/
static final int WINDOWS_FILE_TIME = 3;
/**
* Used in Windows for date time (?). Data is a `long`

. Value
* is ticks (1 tick == 100 nanoseconds) since January 1, 0001.
*
* @draft ICU 3.2
*/
static final int WINDOWS_DATE_TIME = 4;
/**
* Used in older Macintosh systems. Data is an `int`

. Value
* is seconds since January 1, 1904.
*
* @draft ICU 3.2
*/
static final int MAC_OLD_TIME = 5;
/**
* Used in the JDK. Data is a `double`

. Value
* is milliseconds since January 1, 2001.
*
* @draft ICU 3.2
*/
static final int MAC_TIME = 6;
/**
* Used in Excel. Data is a `?unknown?`

. Value
* is days since December 31, 1899.
*
* @draft ICU 3.2
*/
static final int EXCEL_TIME = 7;
/**
* Used in DB2. Data is a `?unknown?`

. Value
* is days since December 31, 1899.
*
* @draft ICU 3.2
*/
static final int DB2_TIME = 8;
/* Conversion to 'universal time scale' */
/**
* Convert a `double`

datetime from the given time scale to the universal time scale.
*
* @param otherTime The `double`

datetime
* @param timeScale The time scale to convert from
*
* @return The datetime converted to the universal time scale
*
* @draft ICU 3.2
*/
static long from(double otherTime, int timeScale);
/**
* Convert a `long`

datetime from the given time scale to the universal time scale.
*
* @param otherTime The `long`

datetime
* @param timeScale The time scale to convert from
*
* @return The datetime converted to the universal time scale
*
* @draft ICU 3.2
*/
static long from(long otherTime, int timeScale);
/**
* Convert a `double`

datetime from the given time scale to the universal time scale.
* All calculations are done using `BigDecimal`

to guarantee that the value
* does not go out of range.
*
* @param otherTime The `double`

datetime
* @param timeScale The time scale to convert from
*
* @return The datetime converted to the universal time scale
*
* @draft ICU 3.2
*/
static BigDecimal bigDecimalFrom(double otherTime, int timeScale);
/**
* Convert a `long`

datetime from the given time scale to the universal time scale.
* All calculations are done using `BigDecimal`

to guarantee that the value
* does not go out of range.
*
* @param otherTime The `long`

datetime
* @param timeScale The time scale to convert from
*
* @return The datetime converted to the universal time scale
*
* @draft ICU 3.2
*/
static BigDecimal bigDecimalFrom(long otherTime, int timeScale);
/* Conversion from 'universal time scale' */
/**
* Convert a datetime from the universal time scale to a `double`

in the given time scale.
*
* @param universal The datetime in the universal time scale
* @param timeScale The time scale to convert to
*
* @return The datetime converted to the given time scale
*
* @draft ICU 3.2
*/
static double toDouble(long universalTime, int timeScale);
/**
* Convert a datetime from the universal time scale stored as a `BigDecimal`

to a
* `double`

in the given time scale.
*
* @param universal The datetime in the universal time scale
* @param timeScale The time scale to convert to
*
* @return The datetime converted to the given time scale
*
* @draft ICU 3.2
*/
static double toDouble(BigDecimal universalTime, int timeScale);
/**
* Convert a datetime from the universal time scale stored as a `BigDecimal`

to a
* `long`

in the given time scale.
*
* @param universal The datetime in the universal time scale
* @param timeScale The time scale to convert to
*
* @return The datetime converted to the given time scale
*
* @draft ICU 3.2
*/
static long toLong(long universalTime, int timeScale);
/**
* Convert a datetime from the universal time scale to a `long`

in the given time scale.
*
* @param universal The datetime in the universal time scale
* @param timeScale The time scale to convert to
*
* @return The datetime converted to the given time scale
*
* @draft ICU 3.2
*/
static long toLong(BigDecimal universalTime, int timeScale);
}