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