1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.commons.time;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.junit.jupiter.api.Assertions.*;
21
22 import java.time.*;
23 import java.time.temporal.*;
24 import java.util.Date;
25
26 import org.apache.juneau.*;
27 import org.apache.juneau.utest.utils.FakeTimeProvider;
28 import org.junit.jupiter.api.*;
29 import org.junit.jupiter.params.*;
30 import org.junit.jupiter.params.provider.*;
31
32
33
34
35 class GranularZonedDateTime_Test extends TestBase {
36
37
38
39
40
41 @Test
42 void b01_constructorWithZonedDateTime() {
43 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
44 var gdt = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
45 assertEquals(zdt, gdt.zdt);
46 assertEquals(ChronoField.HOUR_OF_DAY, gdt.precision);
47 }
48
49 @Test
50 void b02_constructorWithZonedDateTime_preservesZone() {
51 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("America/New_York"));
52 var gdt = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
53 assertEquals(ZoneId.of("America/New_York"), gdt.zdt.getZone());
54 }
55
56 @Test
57 void b03_constructorWithZonedDateTime_preservesPrecision() {
58 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
59 var gdt = new GranularZonedDateTime(zdt, ChronoField.MINUTE_OF_HOUR);
60 assertEquals(ChronoField.MINUTE_OF_HOUR, gdt.precision);
61 }
62
63 @Test
64 void b04_ofZonedDateTime() {
65 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
66 var gdt = GranularZonedDateTime.of(zdt, ChronoField.HOUR_OF_DAY);
67 assertEquals(zdt, gdt.zdt);
68 assertEquals(ChronoField.HOUR_OF_DAY, gdt.precision);
69 }
70
71 @Test
72 void b05_ofDate() {
73 var date = new Date(1705322445000L);
74 var gdt = GranularZonedDateTime.of(date, ChronoField.SECOND_OF_MINUTE);
75 assertEquals(ChronoField.SECOND_OF_MINUTE, gdt.precision);
76
77 assertEquals(date.toInstant(), gdt.zdt.toInstant());
78 }
79
80 @Test
81 void b06_ofDateWithZoneId() {
82 var date = new Date(1705322445000L);
83 var zoneId = ZoneId.of("America/New_York");
84 var gdt = GranularZonedDateTime.of(date, ChronoField.SECOND_OF_MINUTE, zoneId);
85 assertEquals(ChronoField.SECOND_OF_MINUTE, gdt.precision);
86 assertEquals(zoneId, gdt.zdt.getZone());
87 assertEquals(2024, gdt.zdt.getYear());
88 assertEquals(1, gdt.zdt.getMonthValue());
89 assertEquals(15, gdt.zdt.getDayOfMonth());
90 }
91
92
93
94
95
96 @Test
97 void c01_copy() {
98 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
99 var gdt1 = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
100 var gdt2 = gdt1.copy();
101 assertNotSame(gdt1, gdt2);
102 assertEquals(gdt1.zdt, gdt2.zdt);
103 assertEquals(gdt1.precision, gdt2.precision);
104 }
105
106
107
108
109
110 @Test
111 void d01_getZonedDateTime() {
112 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
113 var gdt = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
114 assertEquals(zdt, gdt.getZonedDateTime());
115 }
116
117 @Test
118 void d02_getPrecision() {
119 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
120 var gdt = new GranularZonedDateTime(zdt, ChronoField.MINUTE_OF_HOUR);
121 assertEquals(ChronoField.MINUTE_OF_HOUR, gdt.getPrecision());
122 }
123
124
125
126
127
128 @Test
129 void e01_roll_withField() {
130 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 123000000, ZoneId.of("UTC"));
131 var gdt = new GranularZonedDateTime(zdt, ChronoField.MILLI_OF_SECOND);
132
133 var rolled1 = gdt.roll(ChronoField.YEAR, 1);
134 assertEquals(zdt.plusYears(1), rolled1.zdt);
135
136 var rolled2 = gdt.roll(ChronoField.MONTH_OF_YEAR, 1);
137 assertEquals(zdt.plusMonths(1), rolled2.zdt);
138
139 var rolled3 = gdt.roll(ChronoField.DAY_OF_MONTH, 1);
140 assertEquals(zdt.plusDays(1), rolled3.zdt);
141
142 var rolled4 = gdt.roll(ChronoField.HOUR_OF_DAY, 1);
143 assertEquals(zdt.plusHours(1), rolled4.zdt);
144
145 var rolled5 = gdt.roll(ChronoField.MINUTE_OF_HOUR, 1);
146 assertEquals(zdt.plusMinutes(1), rolled5.zdt);
147
148 var rolled6 = gdt.roll(ChronoField.SECOND_OF_MINUTE, 1);
149 assertEquals(zdt.plusSeconds(1), rolled6.zdt);
150
151 var rolled7 = gdt.roll(ChronoField.MILLI_OF_SECOND, 1);
152 assertEquals(zdt.plus(1, ChronoUnit.MILLIS), rolled7.zdt);
153
154 var rolled8 = gdt.roll(ChronoField.NANO_OF_SECOND, 1);
155 assertEquals(zdt.plus(1, ChronoUnit.NANOS), rolled8.zdt);
156 }
157
158 @Test
159 void e02_roll_withNanoOfSecondPrecision() {
160 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 123456789, ZoneId.of("UTC"));
161 var gdt = new GranularZonedDateTime(zdt, ChronoField.NANO_OF_SECOND);
162
163 var rolled = gdt.roll(ChronoField.NANO_OF_SECOND, 100);
164 assertEquals(zdt.plus(100, ChronoUnit.NANOS), rolled.zdt);
165 assertEquals(ChronoField.NANO_OF_SECOND, rolled.precision);
166 }
167
168 @Test
169 void e03_roll_withUnsupportedField() {
170 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
171 var gdt = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
172
173 assertThrowsWithMessage(IllegalArgumentException.class,
174 "Unsupported roll field: AmPmOfDay",
175 () -> gdt.roll(ChronoField.AMPM_OF_DAY, 1));
176 }
177
178
179
180
181
182 @Test
183 void f01_roll_withPrecision() {
184 var zdt = ZonedDateTime.of(2024, 1, 15, 12, 30, 45, 0, ZoneId.of("UTC"));
185 var gdt = new GranularZonedDateTime(zdt, ChronoField.HOUR_OF_DAY);
186 var rolled = gdt.roll(2);
187 assertEquals(zdt.plusHours(2), rolled.zdt);
188 assertEquals(ChronoField.HOUR_OF_DAY, rolled.precision);
189 }
190
191
192
193
194
195 @Test
196 void h01_rollAndof() {
197 var gdt1 = GranularZonedDateTime.of("2011", FAKE_TIME_PROVIDER);
198 var gdt2 = gdt1.roll(1);
199 assertEquals(2012, gdt2.zdt.getYear());
200 assertEquals(ChronoField.YEAR, gdt2.precision);
201 }
202
203 @Test
204 void h02_rollMultipleTimes() {
205 var gdt = GranularZonedDateTime.of("2011-01-15", FAKE_TIME_PROVIDER);
206 var rolled1 = gdt.roll(1);
207 var rolled2 = rolled1.roll(1);
208 assertEquals(17, rolled2.zdt.getDayOfMonth());
209 }
210
211 @Test
212 void h03_rollWithDifferentField() {
213 var gdt = GranularZonedDateTime.of("2011-01-15T12:30Z", FAKE_TIME_PROVIDER);
214
215 var rolled = gdt.roll(ChronoField.HOUR_OF_DAY, 2);
216 assertEquals(14, rolled.zdt.getHour());
217 assertEquals(30, rolled.zdt.getMinute());
218 assertEquals(ChronoField.MINUTE_OF_HOUR, rolled.precision);
219 }
220
221 @Test
222 void h04_copyAndRoll() {
223 var gdt1 = GranularZonedDateTime.of("2011-01-15", FAKE_TIME_PROVIDER);
224 var gdt2 = gdt1.copy();
225 var rolled = gdt2.roll(1);
226
227 assertEquals(15, gdt1.zdt.getDayOfMonth());
228 assertEquals(16, rolled.zdt.getDayOfMonth());
229 }
230
231
232
233
234
235 private static final FakeTimeProvider FAKE_TIME_PROVIDER = new FakeTimeProvider();
236
237 @Nested class J_parserTests extends TestBase {
238
239 record ParseTest(int index, String name, String input, String expected, ZoneId defaultZoneId) {
240 ParseTest(int index, String name, String input, String expected) {
241 this(index, name, input, expected, null);
242 }
243 }
244
245 static ParseTest[] parseTests() {
246 return new ParseTest[] {
247
248 new ParseTest(1, "yearOnly", "2011", "2011-01-01T00:00:00Z(Year)"),
249 new ParseTest(2, "yearMonth", "2011-01", "2011-01-01T00:00:00Z(MonthOfYear)"),
250 new ParseTest(3, "date", "2011-01-15", "2011-01-15T00:00:00Z(DayOfMonth)"),
251
252
253 new ParseTest(4, "dateTime_hour", "2011-01-15T12", "2011-01-15T12:00:00Z(HourOfDay)"),
254 new ParseTest(5, "dateTime_minute", "2011-01-15T12:30", "2011-01-15T12:30:00Z(MinuteOfHour)"),
255 new ParseTest(6, "dateTime_second", "2011-01-15T12:30:45", "2011-01-15T12:30:45Z(SecondOfMinute)"),
256
257
258 new ParseTest(7, "dateTime_millisecond_dot", "2011-01-15T12:30:45.123", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
259 new ParseTest(8, "dateTime_millisecond_comma", "2011-01-15T12:30:45,123", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
260 new ParseTest(9, "dateTime_nanosecond_1digit", "2011-01-15T12:30:45.1", "2011-01-15T12:30:45.1Z(MilliOfSecond)"),
261 new ParseTest(10, "dateTime_nanosecond_2digits", "2011-01-15T12:30:45.12", "2011-01-15T12:30:45.12Z(MilliOfSecond)"),
262 new ParseTest(11, "dateTime_nanosecond_3digits", "2011-01-15T12:30:45.123", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
263 new ParseTest(12, "dateTime_nanosecond_4digits", "2011-01-15T12:30:45.1234", "2011-01-15T12:30:45.1234Z(NanoOfSecond)"),
264 new ParseTest(13, "dateTime_nanosecond_5digits", "2011-01-15T12:30:45.12345", "2011-01-15T12:30:45.12345Z(NanoOfSecond)"),
265 new ParseTest(14, "dateTime_nanosecond_6digits", "2011-01-15T12:30:45.123456", "2011-01-15T12:30:45.123456Z(NanoOfSecond)"),
266 new ParseTest(15, "dateTime_nanosecond_7digits", "2011-01-15T12:30:45.1234567", "2011-01-15T12:30:45.1234567Z(NanoOfSecond)"),
267 new ParseTest(16, "dateTime_nanosecond_8digits", "2011-01-15T12:30:45.12345678", "2011-01-15T12:30:45.12345678Z(NanoOfSecond)"),
268 new ParseTest(17, "dateTime_nanosecond_9digits", "2011-01-15T12:30:45.123456789", "2011-01-15T12:30:45.123456789Z(NanoOfSecond)"),
269
270
271 new ParseTest(18, "timeOnly_hour", "T12", "2000-01-01T12:00:00Z(HourOfDay)"),
272 new ParseTest(19, "timeOnly_minute", "T12:30", "2000-01-01T12:30:00Z(MinuteOfHour)"),
273 new ParseTest(20, "timeOnly_second", "T12:30:45", "2000-01-01T12:30:45Z(SecondOfMinute)"),
274 new ParseTest(21, "timeOnly_millisecond", "T12:30:45.123", "2000-01-01T12:30:45.123Z(MilliOfSecond)"),
275 new ParseTest(22, "timeOnly_withZ", "T12:30:45Z", "2000-01-01T12:30:45Z(SecondOfMinute)"),
276 new ParseTest(23, "timeOnly_withOffset", "T12:30:45+05:30", "2000-01-01T12:30:45+05:30(SecondOfMinute)"),
277
278
279 new ParseTest(24, "withZ", "2011-01-15T12:30:45Z", "2011-01-15T12:30:45Z(SecondOfMinute)"),
280 new ParseTest(25, "yearWithZ", "2011Z", "2011-01-01T00:00:00Z(Year)"),
281 new ParseTest(26, "yearMonthWithZ", "2011-01Z", "2011-01-01T00:00:00Z(MonthOfYear)"),
282 new ParseTest(27, "dateWithZ", "2011-01-15Z", "2011-01-15T00:00:00Z(DayOfMonth)"),
283 new ParseTest(28, "hourWithZ", "2011-01-15T12Z", "2011-01-15T12:00:00Z(HourOfDay)"),
284 new ParseTest(29, "minuteWithZ", "2011-01-15T12:30Z", "2011-01-15T12:30:00Z(MinuteOfHour)"),
285 new ParseTest(30, "millisecondWithZ", "2011-01-15T12:30:45.123Z", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
286
287
288 new ParseTest(31, "offset_plusHH", "2011-01-15T12:30:45+05", "2011-01-15T12:30:45+05:00(SecondOfMinute)"),
289 new ParseTest(32, "offset_minusHH", "2011-01-15T12:30:45-05", "2011-01-15T12:30:45-05:00(SecondOfMinute)"),
290
291
292 new ParseTest(33, "offset_plusHHMM", "2011-01-15T12:30:45+0530", "2011-01-15T12:30:45+05:30(SecondOfMinute)"),
293 new ParseTest(34, "offset_minusHHMM", "2011-01-15T12:30:45-0530", "2011-01-15T12:30:45-05:30(SecondOfMinute)"),
294
295
296 new ParseTest(35, "offset_plusHH_MM", "2011-01-15T12:30:45+05:30", "2011-01-15T12:30:45+05:30(SecondOfMinute)"),
297 new ParseTest(36, "offset_minusHH_MM", "2011-01-15T12:30:45-05:30", "2011-01-15T12:30:45-05:30(SecondOfMinute)"),
298 new ParseTest(37, "offset_minus12_30", "2011-01-15T12:30:45-12:30", "2011-01-15T12:30:45-12:30(SecondOfMinute)"),
299 new ParseTest(38, "offset_plus09_00", "2011-01-15T12:30:45+09:00", "2011-01-15T12:30:45+09:00(SecondOfMinute)"),
300
301
302 new ParseTest(39, "yearFollowedByT", "2011T12", "2011-01-01T12:00:00Z(HourOfDay)"),
303 new ParseTest(40, "yearFollowedByPlus", "2011+05", "2011-01-01T00:00:00+05:00(Year)"),
304 new ParseTest(41, "yearFollowedByMinus", "2011-01-15T12-05", "2011-01-15T12:00:00-05:00(HourOfDay)"),
305 new ParseTest(42, "monthFollowedByZ", "2011-01Z", "2011-01-01T00:00:00Z(MonthOfYear)"),
306 new ParseTest(43, "monthFollowedByPlus", "2011-01+05", "2011-01-01T00:00:00+05:00(MonthOfYear)"),
307 new ParseTest(44, "monthFollowedByMinus", "2011-01-15T12:30-05", "2011-01-15T12:30:00-05:00(MinuteOfHour)"),
308 new ParseTest(45, "dayFollowedByZ", "2011-01-15Z", "2011-01-15T00:00:00Z(DayOfMonth)"),
309 new ParseTest(46, "dayFollowedByPlus", "2011-01-15+05", "2011-01-15T00:00:00+05:00(DayOfMonth)"),
310 new ParseTest(47, "dayFollowedByMinus", "2011-01-15-05", "2011-01-15T00:00:00-05:00(DayOfMonth)"),
311 new ParseTest(48, "hourFollowedByZ", "2011-01-15T12Z", "2011-01-15T12:00:00Z(HourOfDay)"),
312 new ParseTest(49, "hourFollowedByPlus", "2011-01-15T12+05", "2011-01-15T12:00:00+05:00(HourOfDay)"),
313 new ParseTest(50, "hourFollowedByMinus", "2011-01-15T12-05", "2011-01-15T12:00:00-05:00(HourOfDay)"),
314 new ParseTest(51, "minuteFollowedByZ", "2011-01-15T12:30Z", "2011-01-15T12:30:00Z(MinuteOfHour)"),
315 new ParseTest(52, "minuteFollowedByPlus", "2011-01-15T12:30+05", "2011-01-15T12:30:00+05:00(MinuteOfHour)"),
316 new ParseTest(53, "minuteFollowedByMinus", "2011-01-15T12:30-05", "2011-01-15T12:30:00-05:00(MinuteOfHour)"),
317 new ParseTest(54, "timezoneAfterT", "2011-01T+05:30", "2011-01-01T00:00:00+05:30(MonthOfYear)"),
318 new ParseTest(55, "dateFollowedByTZ", "2011-01TZ", "2011-01-01T00:00:00Z(MonthOfYear)"),
319 new ParseTest(56, "dateFollowedByTMinus", "2011-01T-05:30", "2011-01-01T00:00:00-05:30(MonthOfYear)"),
320 new ParseTest(57, "TFollowedByZ", "TZ", "2000-01-01T00:00:00Z(HourOfDay)"),
321 new ParseTest(58, "TFollowedByPlus", "T+05", "2000-01-01T00:00:00+05:00(HourOfDay)"),
322 new ParseTest(59, "TFollowedByMinus", "T-05", "2000-01-01T00:00:00-05:00(HourOfDay)"),
323
324
325 new ParseTest(60, "fractionalSeparatorDotFollowedByZ", "2011-01-15T12:30:45.Z", "2011-01-15T12:30:45Z(SecondOfMinute)"),
326 new ParseTest(61, "fractionalSeparatorCommaFollowedByZ", "2011-01-15T12:30:45,Z", "2011-01-15T12:30:45Z(SecondOfMinute)"),
327 new ParseTest(62, "fractionalSeparatorDotFollowedByPlus", "2011-01-15T12:30:45.+05:00", "2011-01-15T12:30:45+05:00(SecondOfMinute)"),
328 new ParseTest(63, "fractionalSeparatorCommaFollowedByPlus", "2011-01-15T12:30:45,+05:00", "2011-01-15T12:30:45+05:00(SecondOfMinute)"),
329 new ParseTest(64, "fractionalSeparatorDotFollowedByMinus", "2011-01-15T12:30:45.-05:00", "2011-01-15T12:30:45-05:00(SecondOfMinute)"),
330 new ParseTest(65, "fractionalSeparatorCommaFollowedByMinus", "2011-01-15T12:30:45,-05:00", "2011-01-15T12:30:45-05:00(SecondOfMinute)"),
331
332
333 new ParseTest(66, "fractionalSecondsFollowedByZ", "2011-01-15T12:30:45.123Z", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
334 new ParseTest(67, "fractionalSecondsFollowedByPlus", "2011-01-15T12:30:45.123+05:00", "2011-01-15T12:30:45.123+05:00(MilliOfSecond)"),
335 new ParseTest(68, "fractionalSecondsFollowedByMinus", "2011-01-15T12:30:45.123-05:00", "2011-01-15T12:30:45.123-05:00(MilliOfSecond)"),
336 new ParseTest(69, "fractionalSecondsCommaFollowedByZ", "2011-01-15T12:30:45,123Z", "2011-01-15T12:30:45.123Z(MilliOfSecond)"),
337 new ParseTest(70, "fractionalSecondsCommaFollowedByPlus", "2011-01-15T12:30:45,123+05:00", "2011-01-15T12:30:45.123+05:00(MilliOfSecond)"),
338 new ParseTest(71, "fractionalSecondsCommaFollowedByMinus", "2011-01-15T12:30:45,123-05:00", "2011-01-15T12:30:45.123-05:00(MilliOfSecond)"),
339
340
341 new ParseTest(72, "nanosecondsFollowedByZ", "2011-01-15T12:30:45.1234Z", "2011-01-15T12:30:45.1234Z(NanoOfSecond)"),
342 new ParseTest(73, "nanosecondsFollowedByPlus", "2011-01-15T12:30:45.1234+05:00", "2011-01-15T12:30:45.1234+05:00(NanoOfSecond)"),
343 new ParseTest(74, "nanosecondsFollowedByMinus", "2011-01-15T12:30:45.1234-05:00", "2011-01-15T12:30:45.1234-05:00(NanoOfSecond)"),
344
345
346 new ParseTest(75, "offsetBoundary_minus18_00", "2011-01-15T12:30:45-18:00", "2011-01-15T12:30:45-18:00(SecondOfMinute)"),
347 new ParseTest(76, "offsetBoundary_plus18_00", "2011-01-15T12:30:45+18:00", "2011-01-15T12:30:45+18:00(SecondOfMinute)"),
348 new ParseTest(77, "offsetBoundary_minus18_00_compact", "2011-01-15T12:30:45-1800", "2011-01-15T12:30:45-18:00(SecondOfMinute)"),
349 new ParseTest(78, "offsetBoundary_plus18_00_compact", "2011-01-15T12:30:45+1800", "2011-01-15T12:30:45+18:00(SecondOfMinute)"),
350 new ParseTest(79, "offsetBoundary_minus18_hoursOnly", "2011-01-15T12:30:45-18", "2011-01-15T12:30:45-18:00(SecondOfMinute)"),
351 new ParseTest(80, "offsetBoundary_plus18_hoursOnly", "2011-01-15T12:30:45+18", "2011-01-15T12:30:45+18:00(SecondOfMinute)"),
352 new ParseTest(81, "offsetValid_withinRange1", "2011-01-15T12:30:45-12:30", "2011-01-15T12:30:45-12:30(SecondOfMinute)"),
353 new ParseTest(82, "offsetValid_withinRange2", "2011-01-15T12:30:45+12:30", "2011-01-15T12:30:45+12:30(SecondOfMinute)"),
354 new ParseTest(83, "offsetValid_withinRange3", "2011-01-15T12:30:45-17:59", "2011-01-15T12:30:45-17:59(SecondOfMinute)"),
355 new ParseTest(84, "offsetValid_withinRange4", "2011-01-15T12:30:45+17:59", "2011-01-15T12:30:45+17:59(SecondOfMinute)"),
356
357
358 new ParseTest(85, "offsetInvalid_belowMinimum", "2011-01-15T12:30:45-19:00", "Invalid ISO8601 timestamp"),
359 new ParseTest(86, "offsetInvalid_aboveMaximum", "2011-01-15T12:30:45+19:00", "Invalid ISO8601 timestamp"),
360 new ParseTest(87, "offsetInvalid_belowMinimum_compact", "2011-01-15T12:30:45-1900", "Invalid ISO8601 timestamp"),
361 new ParseTest(88, "offsetInvalid_aboveMaximum_compact", "2011-01-15T12:30:45+1900", "Invalid ISO8601 timestamp"),
362 new ParseTest(89, "offsetInvalid_belowMinimum_hoursOnly", "2011-01-15T12:30:45-19", "Invalid ISO8601 timestamp"),
363 new ParseTest(90, "offsetInvalid_aboveMaximum_hoursOnly", "2011-01-15T12:30:45+19", "Invalid ISO8601 timestamp"),
364
365
366 new ParseTest(91, "offsetInvalid_1digit", "2011-01-15T12:30:45+1", "Invalid ISO8601 timestamp"),
367 new ParseTest(92, "offsetInvalid_3digits", "2011-01-15T12:30:45+123", "Invalid ISO8601 timestamp"),
368 new ParseTest(93, "offsetInvalid_5digits", "2011-01-15T12:30:45+12345", "Invalid ISO8601 timestamp"),
369
370
371 new ParseTest(94, "invalidYearLength", "123", "Invalid ISO8601 timestamp"),
372 new ParseTest(95, "invalidMonth_00", "2011-00", "Invalid ISO8601 timestamp"),
373 new ParseTest(96, "invalidMonth_13", "2011-13", "Invalid ISO8601 timestamp"),
374 new ParseTest(97, "invalidMonth_99", "2011-99", "Invalid ISO8601 timestamp"),
375 new ParseTest(98, "invalidDay_00", "2011-01-00", "Invalid ISO8601 timestamp"),
376 new ParseTest(99, "invalidDay_32", "2011-01-32", "Invalid ISO8601 timestamp"),
377 new ParseTest(100, "invalidDay_99", "2011-01-99", "Invalid ISO8601 timestamp"),
378 new ParseTest(101, "invalidHour_24", "2011-01-15T24", "Invalid ISO8601 timestamp"),
379 new ParseTest(102, "invalidHour_99", "2011-01-15T99", "Invalid ISO8601 timestamp"),
380 new ParseTest(103, "invalidMinute_60", "2011-01-15T12:60", "Invalid ISO8601 timestamp"),
381 new ParseTest(104, "invalidMinute_99", "2011-01-15T12:99", "Invalid ISO8601 timestamp"),
382 new ParseTest(105, "invalidSecond_60", "2011-01-15T12:30:60", "Invalid ISO8601 timestamp"),
383 new ParseTest(106, "invalidSecond_99", "2011-01-15T12:30:99", "Invalid ISO8601 timestamp"),
384
385
386 new ParseTest(107, "invalidDate_Nov31", "2011-11-31", "Invalid date 'NOVEMBER 31'"),
387 new ParseTest(108, "invalidDate_Feb29_nonLeap", "2011-02-29", "Invalid date 'February 29' as '2011' is not a leap year"),
388 new ParseTest(109, "invalidDate_Feb30", "2011-02-30", "Invalid date 'FEBRUARY 30'"),
389 new ParseTest(110, "invalidDate_Apr31", "2011-04-31", "Invalid date 'APRIL 31'"),
390 new ParseTest(111, "invalidDate_Jun31", "2011-06-31", "Invalid date 'JUNE 31'"),
391 new ParseTest(112, "invalidDate_Sep31", "2011-09-31", "Invalid date 'SEPTEMBER 31'"),
392 new ParseTest(113, "validDate_Feb29_leap", "2024-02-29", "2024-02-29T00:00:00Z(DayOfMonth)"),
393
394
395 new ParseTest(114, "invalidCharAfterYear", "2011X", "Invalid ISO8601 timestamp"),
396 new ParseTest(115, "invalidCharAfterYearDash", "2011-X", "Invalid ISO8601 timestamp"),
397 new ParseTest(116, "invalidCharAfterMonth", "2011-01X", "Invalid ISO8601 timestamp"),
398 new ParseTest(117, "invalidCharAfterMonthDash", "2011-01-X", "Invalid ISO8601 timestamp"),
399 new ParseTest(118, "invalidCharAfterDay", "2011-01-15X", "Invalid ISO8601 timestamp"),
400 new ParseTest(119, "invalidCharAfterT", "TX", "Invalid ISO8601 timestamp"),
401 new ParseTest(120, "invalidCharAfterHour", "2011-01-15T12X", "Invalid ISO8601 timestamp"),
402 new ParseTest(121, "invalidCharAfterHourColon", "2011-01-15T12:X", "Invalid ISO8601 timestamp"),
403 new ParseTest(122, "invalidCharAfterMinute", "2011-01-15T12:30X", "Invalid ISO8601 timestamp"),
404 new ParseTest(123, "invalidCharAfterMinuteColon", "2011-01-15T12:30:X", "Invalid ISO8601 timestamp"),
405 new ParseTest(124, "invalidCharAfterSecond", "2011-01-15T12:30:45X", "Invalid ISO8601 timestamp"),
406 new ParseTest(125, "invalidCharAfterFractionalSeparator", "2011-01-15T12:30:45.X", "Invalid ISO8601 timestamp"),
407 new ParseTest(126, "invalidCharInFractionalSeconds", "2011-01-15T12:30:45.12X", "Invalid ISO8601 timestamp"),
408 new ParseTest(127, "invalidCharAfterPlus", "2011-01-15T12:30:45+X", "Invalid ISO8601 timestamp"),
409 new ParseTest(128, "invalidCharAfterMinus", "2011-01-15T12:30:45-X", "Invalid ISO8601 timestamp"),
410 new ParseTest(129, "invalidCharInOffsetHours", "2011-01-15T12:30:45+05X", "Invalid ISO8601 timestamp"),
411 new ParseTest(130, "invalidCharAfterOffsetColon", "2011-01-15T12:30:45+05:X", "Invalid ISO8601 timestamp"),
412 new ParseTest(131, "invalidCharInOffsetMinutes", "2011-01-15T12:30:45+05:30X", "Invalid ISO8601 timestamp"),
413
414
415 new ParseTest(132, "invalidCharAfterZ_year", "2011Z5", "Invalid ISO8601 timestamp"),
416 new ParseTest(133, "invalidCharAfterZ_month", "2011-01ZX", "Invalid ISO8601 timestamp"),
417 new ParseTest(134, "invalidCharAfterZ_day", "2011-01-15ZX", "Invalid ISO8601 timestamp"),
418 new ParseTest(135, "invalidCharAfterZ_T", "TZX", "Invalid ISO8601 timestamp"),
419 new ParseTest(136, "invalidCharAfterZ_hour", "2011-01-15T12ZX", "Invalid ISO8601 timestamp"),
420 new ParseTest(137, "invalidCharAfterZ_minute", "2011-01-15T12:30ZX", "Invalid ISO8601 timestamp"),
421 new ParseTest(138, "invalidCharAfterZ_second", "2011-01-15T12:30:45ZX", "Invalid ISO8601 timestamp"),
422 new ParseTest(139, "invalidCharAfterZ_secondPlus", "2011-01-15T12:30:45Z+", "Invalid ISO8601 timestamp"),
423 new ParseTest(140, "invalidCharAfterZ_secondMinus", "2011-01-15T12:30:45Z-", "Invalid ISO8601 timestamp"),
424 new ParseTest(141, "invalidCharAfterZ_secondDigit", "2011-01-15T12:30:45Z5", "Invalid ISO8601 timestamp"),
425 new ParseTest(142, "invalidCharAfterZ_secondSpace", "2011-01-15T12:30:45Z ", "Invalid ISO8601 timestamp"),
426 new ParseTest(143, "invalidCharAfterZ_fractionalSeparator", "2011-01-15T12:30:45.ZX", "Invalid ISO8601 timestamp"),
427 new ParseTest(144, "invalidCharAfterZ_fractionalSeconds", "2011-01-15T12:30:45.123ZX", "Invalid ISO8601 timestamp"),
428 new ParseTest(145, "invalidCharAfterZ_timeOnly", "T12:30:45ZX", "Invalid ISO8601 timestamp"),
429
430
431 new ParseTest(146, "invalidNanos_10digits", "2011-01-15T12:30:45.1234567890", "Invalid ISO8601 timestamp"),
432
433
434 new ParseTest(147, "withDefaultZoneId", "2011-01-15T12:30:45", "2011-01-15T12:30:45-05:00(SecondOfMinute)", ZoneId.of("America/New_York")),
435 new ParseTest(148, "withDefaultZoneId_timeOnly", "T12:30:45", "2000-01-01T12:30:45-05:00(SecondOfMinute)", ZoneId.of("America/New_York")),
436 new ParseTest(149, "withDefaultZoneId_ignoredWhenZoneInString", "2011-01-15T12:30:45Z", "2011-01-15T12:30:45Z(SecondOfMinute)", ZoneId.of("America/New_York")),
437
438
439 new ParseTest(150, "null", null, "Argument 'value' cannot be null."),
440 new ParseTest(151, "emptyString", "", "Invalid ISO8601 timestamp"),
441 new ParseTest(152, "invalidString", "invalid-date", "Invalid ISO8601 timestamp"),
442 };
443 }
444
445 @ParameterizedTest(name = "[{0}] {1}")
446 @MethodSource("parseTests")
447 void j01_parse(ParseTest test) {
448 if (test.defaultZoneId == null) {
449 testParse(test.expected, test.input);
450 } else {
451 testParse(test.expected, test.input, test.defaultZoneId);
452 }
453 }
454
455 private void testParse(String expected, String in) {
456 try {
457 var x = GranularZonedDateTime.of(in, FAKE_TIME_PROVIDER);
458 assertEquals(expected, x.toString(), "Failed for input: " + in);
459 } catch (Exception e) {
460 assertEquals(expected, e.getLocalizedMessage(), "Failed for input: " + in);
461 }
462 }
463
464 private void testParse(String expected, String in, ZoneId zoneId) {
465 try {
466 var x = GranularZonedDateTime.of(in, zoneId, FAKE_TIME_PROVIDER);
467 assertEquals(expected, x.toString(), "Failed for input: " + in + " with zoneId: " + zoneId);
468 } catch (Exception e) {
469 assertEquals(expected, e.getLocalizedMessage(), "Failed for input: " + in + " with zoneId: " + zoneId);
470 }
471 }
472 }
473 }