12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 3bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/* 4bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ******************************************************************************* 5bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Copyright (C) 1996-2008, International Business Machines Corporation and * 6bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * others. All Rights Reserved. * 7bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert ******************************************************************************* 8bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 9bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 10bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 11bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpackage com.ibm.icu.dev.tool.timescale; 12bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 13bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.ibm.icu.math.BigDecimal; 14bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.ibm.icu.text.MessageFormat; 15bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertimport com.ibm.icu.util.UniversalTimeScale; 16bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 17bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert/** 18bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * This class calculates the minimum and maximum values which can be 19bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * used as arguments to <code>toLong</code> and <code>from</code>. 20bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 21bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * NOTE: If you change the way in which these values are calculated, it 22bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * may be necessary to disable to <code>toRangeCheck()</code> and 23bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * <code>fromRangeCheck()</code> methods in the <code>UniversalTimeScale</code> 24bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * for all of the calculations to run without throwing an error. 25bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 26bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * @see com.ibm.icu.util.UniversalTimeScale 27bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 28bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubertpublic class CalculateLimits { 29bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 30bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /** 31bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * The default constructor. 32bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 33bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public CalculateLimits() 34bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert { 35bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 36bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 37bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert /** 38bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * This method first calculates the <code>from</code> limits by 39bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * passing <code>Long.MIN_VALUE</code> and <code>Long.MAX_VALUE</code> to 40bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * the (internal) <code>toBigDecimalTrunc()</code> method. Any values outside 41bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * of the range of a <code>long</code> are pinned. 42bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 43bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * The mimimum and maximum values for <code>toLong</code> are calulated by passing 44bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * the min and max values calculated above to <code>BigDecimalFrom()</code>. Because 45bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * this method will round, the returned values are adjusted to take this into account. 46bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 47bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * @see com.ibm.icu.util.UniversalTimeScale 48bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * 49bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * @param args - the command line arugments 50bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert */ 51bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert public static void main(String[] args) 52bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert { 53bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert MessageFormat fmt = new MessageFormat("{0}L, {1}L, {2}L, {3}L"); 54bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal universalMin = new BigDecimal(Long.MIN_VALUE); 55bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal universalMax = new BigDecimal(Long.MAX_VALUE); 56bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert Object limitArgs[] = {null, null, null, null}; 57bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 58bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println("\nTo, From limits:"); 59bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 60bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // from limits 61bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for(int scale = 0; scale < UniversalTimeScale.MAX_SCALE; scale += 1) { 62bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal min = UniversalTimeScale.toBigDecimalTrunc(universalMin, scale).max(universalMin); 63bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal max = UniversalTimeScale.toBigDecimalTrunc(universalMax, scale).min(universalMax); 64bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert long minLong = min.longValue(); 65bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert long maxLong = max.longValue(); 66bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 67bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert limitArgs[2] = min.toString(); 68bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert limitArgs[3] = max.toString(); 69bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 70bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // to limits 71bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal minTrunc = UniversalTimeScale.bigDecimalFrom(min, scale); 72bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal maxTrunc = UniversalTimeScale.bigDecimalFrom(max, scale); 73bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal minResidue = minTrunc.subtract(universalMin); 74bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal maxResidue = universalMax.subtract(maxTrunc); 75bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert long units = UniversalTimeScale.getTimeScaleValue(scale, UniversalTimeScale.UNITS_VALUE); 76bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert BigDecimal half = new BigDecimal(units == 1? 0: units / 2 - 1); 77bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 78bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert min = minTrunc.subtract(minResidue.min(half)); 79bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert max = maxTrunc.add(maxResidue.min(half)); 80bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert limitArgs[0] = min.toString(); 81bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert limitArgs[1] = max.toString(); 82bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 83bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println(fmt.format(limitArgs)); 84bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 85bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // round-trip test the from limits 86bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if(UniversalTimeScale.toLong(UniversalTimeScale.from(minLong, scale), scale) != minLong) { 87bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println("OOPS: min didn't round trip!"); 88bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 89bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 90bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if(UniversalTimeScale.toLong(UniversalTimeScale.from(maxLong, scale), scale) != maxLong) { 91bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println("OOPS: max didn't round trip!"); 92bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 93bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 94bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert // make sure that the to limits convert to the from limits 95bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if(UniversalTimeScale.toLong(min.longValue(), scale) != minLong) { 96bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println("OOPS: toLong(toMin) != fromMin"); 97bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 98bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 99bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if(UniversalTimeScale.toLong(max.longValue(), scale) != maxLong) { 100bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert System.out.println("OOPS: toLong(toMax) != fromMax"); 101bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 102bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 103bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 104bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert} 105