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