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.ResolverStyle; 73 import java.time.temporal.TemporalAccessor; 74 75 import org.testng.annotations.DataProvider; 76 import org.testng.annotations.Test; 77 78 /* 79 * @test 80 * @bug 8166138 81 */ 82 83 /** 84 * Test DateTimeFormatterBuilder.appendInstant(). 85 */ 86 @Test 87 public class TCKInstantPrinterParser { 88 89 @DataProvider(name="printGrouped") 90 Object[][] data_printGrouped() { 91 return new Object[][] { 92 {0, 0, "1970-01-01T00:00:00Z"}, 93 94 {-1, 0, "1969-12-31T23:59:59Z"}, 95 {1, 0, "1970-01-01T00:00:01Z"}, 96 {60, 0, "1970-01-01T00:01:00Z"}, 97 {3600, 0, "1970-01-01T01:00:00Z"}, 98 {86400, 0, "1970-01-02T00:00:00Z"}, 99 100 {182, 2, "1970-01-01T00:03:02.000000002Z"}, 101 {182, 20, "1970-01-01T00:03:02.000000020Z"}, 102 {182, 200, "1970-01-01T00:03:02.000000200Z"}, 103 {182, 2000, "1970-01-01T00:03:02.000002Z"}, 104 {182, 20000, "1970-01-01T00:03:02.000020Z"}, 105 {182, 200000, "1970-01-01T00:03:02.000200Z"}, 106 {182, 2000000, "1970-01-01T00:03:02.002Z"}, 107 {182, 20000000, "1970-01-01T00:03:02.020Z"}, 108 {182, 200000000, "1970-01-01T00:03:02.200Z"}, 109 110 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"}, 111 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00Z"}, 112 }; 113 } 114 115 @Test(dataProvider="printGrouped") 116 public void test_print_grouped(long instantSecs, int nano, String expected) { 117 Instant instant = Instant.ofEpochSecond(instantSecs, nano); 118 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant().toFormatter(); 119 assertEquals(f.format(instant), expected); 120 } 121 122 //----------------------------------------------------------------------- 123 @DataProvider(name="printDigits") 124 Object[][] data_printDigits() { 125 return new Object[][] { 126 {-1, 0, 0, "1970-01-01T00:00:00Z"}, 127 {0, 0, 0, "1970-01-01T00:00:00Z"}, 128 {1, 0, 0, "1970-01-01T00:00:00.0Z"}, 129 {3, 0, 0, "1970-01-01T00:00:00.000Z"}, 130 {9, 0, 0, "1970-01-01T00:00:00.000000000Z"}, 131 132 {-1, -1, 0, "1969-12-31T23:59:59Z"}, 133 {-1, 1, 0, "1970-01-01T00:00:01Z"}, 134 {-1, 60, 0, "1970-01-01T00:01:00Z"}, 135 {-1, 3600, 0, "1970-01-01T01:00:00Z"}, 136 {-1, 86400, 0, "1970-01-02T00:00:00Z"}, 137 138 {-1, 182, 2, "1970-01-01T00:03:02.000000002Z"}, 139 {-1, 182, 20, "1970-01-01T00:03:02.00000002Z"}, 140 {-1, 182, 200, "1970-01-01T00:03:02.0000002Z"}, 141 {-1, 182, 2000, "1970-01-01T00:03:02.000002Z"}, 142 {-1, 182, 20000, "1970-01-01T00:03:02.00002Z"}, 143 {-1, 182, 200000, "1970-01-01T00:03:02.0002Z"}, 144 {-1, 182, 2000000, "1970-01-01T00:03:02.002Z"}, 145 {-1, 182, 20000000, "1970-01-01T00:03:02.02Z"}, 146 {-1, 182, 200000000, "1970-01-01T00:03:02.2Z"}, 147 148 {0, 182, 2, "1970-01-01T00:03:02Z"}, 149 {0, 182, 20, "1970-01-01T00:03:02Z"}, 150 {0, 182, 200, "1970-01-01T00:03:02Z"}, 151 {0, 182, 2000, "1970-01-01T00:03:02Z"}, 152 {0, 182, 20000, "1970-01-01T00:03:02Z"}, 153 {0, 182, 200000, "1970-01-01T00:03:02Z"}, 154 {0, 182, 2000000, "1970-01-01T00:03:02Z"}, 155 {0, 182, 20000000, "1970-01-01T00:03:02Z"}, 156 {0, 182, 200000000, "1970-01-01T00:03:02Z"}, 157 158 {1, 182, 2, "1970-01-01T00:03:02.0Z"}, 159 {1, 182, 20, "1970-01-01T00:03:02.0Z"}, 160 {1, 182, 200, "1970-01-01T00:03:02.0Z"}, 161 {1, 182, 2000, "1970-01-01T00:03:02.0Z"}, 162 {1, 182, 20000, "1970-01-01T00:03:02.0Z"}, 163 {1, 182, 200000, "1970-01-01T00:03:02.0Z"}, 164 {1, 182, 2000000, "1970-01-01T00:03:02.0Z"}, 165 {1, 182, 20000000, "1970-01-01T00:03:02.0Z"}, 166 {1, 182, 200000000, "1970-01-01T00:03:02.2Z"}, 167 168 {3, 182, 2, "1970-01-01T00:03:02.000Z"}, 169 {3, 182, 20, "1970-01-01T00:03:02.000Z"}, 170 {3, 182, 200, "1970-01-01T00:03:02.000Z"}, 171 {3, 182, 2000, "1970-01-01T00:03:02.000Z"}, 172 {3, 182, 20000, "1970-01-01T00:03:02.000Z"}, 173 {3, 182, 200000, "1970-01-01T00:03:02.000Z"}, 174 {3, 182, 2000000, "1970-01-01T00:03:02.002Z"}, 175 {3, 182, 20000000, "1970-01-01T00:03:02.020Z"}, 176 {3, 182, 200000000, "1970-01-01T00:03:02.200Z"}, 177 178 {9, 182, 2, "1970-01-01T00:03:02.000000002Z"}, 179 {9, 182, 20, "1970-01-01T00:03:02.000000020Z"}, 180 {9, 182, 200, "1970-01-01T00:03:02.000000200Z"}, 181 {9, 182, 2000, "1970-01-01T00:03:02.000002000Z"}, 182 {9, 182, 20000, "1970-01-01T00:03:02.000020000Z"}, 183 {9, 182, 200000, "1970-01-01T00:03:02.000200000Z"}, 184 {9, 182, 2000000, "1970-01-01T00:03:02.002000000Z"}, 185 {9, 182, 20000000, "1970-01-01T00:03:02.020000000Z"}, 186 {9, 182, 200000000, "1970-01-01T00:03:02.200000000Z"}, 187 188 {9, Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"}, 189 {9, Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"}, 190 }; 191 } 192 193 @Test(dataProvider="printDigits") 194 public void test_print_digits(int fractionalDigits, long instantSecs, int nano, String expected) { 195 Instant instant = Instant.ofEpochSecond(instantSecs, nano); 196 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(fractionalDigits).toFormatter(); 197 assertEquals(f.format(instant), expected); 198 } 199 200 //----------------------------------------------------------------------- 201 @DataProvider(name="parseDigits") 202 Object[][] data_parse_digits() { 203 return new Object[][] { 204 {0, 0, "1970-01-01T00:00:00Z"}, 205 {0, 0, "1970-01-01T00:00:00Z"}, 206 {0, 0, "1970-01-01T00:00:00.0Z"}, 207 {0, 0, "1970-01-01T00:00:00.000Z"}, 208 {0, 0, "1970-01-01T00:00:00.000000000Z"}, 209 210 {0, 0, "1970-01-01T00:00:00+00:00"}, 211 {0, 0, "1970-01-01T00:00:00+00:00"}, 212 {0, 0, "1970-01-01T00:00:00.0+00:00"}, 213 {0, 0, "1970-01-01T00:00:00.000+00:00"}, 214 215 {-1, 0, "1969-12-31T23:59:59Z"}, 216 {1, 0, "1970-01-01T00:00:01Z"}, 217 {60, 0, "1970-01-01T00:01:00Z"}, 218 {3600, 0, "1970-01-01T01:00:00Z"}, 219 {86400, 0, "1970-01-02T00:00:00Z"}, 220 221 {-1, 0, "1969-12-31T23:59:59+0000"}, 222 {1, 0, "1970-01-01T00:00:01+0000"}, 223 {60, 0, "1970-01-01T00:01:00+0000"}, 224 {3600, 0, "1970-01-01T01:00:00+0000"}, 225 {86400, 0, "1970-01-02T00:00:00+0000"}, 226 227 {182, 234000000, "1970-01-01T00:03:02.234Z"}, 228 {182, 234000000, "1970-01-01T00:03:02.2340Z"}, 229 {182, 234000000, "1970-01-01T00:03:02.23400Z"}, 230 {182, 234000000, "1970-01-01T00:03:02.234000Z"}, 231 {182, 234000000, "1970-01-01T00:03:02.234000000Z"}, 232 233 {182, 234000000, "1970-01-01T00:03:02.234+00"}, 234 {182, 234000000, "1970-01-01T00:03:02.2340+00"}, 235 {182, 234000000, "1970-01-01T00:03:02.23400+00"}, 236 {182, 234000000, "1970-01-01T00:03:02.234000+00"}, 237 238 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789Z"}, 239 240 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"}, 241 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"}, 242 }; 243 } 244 245 @Test(dataProvider="parseDigits") 246 public void test_parse_digitsMinusOne(long instantSecs, int nano, String input) { 247 Instant expected = Instant.ofEpochSecond(instantSecs, nano); 248 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 249 assertEquals(f.parse(input, Instant::from), expected); 250 assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 251 assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 252 } 253 254 @Test(dataProvider="parseDigits") 255 public void test_parse_digitsNine(long instantSecs, int nano, String input) { 256 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(9).toFormatter(); 257 if (input.charAt(input.length() - 11) == '.') { 258 Instant expected = Instant.ofEpochSecond(instantSecs, nano); 259 assertEquals(f.parse(input, Instant::from), expected); 260 assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 261 assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 262 } else { 263 try { 264 f.parse(input, Instant::from); 265 fail(); 266 } catch (DateTimeException ex) { 267 // expected 268 } 269 } 270 } 271 272 @DataProvider(name="parseDigitsWithOffsets") 273 Object[][] data_parse_ninedigits() { 274 return new Object[][] { 275 {0, 0, "1970-01-01T00:00:00.000000000+00:00"}, 276 {0, 0, "1970-01-01T00:00:00.000000000+0000"}, 277 {0, 0, "1970-01-01T00:00:00.000000000+00"}, 278 279 {182, 234000000, "1970-01-01T00:03:02.234000000+00:00"}, 280 {182, 234000000, "1970-01-01T00:03:02.234000000+0000"}, 281 {182, 234000000, "1970-01-01T00:03:02.234000000+00"}, 282 283 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789+00:00"}, 284 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789+0000"}, 285 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789+00"}, 286 287 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999+00:00"}, 288 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999+0000"}, 289 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999+00"}, 290 291 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000+00:00"}, 292 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000+0000"}, 293 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000+00"}, 294 }; 295 } 296 297 @Test(dataProvider="parseDigitsWithOffsets") 298 public void test_parse_digitsNine_withOffset(long instantSecs, int nano, String input) { 299 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(9).toFormatter(); 300 Instant expected = Instant.ofEpochSecond(instantSecs, nano); 301 assertEquals(f.parse(input, Instant::from), expected); 302 assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 303 assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 304 } 305 306 @Test 307 public void test_parse_endOfDay() { 308 Instant expected = OffsetDateTime.of(1970, 2, 4, 0, 0, 0, 0, ZoneOffset.UTC).toInstant(); 309 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 310 for (ResolverStyle style : ResolverStyle.values()) { 311 TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T24:00:00Z"); 312 assertEquals(parsed.query(Instant::from), expected); 313 assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 314 assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 315 } 316 } 317 318 @Test 319 public void test_parse_leapSecond() { 320 Instant expected = OffsetDateTime.of(1970, 2, 3, 23, 59, 59, 123456789, ZoneOffset.UTC).toInstant(); 321 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 322 for (ResolverStyle style : ResolverStyle.values()) { 323 TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T23:59:60.123456789Z"); 324 assertEquals(parsed.query(Instant::from), expected); 325 assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 326 assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.TRUE); 327 } 328 } 329 330 //----------------------------------------------------------------------- 331 @Test(expectedExceptions=IllegalArgumentException.class) 332 public void test_appendInstant_tooSmall() { 333 new DateTimeFormatterBuilder().appendInstant(-2); 334 } 335 336 @Test(expectedExceptions=IllegalArgumentException.class) 337 public void test_appendInstant_tooBig() { 338 new DateTimeFormatterBuilder().appendInstant(10); 339 } 340 341 //------------------------------------------------------------------------ 342 @Test 343 public void test_equality_withAndWithoutOffset() { 344 Instant instant1 = Instant.parse("2018-09-12T16:45:51+00:00"); 345 Instant instant2 = Instant.parse("2018-09-12T16:45:51Z"); 346 assertEquals(instant2, instant1); 347 } 348 349 }