/// <summary> /// Convert a datetime from the universal time scale stored as a /// <c>BigDecimal</c> to a <c>long</c> in the given time scale. /// Since this calculation requires a divide, we must round. The straight /// forward way to round by adding half of the divisor will push the sum out /// of range for values within have the divisor of the limits of the /// precision of a <c>long</c>. To get around this, we do the rounding /// like this: /// <p> /// <code> /// (universalTime - units + units/2) / units + 1 /// </code> /// <p> /// (i.e. we subtract units first to guarantee that we'll still be in range /// when we add <code>units/2</code>. We then need to add one to the quotent /// to make up for the extra subtraction. This simplifies to: /// <p> /// <code> /// (universalTime - units/2) / units - 1 /// </code> /// <p> /// For negative values to round away from zero, we need to flip the signs: /// <p> /// <code> /// (universalTime + units/2) / units + 1 /// </code> /// <p> /// Since we also need to subtract the epochOffset, we fold the /// <code>+/- 1</code> into the offset value. (i.e. /// <c>epochOffsetP1</c>, <c>epochOffsetM1</c>.) /// </summary> /// /// <param name="universalTime">The datetime in the universal time scale</param> /// <param name="timeScale">The time scale to convert to</param> /// <returns>The datetime converted to the given time scale</returns> /// @stable ICU 3.2 public static long ToLong(long universalTime, int timeScale) { UniversalTimeScale.TimeScaleData data = ToRangeCheck(universalTime, timeScale); if (universalTime < 0) { if (universalTime < data.minRound) { return((universalTime + data.unitsRound) / data.units - data.epochOffsetP1); } return((universalTime - data.unitsRound) / data.units - data.epochOffset); } if (universalTime > data.maxRound) { return((universalTime - data.unitsRound) / data.units - data.epochOffsetM1); } return((universalTime + data.unitsRound) / data.units - data.epochOffset); }
/// <summary> /// Convert a <c>BigDecimal</c> datetime from the given time scale to /// the universal time scale. All calculations are done using /// <c>BigDecimal</c> to guarantee that the value does not go out of /// range. /// </summary> /// /// <param name="otherTime">The <c>BigDecimal</c> datetime</param> /// <param name="timeScale">The time scale to convert from</param> /// <returns>The datetime converted to the universal time scale</returns> /// @stable ICU 3.2 public static BigDecimal BigDecimalFrom(BigDecimal otherTime, int timeScale) { UniversalTimeScale.TimeScaleData data = GetTimeScaleData(timeScale); BigDecimal units_0 = new BigDecimal(data.units); BigDecimal epochOffset_1 = new BigDecimal(data.epochOffset); return(otherTime.Add(epochOffset_1).Multiply(units_0)); }
/// <exclude/> /// <summary> /// Convert a time in the Universal Time Scale into another time scale. The /// division used to do the conversion rounds down. /// NOTE: This is an internal routine used by the tool that generates the to /// and from limits. Use it at your own risk. /// </summary> /// /// <param name="universalTime">the time in the Universal Time scale</param> /// <param name="timeScale">the time scale to convert to</param> /// <returns>the time in the given time scale</returns> public static BigDecimal ToBigDecimalTrunc(BigDecimal universalTime, int timeScale) { UniversalTimeScale.TimeScaleData data = GetTimeScaleData(timeScale); BigDecimal units_0 = new BigDecimal(data.units); BigDecimal epochOffset_1 = new BigDecimal(data.epochOffset); return(universalTime.Divide(units_0, IBM.ICU.Math.BigDecimal.ROUND_DOWN).Subtract( epochOffset_1)); }
private static UniversalTimeScale.TimeScaleData FromRangeCheck(long otherTime, int scale) { UniversalTimeScale.TimeScaleData data = GetTimeScaleData(scale); if (otherTime >= data.fromMin && otherTime <= data.fromMax) { return(data); } throw new ArgumentException("otherTime out of range:" + otherTime); }
private static UniversalTimeScale.TimeScaleData ToRangeCheck(long universalTime, int scale) { UniversalTimeScale.TimeScaleData data = GetTimeScaleData(scale); if (universalTime >= data.toMin && universalTime <= data.toMax) { return(data); } throw new ArgumentException("universalTime out of range:" + universalTime); }
/// <summary> /// Get a value associated with a particular time scale. /// </summary> /// /// <param name="scale">- the time scale</param> /// <param name="value">- a constant representing the value to get</param> /// <returns>- the value.</returns> /// @stable ICU 3.2 public static long GetTimeScaleValue(int scale, int value_ren) { UniversalTimeScale.TimeScaleData data = GetTimeScaleData(scale); switch (value_ren) { case UNITS_VALUE: return(data.units); case EPOCH_OFFSET_VALUE: return(data.epochOffset); case FROM_MIN_VALUE: return(data.fromMin); case FROM_MAX_VALUE: return(data.fromMax); case TO_MIN_VALUE: return(data.toMin); case TO_MAX_VALUE: return(data.toMax); case EPOCH_OFFSET_PLUS_1_VALUE: return(data.epochOffsetP1); case EPOCH_OFFSET_MINUS_1_VALUE: return(data.epochOffsetM1); case UNITS_ROUND_VALUE: return(data.unitsRound); case MIN_ROUND_VALUE: return(data.minRound); case MAX_ROUND_VALUE: return(data.maxRound); default: throw new ArgumentException("value out of range: " + value_ren); } }
// /CLOVER:ON /// <summary> /// Convert a <c>long</c> datetime from the given time scale to the /// universal time scale. /// </summary> /// /// <param name="otherTime">The <c>long</c> datetime</param> /// <param name="timeScale">The time scale to convert from</param> /// <returns>The datetime converted to the universal time scale</returns> /// @stable ICU 3.2 public static long From(long otherTime, int timeScale) { UniversalTimeScale.TimeScaleData data = FromRangeCheck(otherTime, timeScale); return((otherTime + data.epochOffset) * data.units); }