]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/util/UniversalTimeScale.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / util / UniversalTimeScale.java
1 /*\r
2  *********************************************************************************\r
3  * Copyright (C) 2004-2008, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                  *\r
5  *********************************************************************************\r
6  *\r
7  */\r
8 \r
9 package com.ibm.icu.util;\r
10 \r
11 import com.ibm.icu.math.BigDecimal;\r
12 import java.lang.IllegalArgumentException;\r
13 \r
14 /** \r
15  * There are quite a few different conventions for binary datetime, depending on different\r
16  * platforms and protocols. Some of these have severe drawbacks. For example, people using\r
17  * Unix time (seconds since Jan 1, 1970, usually in a 32-bit integer)\r
18  * think that they are safe until near the year 2038.\r
19  * But cases can and do arise where arithmetic manipulations causes serious problems. Consider\r
20  * the computation of the average of two datetimes, for example: if one calculates them with\r
21  * <code>averageTime = (time1 + time2)/2</code>, there will be overflow even with dates\r
22  * beginning in 2004. Moreover, even if these problems don't occur, there is the issue of\r
23  * conversion back and forth between different systems.\r
24  *\r
25  * <p>Binary datetimes differ in a number of ways: the datatype, the unit,\r
26  * and the epoch (origin). We refer to these as time scales.</p>\r
27  *\r
28  * <p>ICU implements a universal time scale that is similar to the\r
29  * .NET framework's System.DateTime. The universal time scale is a\r
30  * 64-bit integer that holds ticks since midnight, January 1st, 0001.\r
31  * (One tick is 100 nanoseconds.)\r
32  * Negative values are supported. This has enough range to guarantee that\r
33  * calculations involving dates around the present are safe.</p>\r
34  *\r
35  * <p>The universal time scale always measures time according to the\r
36  * proleptic Gregorian calendar. That is, the Gregorian calendar's\r
37  * leap year rules are used for all times, even before 1582 when it was\r
38  * introduced. (This is different from the default ICU calendar which\r
39  * switches from the Julian to the Gregorian calendar in 1582.\r
40  * See GregorianCalendar.setGregorianChange() and ucal_setGregorianChange().)</p>\r
41  *\r
42  * ICU provides conversion functions to and from all other major time\r
43  * scales, allowing datetimes in any time scale to be converted to the\r
44  * universal time scale, safely manipulated, and converted back to any other\r
45  * datetime time scale.</p>\r
46  *\r
47  * <p>For more details and background, see the\r
48  * <a href="http://www.icu-project.org/userguide/universalTimeScale.html">Universal Time Scale</a>\r
49  * chapter in the ICU User Guide.</p>\r
50  *\r
51  * @stable ICU 3.2\r
52  */\r
53 \r
54 public final class UniversalTimeScale\r
55 {\r
56     /**\r
57      * Used in the JDK. Data is a <code>long</code>. Value\r
58      * is milliseconds since January 1, 1970.\r
59      *\r
60      * @stable ICU 3.2\r
61      */\r
62     public static final int JAVA_TIME = 0;\r
63 \r
64     /**\r
65      * Used in Unix systems. Data is an <code>int</code> or a <code>long</code>. Value\r
66      * is seconds since January 1, 1970.\r
67      *\r
68      * @stable ICU 3.2\r
69      */\r
70     public static final int UNIX_TIME = 1;\r
71 \r
72     /**\r
73      * Used in the ICU4C. Data is a <code>double</code>. Value\r
74      * is milliseconds since January 1, 1970.\r
75      *\r
76      * @stable ICU 3.2\r
77      */\r
78     public static final int ICU4C_TIME = 2;\r
79 \r
80     /**\r
81      * Used in Windows for file times. Data is a <code>long</code>. Value\r
82      * is ticks (1 tick == 100 nanoseconds) since January 1, 1601.\r
83      *\r
84      * @stable ICU 3.2\r
85      */\r
86     public static final int WINDOWS_FILE_TIME = 3;\r
87 \r
88     /**\r
89      * Used in the .NET framework's <code>System.DateTime</code> structure.\r
90      * Data is a <code>long</code>. Value is ticks (1 tick == 100 nanoseconds) since January 1, 0001.\r
91      *\r
92      * @stable ICU 3.2\r
93      */\r
94     public static final int DOTNET_DATE_TIME = 4;\r
95 \r
96     /**\r
97      * Used in older Macintosh systems. Data is an <code>int</code>. Value\r
98      * is seconds since January 1, 1904.\r
99      *\r
100      * @stable ICU 3.2\r
101      */\r
102     public static final int MAC_OLD_TIME = 5;\r
103 \r
104     /**\r
105      * Used in the JDK. Data is a <code>double</code>. Value\r
106      * is milliseconds since January 1, 2001.\r
107      *\r
108      * @stable ICU 3.2\r
109      */\r
110     public static final int MAC_TIME = 6;\r
111 \r
112     /**\r
113      * Used in Excel. Data is a <code>?unknown?</code>. Value\r
114      * is days since December 31, 1899.\r
115      *\r
116      * @stable ICU 3.2\r
117      */\r
118     public static final int EXCEL_TIME = 7;\r
119 \r
120     /**\r
121      * Used in DB2. Data is a <code>?unknown?</code>. Value\r
122      * is days since December 31, 1899.\r
123      *\r
124      * @stable ICU 3.2\r
125      */\r
126     public static final int DB2_TIME = 8;\r
127 \r
128     /**\r
129      * Data is a <code>long</code>. Value is microseconds since January 1, 1970.\r
130      * Similar to Unix time (linear value from 1970) and struct timeval\r
131      * (microseconds resolution).\r
132      *\r
133      * @stable ICU 3.8\r
134      */\r
135     public static final int UNIX_MICROSECONDS_TIME = 9;\r
136     \r
137     /**\r
138      * This is the first unused time scale value.\r
139      *\r
140      * @stable ICU 3.2\r
141      */\r
142     public static final int MAX_SCALE = 10;\r
143     \r
144     /**\r
145      * The constant used to select the units value\r
146      * for a time scale.\r
147      * \r
148      *\r
149      * @stable ICU 3.2\r
150      */\r
151     public static final int UNITS_VALUE = 0;\r
152     \r
153     /**\r
154      * The constant used to select the epoch offset value\r
155      * for a time scale.\r
156      * \r
157      * @see #getTimeScaleValue\r
158      *\r
159      * @stable ICU 3.2\r
160      */\r
161     public static final int EPOCH_OFFSET_VALUE = 1;\r
162     \r
163     /**\r
164      * The constant used to select the minimum from value\r
165      * for a time scale.\r
166      * \r
167      * @see #getTimeScaleValue\r
168      *\r
169      * @stable ICU 3.2\r
170      */\r
171     public static final int FROM_MIN_VALUE = 2;\r
172     \r
173     /**\r
174      * The constant used to select the maximum from value\r
175      * for a time scale.\r
176      * \r
177      * @see #getTimeScaleValue\r
178      *\r
179      * @stable ICU 3.2\r
180      */\r
181     public static final int FROM_MAX_VALUE = 3;\r
182     \r
183     /**\r
184      * The constant used to select the minimum to value\r
185      * for a time scale.\r
186      * \r
187      * @see #getTimeScaleValue\r
188      *\r
189      * @stable ICU 3.2\r
190      */\r
191     public static final int TO_MIN_VALUE = 4;\r
192     \r
193     /**\r
194      * The constant used to select the maximum to value\r
195      * for a time scale.\r
196      * \r
197      * @see #getTimeScaleValue\r
198      *\r
199      * @stable ICU 3.2\r
200      */\r
201     public static final int TO_MAX_VALUE = 5;\r
202     \r
203     /**\r
204      * The constant used to select the epoch plus one value\r
205      * for a time scale.\r
206      * \r
207      * NOTE: This is an internal value. DO NOT USE IT. May not\r
208      * actually be equal to the epoch offset value plus one.\r
209      * \r
210      * @see #getTimeScaleValue\r
211      *\r
212      * @stable ICU 3.2\r
213      */\r
214     public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6;\r
215     \r
216     /**\r
217      * The constant used to select the epoch offset minus one value\r
218      * for a time scale.\r
219      * \r
220      * NOTE: This is an internal value. DO NOT USE IT. May not\r
221      * actually be equal to the epoch offset value minus one.\r
222      * \r
223      * @see #getTimeScaleValue\r
224      *\r
225      * @internal\r
226      * @deprecated This API is ICU internal only.\r
227      */\r
228     public static final int EPOCH_OFFSET_MINUS_1_VALUE = 7;\r
229     \r
230     /**\r
231      * The constant used to select the units round value\r
232      * for a time scale.\r
233      * \r
234      * NOTE: This is an internal value. DO NOT USE IT.\r
235      * \r
236      * @see #getTimeScaleValue\r
237      *\r
238      * @internal\r
239      * @deprecated This API is ICU internal only.\r
240      */\r
241     public static final int UNITS_ROUND_VALUE = 8;\r
242     \r
243     /**\r
244      * The constant used to select the minimum safe rounding value\r
245      * for a time scale.\r
246      * \r
247      * NOTE: This is an internal value. DO NOT USE IT.\r
248      * \r
249      * @see #getTimeScaleValue\r
250      *\r
251      * @internal\r
252      * @deprecated This API is ICU internal only.\r
253      */\r
254     public static final int MIN_ROUND_VALUE = 9;\r
255     \r
256     /**\r
257      * The constant used to select the maximum safe rounding value\r
258      * for a time scale.\r
259      * \r
260      * NOTE: This is an internal value. DO NOT USE IT.\r
261      * \r
262      * @see #getTimeScaleValue\r
263      *\r
264      * @internal\r
265      * @deprecated This API is ICU internal only.\r
266      */\r
267     public static final int MAX_ROUND_VALUE = 10;\r
268     \r
269     /**\r
270      * The number of time scale values.\r
271      * \r
272      * NOTE: This is an internal value. DO NOT USE IT.\r
273      * \r
274      * @see #getTimeScaleValue\r
275      *\r
276      * @internal\r
277      * @deprecated This API is ICU internal only.\r
278      */\r
279     public static final int MAX_SCALE_VALUE = 11;\r
280     \r
281     private static final long ticks        = 1;\r
282     private static final long microseconds = ticks * 10;\r
283     private static final long milliseconds = microseconds * 1000;\r
284     private static final long seconds      = milliseconds * 1000;\r
285     private static final long minutes      = seconds * 60;\r
286     private static final long hours        = minutes * 60;\r
287     private static final long days         = hours * 24;\r
288     \r
289     /**\r
290      * This class holds the data that describes a particular\r
291      * time scale.\r
292      *\r
293      * @internal\r
294      * @deprecated This API is ICU internal only.\r
295      */\r
296     private static final class TimeScaleData\r
297     {\r
298         TimeScaleData(long theUnits, long theEpochOffset,\r
299                        long theToMin, long theToMax,\r
300                        long theFromMin, long theFromMax)\r
301         {\r
302             units      = theUnits;\r
303             unitsRound = theUnits / 2;\r
304             \r
305             minRound = Long.MIN_VALUE + unitsRound;\r
306             maxRound = Long.MAX_VALUE - unitsRound;\r
307                         \r
308             epochOffset   = theEpochOffset / theUnits;\r
309             \r
310             if (theUnits == 1) {\r
311                 epochOffsetP1 = epochOffsetM1 = epochOffset;\r
312             } else {\r
313                 epochOffsetP1 = epochOffset + 1;\r
314                 epochOffsetM1 = epochOffset - 1;\r
315             }\r
316             \r
317             toMin = theToMin;\r
318             toMax = theToMax;\r
319             \r
320             fromMin = theFromMin;\r
321             fromMax = theFromMax;\r
322         }\r
323         \r
324         long units;\r
325         long epochOffset;\r
326         long fromMin;\r
327         long fromMax;\r
328         long toMin;\r
329         long toMax;\r
330         \r
331         long epochOffsetP1;\r
332         long epochOffsetM1;\r
333         long unitsRound;\r
334         long minRound;\r
335         long maxRound;\r
336     }\r
337     \r
338     private static final TimeScaleData[] timeScaleTable = {\r
339         new TimeScaleData(milliseconds, 621355968000000000L, -9223372036854774999L, 9223372036854774999L, -984472800485477L,         860201606885477L), // JAVA_TIME\r
340         new TimeScaleData(seconds,      621355968000000000L, -9223372036854775808L, 9223372036854775807L, -984472800485L,               860201606885L), // UNIX_TIME\r
341         new TimeScaleData(milliseconds, 621355968000000000L, -9223372036854774999L, 9223372036854774999L, -984472800485477L,         860201606885477L), // ICU4C_TIME\r
342         new TimeScaleData(ticks,        504911232000000000L, -8718460804854775808L, 9223372036854775807L, -9223372036854775808L, 8718460804854775807L), // WINDOWS_FILE_TIME\r
343         new TimeScaleData(ticks,        000000000000000000L, -9223372036854775808L, 9223372036854775807L, -9223372036854775808L, 9223372036854775807L), // DOTNET_DATE_TIME\r
344         new TimeScaleData(seconds,      600527520000000000L, -9223372036854775808L, 9223372036854775807L, -982389955685L,               862284451685L), // MAC_OLD_TIME\r
345         new TimeScaleData(seconds,      631139040000000000L, -9223372036854775808L, 9223372036854775807L, -985451107685L,               859223299685L), // MAC_TIME\r
346         new TimeScaleData(days,         599265216000000000L, -9223372036854775808L, 9223372036854775807L, -11368793L,                        9981605L), // EXCEL_TIME\r
347         new TimeScaleData(days,         599265216000000000L, -9223372036854775808L, 9223372036854775807L, -11368793L,                        9981605L), // DB2_TIME\r
348         new TimeScaleData(microseconds, 621355968000000000L, -9223372036854775804L, 9223372036854775804L, -984472800485477580L,   860201606885477580L)  // UNIX_MICROSECONDS_TIME\r
349     };\r
350     \r
351     \r
352     /*\r
353      * Prevent construction of this class.\r
354      */\r
355     ///CLOVER:OFF\r
356     private UniversalTimeScale()\r
357     {\r
358         // nothing to do\r
359     }\r
360     ///CLOVER:ON\r
361     \r
362     /**\r
363      * Convert a <code>long</code> datetime from the given time scale to the universal time scale.\r
364      *\r
365      * @param otherTime The <code>long</code> datetime\r
366      * @param timeScale The time scale to convert from\r
367      * \r
368      * @return The datetime converted to the universal time scale\r
369      *\r
370      * @stable ICU 3.2\r
371      */\r
372     public static long from(long otherTime, int timeScale)\r
373     {\r
374         TimeScaleData data = fromRangeCheck(otherTime, timeScale);\r
375                 \r
376         return (otherTime + data.epochOffset) * data.units;\r
377     }\r
378 \r
379     /**\r
380      * Convert a <code>double</code> datetime from the given time scale to the universal time scale.\r
381      * All calculations are done using <code>BigDecimal</code> to guarantee that the value\r
382      * does not go out of range.\r
383      *\r
384      * @param otherTime The <code>double</code> datetime\r
385      * @param timeScale The time scale to convert from\r
386      * \r
387      * @return The datetime converted to the universal time scale\r
388      *\r
389      * @stable ICU 3.2\r
390      */\r
391     public static BigDecimal bigDecimalFrom(double otherTime, int timeScale)\r
392     {\r
393         TimeScaleData data     = getTimeScaleData(timeScale);\r
394         BigDecimal other       = new BigDecimal(String.valueOf(otherTime));\r
395         BigDecimal units       = new BigDecimal(data.units);\r
396         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
397         \r
398         return other.add(epochOffset).multiply(units);\r
399     }\r
400 \r
401     /**\r
402      * Convert a <code>long</code> datetime from the given time scale to the universal time scale.\r
403      * All calculations are done using <code>BigDecimal</code> to guarantee that the value\r
404      * does not go out of range.\r
405      *\r
406      * @param otherTime The <code>long</code> datetime\r
407      * @param timeScale The time scale to convert from\r
408      * \r
409      * @return The datetime converted to the universal time scale\r
410      *\r
411      * @stable ICU 3.2\r
412      */\r
413     public static BigDecimal bigDecimalFrom(long otherTime, int timeScale)\r
414     {\r
415         TimeScaleData data     = getTimeScaleData(timeScale);\r
416         BigDecimal other       = new BigDecimal(otherTime);\r
417         BigDecimal units       = new BigDecimal(data.units);\r
418         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
419         \r
420         return other.add(epochOffset).multiply(units);\r
421     }\r
422 \r
423     /**\r
424      * Convert a <code>BigDecimal</code> datetime from the given time scale to the universal time scale.\r
425      * All calculations are done using <code>BigDecimal</code> to guarantee that the value\r
426      * does not go out of range.\r
427      *\r
428      * @param otherTime The <code>BigDecimal</code> datetime\r
429      * @param timeScale The time scale to convert from\r
430      * \r
431      * @return The datetime converted to the universal time scale\r
432      *\r
433      * @stable ICU 3.2\r
434      */\r
435     public static BigDecimal bigDecimalFrom(BigDecimal otherTime, int timeScale)\r
436     {\r
437         TimeScaleData data = getTimeScaleData(timeScale);\r
438         \r
439         BigDecimal units = new BigDecimal(data.units);\r
440         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
441         \r
442         return otherTime.add(epochOffset).multiply(units);\r
443     }\r
444 \r
445     /**\r
446      * Convert a datetime from the universal time scale stored as a <code>BigDecimal</code> to a\r
447      * <code>long</code> in the given time scale.\r
448      *\r
449      * Since this calculation requires a divide, we must round. The straight forward\r
450      * way to round by adding half of the divisor will push the sum out of range for values\r
451      * within have the divisor of the limits of the precision of a <code>long</code>. To get around this, we do\r
452      * the rounding like this:\r
453      * \r
454      * <p><code>\r
455      * (universalTime - units + units/2) / units + 1\r
456      * </code>\r
457      * \r
458      * <p>\r
459      * (i.e. we subtract units first to guarantee that we'll still be in range when we\r
460      * add <code>units/2</code>. We then need to add one to the quotent to make up for the extra subtraction.\r
461      * This simplifies to:\r
462      * \r
463      * <p><code>\r
464      * (universalTime - units/2) / units - 1\r
465      * </code>\r
466      * \r
467      * <p>\r
468      * For negative values to round away from zero, we need to flip the signs:\r
469      * \r
470      * <p><code>\r
471      * (universalTime + units/2) / units + 1\r
472      * </code>\r
473      * \r
474      * <p>\r
475      * Since we also need to subtract the epochOffset, we fold the <code>+/- 1</code>\r
476      * into the offset value. (i.e. <code>epochOffsetP1</code>, <code>epochOffsetM1</code>.)\r
477      * \r
478      * @param universalTime The datetime in the universal time scale\r
479      * @param timeScale The time scale to convert to\r
480      * \r
481      * @return The datetime converted to the given time scale\r
482      *\r
483      * @stable ICU 3.2\r
484      */\r
485     public static long toLong(long universalTime, int timeScale)\r
486     {\r
487         TimeScaleData data = toRangeCheck(universalTime, timeScale);\r
488         \r
489         if (universalTime < 0) {\r
490             if (universalTime < data.minRound) {\r
491                 return (universalTime + data.unitsRound) / data.units - data.epochOffsetP1;\r
492             }\r
493             \r
494             return (universalTime - data.unitsRound) / data.units - data.epochOffset;\r
495         }\r
496         \r
497         if (universalTime > data.maxRound) {\r
498             return (universalTime - data.unitsRound) / data.units - data.epochOffsetM1;\r
499         }\r
500         \r
501         return (universalTime + data.unitsRound) / data.units - data.epochOffset;\r
502     }\r
503     \r
504     /**\r
505      * Convert a datetime from the universal time scale to a <code>BigDecimal</code> in the given time scale.\r
506      *\r
507      * @param universalTime The datetime in the universal time scale\r
508      * @param timeScale The time scale to convert to\r
509      * \r
510      * @return The datetime converted to the given time scale\r
511      *\r
512      * @stable ICU 3.2\r
513      */\r
514     public static BigDecimal toBigDecimal(long universalTime, int timeScale)\r
515     {\r
516         TimeScaleData data     = getTimeScaleData(timeScale);\r
517         BigDecimal universal   = new BigDecimal(universalTime);\r
518         BigDecimal units       = new BigDecimal(data.units);\r
519         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
520         \r
521         return universal.divide(units, BigDecimal.ROUND_HALF_UP).subtract(epochOffset);\r
522     }\r
523     \r
524     /**\r
525      * Convert a datetime from the universal time scale to a <code>BigDecimal</code> in the given time scale.\r
526      *\r
527      * @param universalTime The datetime in the universal time scale\r
528      * @param timeScale The time scale to convert to\r
529      * \r
530      * @return The datetime converted to the given time scale\r
531      *\r
532      * @stable ICU 3.2\r
533      */\r
534     public static BigDecimal toBigDecimal(BigDecimal universalTime, int timeScale)\r
535     {\r
536         TimeScaleData data     = getTimeScaleData(timeScale);\r
537         BigDecimal units       = new BigDecimal(data.units);\r
538         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
539         \r
540         return universalTime.divide(units, BigDecimal.ROUND_HALF_UP).subtract(epochOffset);\r
541     }\r
542     \r
543     /**\r
544      * Return the <code>TimeScaleData</code> object for the given time\r
545      * scale.\r
546      * \r
547      * @param scale - the time scale\r
548      * \r
549      * @return the <code>TimeScaleData</code> object for the given time scale\r
550      * \r
551      * @internal\r
552      * @deprecated This API is ICU internal only.\r
553      */\r
554     private static TimeScaleData getTimeScaleData(int scale)\r
555     {\r
556         if (scale < 0 || scale >= MAX_SCALE) {\r
557             throw new IllegalArgumentException("scale out of range: " + scale);\r
558         }\r
559         \r
560         return timeScaleTable[scale];\r
561     }\r
562     \r
563     /**\r
564      * Get a value associated with a particular time scale.\r
565      * \r
566      * @param scale - the time scale\r
567      * @param value - a constant representing the value to get\r
568      * \r
569      * @return - the value.\r
570      * \r
571      * @stable ICU 3.2\r
572      */\r
573     public static long getTimeScaleValue(int scale, int value)\r
574     {\r
575         TimeScaleData data = getTimeScaleData(scale);\r
576         \r
577         switch (value)\r
578         {\r
579         case UNITS_VALUE:\r
580             return data.units;\r
581             \r
582         case EPOCH_OFFSET_VALUE:\r
583             return data.epochOffset;\r
584         \r
585         case FROM_MIN_VALUE:\r
586             return data.fromMin;\r
587             \r
588         case FROM_MAX_VALUE:\r
589             return data.fromMax;\r
590             \r
591         case TO_MIN_VALUE:\r
592             return data.toMin;\r
593             \r
594         case TO_MAX_VALUE:\r
595             return data.toMax;\r
596             \r
597         case EPOCH_OFFSET_PLUS_1_VALUE:\r
598             return data.epochOffsetP1;\r
599             \r
600         case EPOCH_OFFSET_MINUS_1_VALUE:\r
601             return data.epochOffsetM1;\r
602             \r
603         case UNITS_ROUND_VALUE:\r
604             return data.unitsRound;\r
605         \r
606         case MIN_ROUND_VALUE:\r
607             return data.minRound;\r
608             \r
609         case MAX_ROUND_VALUE:\r
610             return data.maxRound;\r
611             \r
612         default:\r
613             throw new IllegalArgumentException("value out of range: " + value);\r
614         }\r
615     }\r
616     \r
617     private static TimeScaleData toRangeCheck(long universalTime, int scale)\r
618     {\r
619         TimeScaleData data = getTimeScaleData(scale);\r
620           \r
621         if (universalTime >= data.toMin && universalTime <= data.toMax) {\r
622             return data;\r
623         }\r
624         \r
625         throw new IllegalArgumentException("universalTime out of range:" + universalTime);\r
626     }\r
627     \r
628     private static TimeScaleData fromRangeCheck(long otherTime, int scale)\r
629     {\r
630         TimeScaleData data = getTimeScaleData(scale);\r
631           \r
632         if (otherTime >= data.fromMin && otherTime <= data.fromMax) {\r
633             return data;\r
634         }\r
635         \r
636         throw new IllegalArgumentException("otherTime out of range:" + otherTime);\r
637     }\r
638     \r
639     /**\r
640      * Convert a time in the Universal Time Scale into another time\r
641      * scale. The division used to do the conversion rounds down.\r
642      * \r
643      * NOTE: This is an internal routine used by the tool that\r
644      * generates the to and from limits. Use it at your own risk.\r
645      * \r
646      * @param universalTime the time in the Universal Time scale\r
647      * @param timeScale the time scale to convert to\r
648      * @return the time in the given time scale\r
649      * \r
650      * @internal\r
651      * @deprecated This API is ICU internal only.\r
652      */\r
653     public static BigDecimal toBigDecimalTrunc(BigDecimal universalTime, int timeScale)\r
654     {\r
655         TimeScaleData data = getTimeScaleData(timeScale);\r
656         BigDecimal units = new BigDecimal(data.units);\r
657         BigDecimal epochOffset = new BigDecimal(data.epochOffset);\r
658         \r
659         return universalTime.divide(units, BigDecimal.ROUND_DOWN).subtract(epochOffset);\r
660     }\r
661 }\r