12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
5145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer * Copyright (C) 2007-2015, International Business Machines Corporation and
6145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer * others. All Rights Reserved.
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.duration;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11145e2c500373e5096c471c25be1dcfd3585e1b46Markus Schererimport java.math.BigDecimal;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Date;
14145e2c500373e5096c471c25be1dcfd3585e1b46Markus Schererimport java.util.HashMap;
15145e2c500373e5096c471c25be1dcfd3585e1b46Markus Schererimport java.util.Map;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
18145e2c500373e5096c471c25be1dcfd3585e1b46Markus Schererimport javax.xml.datatype.DatatypeConstants;
19f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubertimport javax.xml.datatype.DatatypeConstants.Field;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport javax.xml.datatype.Duration;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
222d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubertimport org.junit.Test;
23fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubertimport org.junit.runner.RunWith;
24fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubertimport org.junit.runners.JUnit4;
252d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.dev.test.TestFmwk;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DurationFormat;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale;
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author srl
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
35fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert@RunWith(JUnit4.class)
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class ICUDurationTest extends TestFmwk {
37145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    /**
38145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer     * Allows us to not depend on javax.xml.datatype.DatatypeFactory.
39145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer     * We need just a tiny subset of the Duration API:
40145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer     * The ICU DurationFormat just extracts the field values,
41145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer     * to convert the Duration into an internal Period type.
42145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer     */
43145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    private static final class ICUTestDuration extends javax.xml.datatype.Duration {
44145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        private final int sign;
45145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        // Duration docs say BigInteger/BigDecimal but
46145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        // ICU only cares about intValue() and floatValue().
47145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        private final Map<Field, Number> fields;
48145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
49145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        ICUTestDuration(long millis) {
50145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            fields = new HashMap<Field, Number>();
51145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (millis > 0) {
52145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                sign = 1;
53145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            } else if (millis == 0) {
54145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                sign = 0;
55145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                return;
56145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            } else {
57145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                sign = -1;
58145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                millis = -millis;
59145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            }
60145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            long d = millis / 86400000L;
61145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            millis %= 86400000L;
62145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (d > 0) {
63145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                fields.put(DatatypeConstants.DAYS, d);
64145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            }
65145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            long h = millis / 3600000L;
66145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            millis %= 3600000L;
67145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (h > 0) {
68145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                fields.put(DatatypeConstants.HOURS, h);
69145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            }
70145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            long m = millis / 60000L;
71145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            millis %= 60000L;
72145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (m > 0) {
73145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                fields.put(DatatypeConstants.MINUTES, m);
74145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            }
75145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            fields.put(DatatypeConstants.SECONDS, (float)millis / 1000);
76145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
77145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
78145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        /**
79145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer         * Pass in negative values for fields not to be set.
80145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer         */
81145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        ICUTestDuration(int sgn, int y, int months, int d, int h, int m, float s) {
82145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            sign = sgn;
83145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            fields = new HashMap<Field, Number>();
84145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (y >= 0) { fields.put(DatatypeConstants.YEARS, y); }
85145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (months >= 0) { fields.put(DatatypeConstants.MONTHS, months); }
86145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (d >= 0) { fields.put(DatatypeConstants.DAYS, d); }
87145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (h >= 0) { fields.put(DatatypeConstants.HOURS, h); }
88145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (m >= 0) { fields.put(DatatypeConstants.MINUTES, m); }
89145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            if (s >= 0) { fields.put(DatatypeConstants.SECONDS, s); }
90145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
91145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
92145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        private ICUTestDuration(int sgn, Map<Field, Number> f) {
93145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            sign = sgn;
94145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            fields = f;
95145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
96145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
97145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
98145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public Duration add(Duration rhs) {
99145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
100145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
101145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
102145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
103145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public void addTo(java.util.Calendar calendar) {
104145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
105145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
106145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
107145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
108145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public int compare(Duration duration) {
109145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
110145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
111145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
112145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
113145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public Number getField(Field field) {
114145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            return fields.get(field);
115145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
116145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
117145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
118145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public int getSign() {
119145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            return sign;
120145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
121145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
122145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
123145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public int hashCode() {
124145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
125145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
126145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
127145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
128145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public boolean isSet(Field field) {
129145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            return fields.containsKey(field);
130145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
131145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
132145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
133145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public Duration multiply(BigDecimal factor) {
134145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
135145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
136145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
137145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
138145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public Duration negate() {
139145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            return new ICUTestDuration(-sign, fields);
140145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
141145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
142145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
143145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public Duration normalizeWith(java.util.Calendar startTimeInstant) {
144145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            throw new UnsupportedOperationException();
145145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
146145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
147145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        @Override
148145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        public String toString() {
149145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            String signString = sign > 0 ? "positive" : sign == 0 ? "zero" : "negative";
150145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            return signString + " fields=" + fields;
151145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        }
152145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    }
153145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    private static final ICUTestDuration newDuration(long millis) {
154145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        return new ICUTestDuration(millis);
155145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    }
156145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    private static final ICUTestDuration newDuration(int sgn, int d, int h, int m, float s) {
157145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        return new ICUTestDuration(sgn, -1, -1, d, h, m, s);
158145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    }
159145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    private static final ICUTestDuration newDuration(int sgn, int h, int m, float s) {
160145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        return new ICUTestDuration(sgn, -1, -1, -1, h, m, s);
161145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    }
162145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    private static final ICUTestDuration newDuration(int sgn, float s) {
163145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        return new ICUTestDuration(sgn, -1, -1, -1, -1, -1, s);
164145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer    }
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
167fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert     *
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public ICUDurationTest() {
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Basic test
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestBasics() {
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DurationFormat df;
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String expect;
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String formatted;
180fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        df = DurationFormat.getInstance(new ULocale("it"));
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatted = df.formatDurationFromNow(4096);
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expect = "fra quattro secondi";
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(!expect.equals(formatted)) {
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Expected " + expect + " but got " + formatted);
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("format duration -> " + formatted);
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
189fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatted = df.formatDurationFromNowTo(new Date(0));
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Calendar cal = Calendar.getInstance();
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int years = cal.get(Calendar.YEAR) - 1970; // year of Date(0)
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expect = years + " anni fa";
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(!expect.equals(formatted)) {
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Expected " + expect + " but got " + formatted);
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("format date  -> " + formatted);
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
199fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatted = df.formatDurationFrom(1000*3600*24, new Date(0).getTime());
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expect = "fra un giorno";
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(!expect.equals(formatted)) {
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Expected " + expect + " but got " + formatted);
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("format date from -> " + formatted);
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatted = df.format(new Long(1000*3600*24*2));
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expect = "fra due giorni";
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(!expect.equals(formatted)) {
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("Expected " + expect + " but got " + formatted);
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("format long obj -> " + formatted);
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestSimpleXMLDuration() {
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Duration d;
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DurationFormat df;
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String out;
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String expected;
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String expected2;
224fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // test 1
226145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        d = newDuration(1, 2, 46, 40);  // "PT2H46M40S"
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        df = DurationFormat.getInstance(new ULocale("en"));
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expected = "2 hours, 46 minutes, and 40 seconds";
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        out = df.format(d);
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(out.equals(expected)) {
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("out=expected: " + expected + " from " + d);
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: got " + out + " wanted " + expected + " from " + d);
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
235fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // test 2
237145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        d = newDuration(10000);
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        df = DurationFormat.getInstance(new ULocale("en"));
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expected = "10 seconds";
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        out = df.format(d);
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(out.equals(expected)) {
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("out=expected: " + expected + " from " + d);
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: got " + out + " wanted " + expected + " from " + d);
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // test 3
247145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        d = newDuration(1, 0, 0, 0, 10);  // "P0DT0H0M10.0S"
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        df = DurationFormat.getInstance(new ULocale("en"));
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expected = "10 seconds";
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        out = df.format(d);
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(out.equals(expected)) {
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("out=expected: " + expected + " from " + d);
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: got " + out + " wanted " + expected + " from " + d);
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // test 4
257145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        d = newDuration(86400000);
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        df = DurationFormat.getInstance(new ULocale("en"));
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expected = "1 day, 0 hours, 0 minutes, and 0 seconds";
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expected2 = "1 day and 0 seconds"; // This is the expected result for Windows with IBM JRE6
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        out = df.format(d);
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(out.equals(expected)) {
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("out=expected: " + expected + " from " + d);
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(out.equals(expected2)){
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("WARNING: got " + out + " wanted " + expected + " from " + d);
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else{
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                errln("FAIL: got " + out + " wanted " + expected + " from " + d);
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2732d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestXMLDuration() {
275145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        final class TestCase {
276145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            final String localeString;
277145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            final ULocale locale;
278145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            final String durationString;
279145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            final Duration duration;
280145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            final String expected;
281145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
282145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            TestCase(String loc, String ds, Duration d, String exp) {
283145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                localeString = loc;
284145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                locale = new ULocale(loc);
285145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                durationString = ds;
286145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                duration = d;
287145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer                expected = exp;
288145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            }
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
290145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
291145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        TestCase cases[] = {
292145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT10.00099S",  newDuration(1, 10.00099F),  "10 seconds"),
293145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "#10000",       newDuration(10000),         "10 seconds"),
294145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "-PT10.00099S", newDuration(-1, 10.00099F), "10 seconds"),
295145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "#-10000",      newDuration(-10000),        "10 seconds"),
296145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
297145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            // from BD req's
298145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT2H46M40S",   newDuration(1, 2, 46, 40),  "2 hours, 46 minutes, and 40 seconds"),
299145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("it", "PT2H46M40S",   newDuration(1, 2, 46, 40),  "due ore, 46 minuti e 40 secondi"),
300145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
301145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            // more cases
302145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT10S",        newDuration(1, 10),         "10 seconds"),
303145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT88M70S",     newDuration(1, -1, 88, 70), "88 minutes and 70 seconds"),
304145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT10.100S",    newDuration(1, 10.100F),    "10 seconds and 100 milliseconds"),
305145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "-PT10S",       newDuration(-1, 10),        "10 seconds"),
306145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            new TestCase("en", "PT0H5M0S",     newDuration(1, 0, 5, 0),    "5 minutes and 0 seconds")
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
308145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
309145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer        for (TestCase tc : cases) {
310145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            String loc = tc.localeString;
311145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            String from = tc.durationString;
312145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            String to = tc.expected;
313145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
314145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            ULocale locale = tc.locale;
315145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer            Duration d = tc.duration;
316145e2c500373e5096c471c25be1dcfd3585e1b46Markus Scherer
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            DurationFormat df = DurationFormat.getInstance(locale);
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String output = df.format(d);
319fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(output.equals(to)) {
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("SUCCESS: locale: " + loc + ", from " + from + " ["+d.toString()+"] " +" to " + to + "= " + output);
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                logln("FAIL: locale: " + loc + ", from " + from + " ["+d.toString()+"] " +": expected " + to + " got " + output);
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestBadObjectError() {
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Runtime r = Runtime.getRuntime();
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DurationFormat df = DurationFormat.getInstance(new ULocale("en"));
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String output = null;
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            output = df.format(r);
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: did NOT get IllegalArgumentException! Should have. Formatted Runtime as " + output + " ???");
3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (IllegalArgumentException iae) {
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("PASS: expected: Caught iae: " + iae.toString() );
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // try a second time, because it is a different code path for java < 1.5
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            output = df.format(r);
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: [#2] did NOT get IllegalArgumentException! Should have. Formatted Runtime as " + output + " ???");
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (IllegalArgumentException iae) {
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("PASS: [#2] expected: Caught iae: " + iae.toString() );
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3492d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestBadLocaleError() {
3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            DurationFormat df = DurationFormat.getInstance(new ULocale("und"));
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            df.format(new Date());
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("Should have thrown err.");
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("failed, should have thrown err.");
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch(MissingResourceException mre) {
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln("PASS: caught missing resource exception on locale 'und'");
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            logln(mre.toString());
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3622d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestResourceWithCalendar() {
3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DurationFormat df = DurationFormat.getInstance(new ULocale("th@calendar=buddhist"));
3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // should pass, but return a default formatter for th.
3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (df == null) {
3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("FAIL: null DurationFormat returned.");
3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
370fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* Tests the class
3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      DurationFormat
3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestDurationFormat(){
3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("serial")
3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        class TestDurationFormat extends DurationFormat {
378fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert            @Override
3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public StringBuffer format(Object object, StringBuffer toAppend, FieldPosition pos) {return null;}
380fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert            @Override
3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public String formatDurationFrom(long duration, long referenceDate) {return null;}
382fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert            @Override
3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public String formatDurationFromNow(long duration) {return null;}
384fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert            @Override
3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public String formatDurationFromNowTo(Date targetDate) {return null;}
3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            public TestDurationFormat() {super();}
387fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
389fe77e7203e518f62b5bd8e8c603bca361e9cf47bFredrik Roubert
3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Tests the constructor and the following method
3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //      public Object parseObject(String source, ParsePosition pos)
3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try{
3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            TestDurationFormat tdf = new TestDurationFormat();
3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tdf.parseObject("",null);
3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            errln("DurationFormat.parseObjet(String,ParsePosition) was " +
3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    "to return an exception for an unsupported operation.");
3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch(Exception e){}
3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Test
4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void TestFromNowTo() {
4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        class TestCase {
4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ULocale locale;
4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int diffInSeconds;
4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String expected;
4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            TestCase(ULocale locale, int diffInSeconds, String expected) {
4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.locale = locale;
4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.diffInSeconds = diffInSeconds;
4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.expected = expected;
4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        TestCase[] testCases = {
4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, 10, "10 seconds from now"),
4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, -10, "10 seconds ago"),
4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, -1800, "30 minutes ago"),
4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, 3600, "1 hour from now"),
4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, 10000, "2 hours from now"),
4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.US, -20000, "5 hours ago"),
4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.FRANCE, -1800, "il y a 30 minutes"),
4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new TestCase(ULocale.ITALY, 10000, "fra due ore"),
4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        };
4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        final long delayMS = 10;    // Safe margin - 10 milliseconds
4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    // See the comments below
4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (TestCase test : testCases) {
4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            DurationFormat df = DurationFormat.getInstance(test.locale);
4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            long target = System.currentTimeMillis() + test.diffInSeconds * 1000;
4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Need some adjustment because time difference is recalculated in
4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // formatDurationFromNowTo method.
4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            target = test.diffInSeconds > 0 ? target + delayMS : target - delayMS;
4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Date d = new Date(target);
4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String result = df.formatDurationFromNowTo(d);
4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            assertEquals("TestFromNowTo (" + test.locale + ", " + test.diffInSeconds + "sec)",
4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    test.expected, result);
4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
438