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 209 {0, 0, "1970-01-01T00:00:00+00:00"}, 210 {0, 0, "1970-01-01T05:30:00+05:30"}, 211 {0, 0, "1970-01-01T01:00:00.0+01:00"}, 212 213 {-1, 0, "1969-12-31T23:59:59Z"}, 214 {1, 0, "1970-01-01T00:00:01Z"}, 215 {60, 0, "1970-01-01T00:01:00Z"}, 216 {3600, 0, "1970-01-01T01:00:00Z"}, 217 {86400, 0, "1970-01-02T00:00:00Z"}, 218 219 {-1, 0, "1969-12-31T23:59:59+00:00"}, 220 {1, 0, "1970-01-01T05:30:01+05:30"}, 221 {60, 0, "1969-12-31T19:01:00-05:00"}, 222 {3600, 0, "1970-01-01T06:30:00+05:30"}, 223 {86400, 0, "1970-01-01T19:00:00-05:00"}, 224 225 {182, 234000000, "1970-01-01T00:03:02.234Z"}, 226 {182, 234000000, "1970-01-01T00:03:02.2340Z"}, 227 {182, 234000000, "1970-01-01T00:03:02.23400Z"}, 228 {182, 234000000, "1970-01-01T00:03:02.234000Z"}, 229 230 {182, 234000000, "1970-01-01T00:03:02.234+00:00"}, 231 {182, 234000000, "1970-01-01T05:33:02.2340+05:30"}, 232 {182, 234000000, "1969-12-31T19:03:02.23400-05:00"}, 233 {182, 234000000, "1970-01-01T00:03:02.234000+00:00"}, 234 235 }; 236 } 237 238 @Test(dataProvider="parseDigits") 239 public void test_parse_digitsMinusOne(long instantSecs, int nano, String input) { 240 Instant expected = Instant.ofEpochSecond(instantSecs, nano); 241 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 242 assertEquals(f.parse(input, Instant::from), expected); 243 assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 244 assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 245 } 246 247 @DataProvider(name="parseNineDigits") 248 Object[][] data_parse_ninedigits() { 249 return new Object[][] { 250 {0, 0, "1970-01-01T00:00:00.000000000Z"}, 251 {0, 0, "1970-01-01T05:30:00.000000000+05:30"}, 252 253 {182, 234000000, "1970-01-01T00:03:02.234000000Z"}, 254 {182, 234000000, "1970-01-01T01:03:02.234000000+01:00"}, 255 256 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-01T23:59:59.123456789Z"}, 257 {((23 * 60) + 59) * 60 + 59, 123456789, "1970-01-02T05:29:59.123456789+05:30"}, 258 259 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999Z"}, 260 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000Z"}, 261 {Instant.MAX.getEpochSecond(), 999999999, "+1000000000-12-31T23:59:59.999999999+00:00"}, 262 {Instant.MIN.getEpochSecond(), 0, "-1000000000-01-01T00:00:00.000000000+00:00"}, 263 }; 264 } 265 266 @Test(dataProvider="parseNineDigits") 267 public void test_parse_digitsNine(long instantSecs, int nano, String input) { 268 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(9).toFormatter(); 269 Instant expected = Instant.ofEpochSecond(instantSecs, nano); 270 assertEquals(f.parse(input, Instant::from), expected); 271 assertEquals(f.parse(input).query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 272 assertEquals(f.parse(input).query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 273 } 274 275 @Test 276 public void test_parse_endOfDay() { 277 Instant expected = OffsetDateTime.of(1970, 2, 4, 0, 0, 0, 0, ZoneOffset.UTC).toInstant(); 278 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 279 for (ResolverStyle style : ResolverStyle.values()) { 280 TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T24:00:00Z"); 281 assertEquals(parsed.query(Instant::from), expected); 282 assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 283 assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.FALSE); 284 } 285 } 286 287 @Test 288 public void test_parse_leapSecond() { 289 Instant expected = OffsetDateTime.of(1970, 2, 3, 23, 59, 59, 123456789, ZoneOffset.UTC).toInstant(); 290 DateTimeFormatter f = new DateTimeFormatterBuilder().appendInstant(-1).toFormatter(); 291 for (ResolverStyle style : ResolverStyle.values()) { 292 TemporalAccessor parsed = f.withResolverStyle(style).parse("1970-02-03T23:59:60.123456789Z"); 293 assertEquals(parsed.query(Instant::from), expected); 294 assertEquals(parsed.query(DateTimeFormatter.parsedExcessDays()), Period.ZERO); 295 assertEquals(parsed.query(DateTimeFormatter.parsedLeapSecond()), Boolean.TRUE); 296 } 297 } 298 299 //----------------------------------------------------------------------- 300 @Test(expectedExceptions=IllegalArgumentException.class) 301 public void test_appendInstant_tooSmall() { 302 new DateTimeFormatterBuilder().appendInstant(-2); 303 } 304 305 @Test(expectedExceptions=IllegalArgumentException.class) 306 public void test_appendInstant_tooBig() { 307 new DateTimeFormatterBuilder().appendInstant(10); 308 } 309 310 //------------------------------------------------------------------------ 311 @Test 312 public void test_equality() { 313 Instant instant1 = Instant.parse("2018-09-12T22:15:51+05:30"); 314 Instant instant2 = Instant.parse("2018-09-12T16:45:51Z"); 315 assertEquals(instant2, instant1); 316 } 317 318 }