1 /*
2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * This file is available under and governed by the GNU General Public
26  * License version 2 only, as published by the Free Software Foundation.
27  * However, the following notice accompanied the original version of this
28  * file:
29  *
30  * Copyright (c) 2010-2013, Stephen Colebourne & Michael Nascimento Santos
31  *
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions are met:
36  *
37  *  * Redistributions of source code must retain the above copyright notice,
38  *    this list of conditions and the following disclaimer.
39  *
40  *  * Redistributions in binary form must reproduce the above copyright notice,
41  *    this list of conditions and the following disclaimer in the documentation
42  *    and/or other materials provided with the distribution.
43  *
44  *  * Neither the name of JSR-310 nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59  */
60 package tck.java.time.format;
61 
62 import static org.testng.Assert.assertEquals;
63 import static org.testng.Assert.fail;
64 
65 import java.time.DateTimeException;
66 import java.time.Instant;
67 import java.time.OffsetDateTime;
68 import java.time.Period;
69 import java.time.ZoneOffset;
70 import java.time.format.DateTimeFormatter;
71 import java.time.format.DateTimeFormatterBuilder;
72 import java.time.format.DateTimeParseException;
73 import java.time.format.ResolverStyle;
74 import java.time.temporal.TemporalAccessor;
75 
76 import org.testng.annotations.DataProvider;
77 import org.testng.annotations.Test;
78 
79 /*
80  * @test
81  * @bug 8166138
82  */
83 
84 /**
85  * Test DateTimeFormatterBuilder.appendInstant().
86  */
87 @Test
88 public class TCKInstantPrinterParser {
89 
90     @DataProvider(name="printGrouped")
data_printGrouped()91     Object[][] data_printGrouped() {
92         return new Object[][] {
93                 {0, 0, "1970-01-01T00:00:00Z"},
94 
95                 {-1, 0, "1969-12-31T23:59:59Z"},
96                 {1, 0, "1970-01-01T00:00:01Z"},
97                 {60, 0, "1970-01-01T00:01:00Z"},
98                 {3600, 0, "1970-01-01T01:00:00Z"},
99                 {86400, 0, "1970-01-02T00:00:00Z"},
100 
101                 {182, 2, "1970-01-01T00:03:02.000000002Z"},
102                 {182, 20, "1970-01-01T00:03:02.000000020Z"},
103                 {182, 200, "1970-01-01T00:03:02.000000200Z"},
104                 {182, 2000, "1970-01-01T00:03:02.000002Z"},
105                 {182, 20000, "1970-01-01T00:03:02.000020Z"},
106                 {182, 200000, "1970-01-01T00:03:02.000200Z"},
107                 {182, 2000000, "1970-01-01T00:03:02.002Z"},
108                 {182, 20000000, "1970-01-01T00:03:02.020Z"},
109                 {182, 200000000, "1970-01-01T00:03:02.200Z"},
110 
111                 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
112                 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00Z"},
113         };
114     }
115 
116     @Test(dataProvider="printGrouped")
test_print_grouped(long instantSecs, int nano, String expected)117     public void test_print_grouped(long instantSecs, int nano, String expected) {
118         Instant instant = Instant.ofEpochSecond(instantSecs, nano);
119         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant().toFormatter();
120         assertEquals(f.format(instant), expected);
121     }
122 
123     //-----------------------------------------------------------------------
124     @DataProvider(name="printDigits")
data_printDigits()125     Object[][] data_printDigits() {
126         return new Object[][] {
127                 {-1, 0, 0, "1970-01-01T00:00:00Z"},
128                 {0, 0, 0, "1970-01-01T00:00:00Z"},
129                 {1, 0, 0, "1970-01-01T00:00:00.0Z"},
130                 {3, 0, 0, "1970-01-01T00:00:00.000Z"},
131                 {9, 0, 0, "1970-01-01T00:00:00.000000000Z"},
132 
133                 {-1, -1, 0, "1969-12-31T23:59:59Z"},
134                 {-1, 1, 0, "1970-01-01T00:00:01Z"},
135                 {-1, 60, 0, "1970-01-01T00:01:00Z"},
136                 {-1, 3600, 0, "1970-01-01T01:00:00Z"},
137                 {-1, 86400, 0, "1970-01-02T00:00:00Z"},
138 
139                 {-1, 182, 2, "1970-01-01T00:03:02.000000002Z"},
140                 {-1, 182, 20, "1970-01-01T00:03:02.00000002Z"},
141                 {-1, 182, 200, "1970-01-01T00:03:02.0000002Z"},
142                 {-1, 182, 2000, "1970-01-01T00:03:02.000002Z"},
143                 {-1, 182, 20000, "1970-01-01T00:03:02.00002Z"},
144                 {-1, 182, 200000, "1970-01-01T00:03:02.0002Z"},
145                 {-1, 182, 2000000, "1970-01-01T00:03:02.002Z"},
146                 {-1, 182, 20000000, "1970-01-01T00:03:02.02Z"},
147                 {-1, 182, 200000000, "1970-01-01T00:03:02.2Z"},
148 
149                 {0, 182, 2, "1970-01-01T00:03:02Z"},
150                 {0, 182, 20, "1970-01-01T00:03:02Z"},
151                 {0, 182, 200, "1970-01-01T00:03:02Z"},
152                 {0, 182, 2000, "1970-01-01T00:03:02Z"},
153                 {0, 182, 20000, "1970-01-01T00:03:02Z"},
154                 {0, 182, 200000, "1970-01-01T00:03:02Z"},
155                 {0, 182, 2000000, "1970-01-01T00:03:02Z"},
156                 {0, 182, 20000000, "1970-01-01T00:03:02Z"},
157                 {0, 182, 200000000, "1970-01-01T00:03:02Z"},
158 
159                 {1, 182, 2, "1970-01-01T00:03:02.0Z"},
160                 {1, 182, 20, "1970-01-01T00:03:02.0Z"},
161                 {1, 182, 200, "1970-01-01T00:03:02.0Z"},
162                 {1, 182, 2000, "1970-01-01T00:03:02.0Z"},
163                 {1, 182, 20000, "1970-01-01T00:03:02.0Z"},
164                 {1, 182, 200000, "1970-01-01T00:03:02.0Z"},
165                 {1, 182, 2000000, "1970-01-01T00:03:02.0Z"},
166                 {1, 182, 20000000, "1970-01-01T00:03:02.0Z"},
167                 {1, 182, 200000000, "1970-01-01T00:03:02.2Z"},
168 
169                 {3, 182, 2, "1970-01-01T00:03:02.000Z"},
170                 {3, 182, 20, "1970-01-01T00:03:02.000Z"},
171                 {3, 182, 200, "1970-01-01T00:03:02.000Z"},
172                 {3, 182, 2000, "1970-01-01T00:03:02.000Z"},
173                 {3, 182, 20000, "1970-01-01T00:03:02.000Z"},
174                 {3, 182, 200000, "1970-01-01T00:03:02.000Z"},
175                 {3, 182, 2000000, "1970-01-01T00:03:02.002Z"},
176                 {3, 182, 20000000, "1970-01-01T00:03:02.020Z"},
177                 {3, 182, 200000000, "1970-01-01T00:03:02.200Z"},
178 
179                 {9, 182, 2, "1970-01-01T00:03:02.000000002Z"},
180                 {9, 182, 20, "1970-01-01T00:03:02.000000020Z"},
181                 {9, 182, 200, "1970-01-01T00:03:02.000000200Z"},
182                 {9, 182, 2000, "1970-01-01T00:03:02.000002000Z"},
183                 {9, 182, 20000, "1970-01-01T00:03:02.000020000Z"},
184                 {9, 182, 200000, "1970-01-01T00:03:02.000200000Z"},
185                 {9, 182, 2000000, "1970-01-01T00:03:02.002000000Z"},
186                 {9, 182, 20000000, "1970-01-01T00:03:02.020000000Z"},
187                 {9, 182, 200000000, "1970-01-01T00:03:02.200000000Z"},
188 
189                 {9, Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
190                 {9, Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"},
191         };
192     }
193 
194     @Test(dataProvider="printDigits")
test_print_digits(int fractionalDigits, long instantSecs, int nano, String expected)195     public void test_print_digits(int fractionalDigits, long instantSecs, int nano, String expected) {
196         Instant instant = Instant.ofEpochSecond(instantSecs, nano);
197         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(fractionalDigits).toFormatter();
198         assertEquals(f.format(instant), expected);
199     }
200 
201     //-----------------------------------------------------------------------
202     @DataProvider(name="parseDigits")
data_parse_digits()203     Object[][] data_parse_digits() {
204         return new Object[][] {
205                 {0, 0, "1970-01-01T00:00:00Z"},
206                 {0, 0, "1970-01-01T00:00:00Z"},
207                 {0, 0, "1970-01-01T00:00:00.0Z"},
208                 {0, 0, "1970-01-01T00:00:00.000Z"},
209 
210                 {0, 0, "1970-01-01T00:00:00+00:00"},
211                 {0, 0, "1970-01-01T05:30:00+05:30"},
212                 {0, 0, "1970-01-01T01:00:00.0+01:00"},
213 
214                 {-1, 0, "1969-12-31T23:59:59Z"},
215                 {1, 0, "1970-01-01T00:00:01Z"},
216                 {60, 0, "1970-01-01T00:01:00Z"},
217                 {3600, 0, "1970-01-01T01:00:00Z"},
218                 {86400, 0, "1970-01-02T00:00:00Z"},
219 
220                 {-1, 0, "1969-12-31T23:59:59+00:00"},
221                 {1, 0, "1970-01-01T05:30:01+05:30"},
222                 {60, 0, "1969-12-31T19:01:00-05:00"},
223                 {3600, 0, "1970-01-01T06:30:00+05:30"},
224                 {86400, 0, "1970-01-01T19:00:00-05:00"},
225 
226                 {182, 234000000, "1970-01-01T00:03:02.234Z"},
227                 {182, 234000000, "1970-01-01T00:03:02.2340Z"},
228                 {182, 234000000, "1970-01-01T00:03:02.23400Z"},
229                 {182, 234000000, "1970-01-01T00:03:02.234000Z"},
230 
231                 {182, 234000000, "1970-01-01T00:03:02.234+00:00"},
232                 {182, 234000000, "1970-01-01T05:33:02.2340+05:30"},
233                 {182, 234000000, "1969-12-31T19:03:02.23400-05:00"},
234                 {182, 234000000, "1970-01-01T00:03:02.234000+00:00"},
235 
236         };
237     }
238 
239     @Test(dataProvider="parseDigits")
test_parse_digitsMinusOne(long instantSecs, int nano, String input)240     public void test_parse_digitsMinusOne(long instantSecs, int nano, String input) {
241         Instant expected = Instant.ofEpochSecond(instantSecs, nano);
242         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
243         assertEquals(f.parse(input, Instant::from), expected);
244         assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
245         assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
246     }
247 
248     @DataProvider(name="parseNineDigits")
data_parse_ninedigits()249     Object[][] data_parse_ninedigits() {
250         return new Object[][] {
251                 {0, 0, "1970-01-01T00:00:00.000000000Z"},
252                 {0, 0, "1970-01-01T05:30:00.000000000+05:30"},
253 
254                 {182, 234000000, "1970-01-01T00:03:02.234000000Z"},
255                 {182, 234000000, "1970-01-01T01:03:02.234000000+01:00"},
256 
257                 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789Z"},
258                 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-02T05:29:59.123456789+05:30"},
259 
260                 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"},
261                 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"},
262                 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999+00:00"},
263                 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000+00:00"},
264         };
265     }
266 
267     @Test(dataProvider="parseNineDigits")
test_parse_digitsNine(long instantSecs, int nano, String input)268     public void test_parse_digitsNine(long instantSecs, int nano, String input) {
269         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(9).toFormatter();
270         Instant expected = Instant.ofEpochSecond(instantSecs, nano);
271         assertEquals(f.parse(input, Instant::from), expected);
272         assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
273         assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
274     }
275 
276     @DataProvider(name="parseMaxMinInstant")
data_parse_MaxMinInstant()277     Object[][] data_parse_MaxMinInstant() {
278         return new Object[][] {
279                 {"+1000000000-12-31T23:59:59.999999999-01:00"},
280                 {"-1000000000-01-01T00:00:00.000000000+01:00"}
281         };
282     }
283 
284     @Test(dataProvider="parseMaxMinInstant", expectedExceptions=DateTimeParseException.class)
test_invalid_Instant(String input)285     public void test_invalid_Instant(String input) {
286         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
287         f.parse(input, Instant::from);
288     }
289 
290     @Test
test_parse_endOfDay()291     public void test_parse_endOfDay() {
292         Instant expected = OffsetDateTime.of(1970, 2, 4, 0, 0, 0, 0, ZoneOffset.UTC).toInstant();
293         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
294         for (ResolverStyle style : ResolverStyle.values()) {
295             TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T24:00:00Z");
296             assertEquals(parsed.query(Instant::from), expected);
297             assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
298             assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE);
299         }
300     }
301 
302     @Test
test_parse_leapSecond()303     public void test_parse_leapSecond() {
304         Instant expected = OffsetDateTime.of(1970, 2, 3, 23, 59, 59, 123456789, ZoneOffset.UTC).toInstant();
305         DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter();
306         for (ResolverStyle style : ResolverStyle.values()) {
307             TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T23:59:60.123456789Z");
308             assertEquals(parsed.query(Instant::from), expected);
309             assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO);
310             assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.TRUE);
311         }
312     }
313 
314     //-----------------------------------------------------------------------
315     @Test(expectedExceptions=IllegalArgumentException.class)
test_appendInstant_tooSmall()316     public void test_appendInstant_tooSmall() {
317         new DateTimeFormatterBuilder().appendInstant(-2);
318     }
319 
320     @Test(expectedExceptions=IllegalArgumentException.class)
test_appendInstant_tooBig()321     public void test_appendInstant_tooBig() {
322         new DateTimeFormatterBuilder().appendInstant(10);
323     }
324 
325     //------------------------------------------------------------------------
326     @Test
test_equality()327     public void test_equality() {
328         Instant instant1 = Instant.parse("2018-09-12T22:15:51+05:30");
329         Instant instant2 = Instant.parse("2018-09-12T16:45:51Z");
330         assertEquals(instant2, instant1);
331     }
332 
333 }
334