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