1 /*
2  * Copyright (c) 2012, 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) 2008-2012, 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 test.java.time.format;
61 
62 import static java.time.temporal.ChronoField.OFFSET_SECONDS;
63 import static org.testng.Assert.assertEquals;
64 import static org.testng.Assert.assertTrue;
65 
66 import java.text.ParsePosition;
67 import java.time.ZoneOffset;
68 import java.time.temporal.TemporalAccessor;
69 
70 import org.testng.annotations.DataProvider;
71 import org.testng.annotations.Test;
72 
73 /**
74  * Test ZoneOffsetPrinterParser.
75  */
76 @Test
77 public class TestZoneOffsetParser extends AbstractTestPrinterParser {
78 
79     //-----------------------------------------------------------------------
80     @DataProvider(name="error")
data_error()81     Object[][] data_error() {
82         return new Object[][] {
83             {"+HH:MM:ss", "Z", "hello", -1, IndexOutOfBoundsException.class},
84             {"+HH:MM:ss", "Z", "hello", 6, IndexOutOfBoundsException.class},
85         };
86     }
87 
88     @Test(dataProvider="error")
test_parse_error(String pattern, String noOffsetText, String text, int pos, Class<?> expected)89     public void test_parse_error(String pattern, String noOffsetText, String text, int pos, Class<?> expected) {
90         try {
91             getFormatter(pattern, noOffsetText).parseUnresolved(text, new ParsePosition(pos));
92         } catch (RuntimeException ex) {
93             assertTrue(expected.isInstance(ex));
94         }
95     }
96 
97     //-----------------------------------------------------------------------
test_parse_exactMatch_UTC()98     public void test_parse_exactMatch_UTC() throws Exception {
99         ParsePosition pos = new ParsePosition(0);
100         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos);
101         assertEquals(pos.getIndex(), 1);
102         assertParsed(parsed, ZoneOffset.UTC);
103     }
104 
test_parse_startStringMatch_UTC()105     public void test_parse_startStringMatch_UTC() throws Exception {
106         ParsePosition pos = new ParsePosition(0);
107         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("ZOTHER", pos);
108         assertEquals(pos.getIndex(), 1);
109         assertParsed(parsed, ZoneOffset.UTC);
110     }
111 
test_parse_midStringMatch_UTC()112     public void test_parse_midStringMatch_UTC() throws Exception {
113         ParsePosition pos = new ParsePosition(5);
114         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("OTHERZOTHER", pos);
115         assertEquals(pos.getIndex(), 6);
116         assertParsed(parsed, ZoneOffset.UTC);
117     }
118 
test_parse_endStringMatch_UTC()119     public void test_parse_endStringMatch_UTC() throws Exception {
120         ParsePosition pos = new ParsePosition(5);
121         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("OTHERZ", pos);
122         assertEquals(pos.getIndex(), 6);
123         assertParsed(parsed, ZoneOffset.UTC);
124     }
125 
126     //-----------------------------------------------------------------------
test_parse_exactMatch_UTC_EmptyUTC()127     public void test_parse_exactMatch_UTC_EmptyUTC() throws Exception {
128         ParsePosition pos = new ParsePosition(0);
129         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("", pos);
130         assertEquals(pos.getIndex(), 0);
131         assertParsed(parsed, ZoneOffset.UTC);
132     }
133 
test_parse_startStringMatch_UTC_EmptyUTC()134     public void test_parse_startStringMatch_UTC_EmptyUTC() throws Exception {
135         ParsePosition pos = new ParsePosition(0);
136         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHER", pos);
137         assertEquals(pos.getIndex(), 0);
138         assertParsed(parsed, ZoneOffset.UTC);
139     }
140 
test_parse_midStringMatch_UTC_EmptyUTC()141     public void test_parse_midStringMatch_UTC_EmptyUTC() throws Exception {
142         ParsePosition pos = new ParsePosition(5);
143         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHEROTHER", pos);
144         assertEquals(pos.getIndex(), 5);
145         assertParsed(parsed, ZoneOffset.UTC);
146     }
147 
test_parse_endStringMatch_UTC_EmptyUTC()148     public void test_parse_endStringMatch_UTC_EmptyUTC() throws Exception {
149         ParsePosition pos = new ParsePosition(5);
150         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHER", pos);
151         assertEquals(pos.getIndex(), 5);
152         assertParsed(parsed, ZoneOffset.UTC);
153     }
154 
155     //-----------------------------------------------------------------------
156     @DataProvider(name="offsets")
provider_offsets()157     Object[][] provider_offsets() {
158         return new Object[][] {
159             {"+HH", "+00", ZoneOffset.UTC},
160             {"+HH", "-00", ZoneOffset.UTC},
161             {"+HH", "+01", ZoneOffset.ofHours(1)},
162             {"+HH", "-01", ZoneOffset.ofHours(-1)},
163 
164             {"+HHMM", "+0000", ZoneOffset.UTC},
165             {"+HHMM", "-0000", ZoneOffset.UTC},
166             {"+HHMM", "+0102", ZoneOffset.ofHoursMinutes(1, 2)},
167             {"+HHMM", "-0102", ZoneOffset.ofHoursMinutes(-1, -2)},
168 
169             {"+HH:MM", "+00:00", ZoneOffset.UTC},
170             {"+HH:MM", "-00:00", ZoneOffset.UTC},
171             {"+HH:MM", "+01:02", ZoneOffset.ofHoursMinutes(1, 2)},
172             {"+HH:MM", "-01:02", ZoneOffset.ofHoursMinutes(-1, -2)},
173 
174             {"+HHMMss", "+0000", ZoneOffset.UTC},
175             {"+HHMMss", "-0000", ZoneOffset.UTC},
176             {"+HHMMss", "+0100", ZoneOffset.ofHoursMinutesSeconds(1, 0, 0)},
177             {"+HHMMss", "+0159", ZoneOffset.ofHoursMinutesSeconds(1, 59, 0)},
178             {"+HHMMss", "+0200", ZoneOffset.ofHoursMinutesSeconds(2, 0, 0)},
179             {"+HHMMss", "+1800", ZoneOffset.ofHoursMinutesSeconds(18, 0, 0)},
180             {"+HHMMss", "+010215", ZoneOffset.ofHoursMinutesSeconds(1, 2, 15)},
181             {"+HHMMss", "-0100", ZoneOffset.ofHoursMinutesSeconds(-1, 0, 0)},
182             {"+HHMMss", "-0200", ZoneOffset.ofHoursMinutesSeconds(-2, 0, 0)},
183             {"+HHMMss", "-1800", ZoneOffset.ofHoursMinutesSeconds(-18, 0, 0)},
184 
185             {"+HHMMss", "+000000", ZoneOffset.UTC},
186             {"+HHMMss", "-000000", ZoneOffset.UTC},
187             {"+HHMMss", "+010000", ZoneOffset.ofHoursMinutesSeconds(1, 0, 0)},
188             {"+HHMMss", "+010203", ZoneOffset.ofHoursMinutesSeconds(1, 2, 3)},
189             {"+HHMMss", "+015959", ZoneOffset.ofHoursMinutesSeconds(1, 59, 59)},
190             {"+HHMMss", "+020000", ZoneOffset.ofHoursMinutesSeconds(2, 0, 0)},
191             {"+HHMMss", "+180000", ZoneOffset.ofHoursMinutesSeconds(18, 0, 0)},
192             {"+HHMMss", "-010000", ZoneOffset.ofHoursMinutesSeconds(-1, 0, 0)},
193             {"+HHMMss", "-020000", ZoneOffset.ofHoursMinutesSeconds(-2, 0, 0)},
194             {"+HHMMss", "-180000", ZoneOffset.ofHoursMinutesSeconds(-18, 0, 0)},
195 
196             {"+HH:MM:ss", "+00:00", ZoneOffset.UTC},
197             {"+HH:MM:ss", "-00:00", ZoneOffset.UTC},
198             {"+HH:MM:ss", "+01:00", ZoneOffset.ofHoursMinutesSeconds(1, 0, 0)},
199             {"+HH:MM:ss", "+01:02", ZoneOffset.ofHoursMinutesSeconds(1, 2, 0)},
200             {"+HH:MM:ss", "+01:59", ZoneOffset.ofHoursMinutesSeconds(1, 59, 0)},
201             {"+HH:MM:ss", "+02:00", ZoneOffset.ofHoursMinutesSeconds(2, 0, 0)},
202             {"+HH:MM:ss", "+18:00", ZoneOffset.ofHoursMinutesSeconds(18, 0, 0)},
203             {"+HH:MM:ss", "+01:02:15", ZoneOffset.ofHoursMinutesSeconds(1, 2, 15)},
204             {"+HH:MM:ss", "-01:00", ZoneOffset.ofHoursMinutesSeconds(-1, 0, 0)},
205             {"+HH:MM:ss", "-02:00", ZoneOffset.ofHoursMinutesSeconds(-2, 0, 0)},
206             {"+HH:MM:ss", "-18:00", ZoneOffset.ofHoursMinutesSeconds(-18, 0, 0)},
207 
208             {"+HH:MM:ss", "+00:00:00", ZoneOffset.UTC},
209             {"+HH:MM:ss", "-00:00:00", ZoneOffset.UTC},
210             {"+HH:MM:ss", "+01:00:00", ZoneOffset.ofHoursMinutesSeconds(1, 0, 0)},
211             {"+HH:MM:ss", "+01:02:03", ZoneOffset.ofHoursMinutesSeconds(1, 2, 3)},
212             {"+HH:MM:ss", "+01:59:59", ZoneOffset.ofHoursMinutesSeconds(1, 59, 59)},
213             {"+HH:MM:ss", "+02:00:00", ZoneOffset.ofHoursMinutesSeconds(2, 0, 0)},
214             {"+HH:MM:ss", "+18:00:00", ZoneOffset.ofHoursMinutesSeconds(18, 0, 0)},
215             {"+HH:MM:ss", "-01:00:00", ZoneOffset.ofHoursMinutesSeconds(-1, 0, 0)},
216             {"+HH:MM:ss", "-02:00:00", ZoneOffset.ofHoursMinutesSeconds(-2, 0, 0)},
217             {"+HH:MM:ss", "-18:00:00", ZoneOffset.ofHoursMinutesSeconds(-18, 0, 0)},
218 
219             {"+HHMMSS", "+000000", ZoneOffset.UTC},
220             {"+HHMMSS", "-000000", ZoneOffset.UTC},
221             {"+HHMMSS", "+010203", ZoneOffset.ofHoursMinutesSeconds(1, 2, 3)},
222             {"+HHMMSS", "-010203", ZoneOffset.ofHoursMinutesSeconds(-1, -2, -3)},
223 
224             {"+HH:MM:SS", "+00:00:00", ZoneOffset.UTC},
225             {"+HH:MM:SS", "-00:00:00", ZoneOffset.UTC},
226             {"+HH:MM:SS", "+01:02:03", ZoneOffset.ofHoursMinutesSeconds(1, 2, 3)},
227             {"+HH:MM:SS", "-01:02:03", ZoneOffset.ofHoursMinutesSeconds(-1, -2, -3)},
228         };
229     }
230 
231     @Test(dataProvider="offsets")
test_parse_exactMatch(String pattern, String parse, ZoneOffset expected)232     public void test_parse_exactMatch(String pattern, String parse, ZoneOffset expected) throws Exception {
233         ParsePosition pos = new ParsePosition(0);
234         TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse, pos);
235         assertEquals(pos.getIndex(), parse.length());
236         assertParsed(parsed, expected);
237     }
238 
239     @Test(dataProvider="offsets")
test_parse_startStringMatch(String pattern, String parse, ZoneOffset expected)240     public void test_parse_startStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception {
241         ParsePosition pos = new ParsePosition(0);
242         TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse + ":OTHER", pos);
243         assertEquals(pos.getIndex(), parse.length());
244         assertParsed(parsed, expected);
245     }
246 
247     @Test(dataProvider="offsets")
test_parse_midStringMatch(String pattern, String parse, ZoneOffset expected)248     public void test_parse_midStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception {
249         ParsePosition pos = new ParsePosition(5);
250         TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved("OTHER" + parse + ":OTHER", pos);
251         assertEquals(pos.getIndex(), parse.length() + 5);
252         assertParsed(parsed, expected);
253     }
254 
255     @Test(dataProvider="offsets")
test_parse_endStringMatch(String pattern, String parse, ZoneOffset expected)256     public void test_parse_endStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception {
257         ParsePosition pos = new ParsePosition(5);
258         TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved("OTHER" + parse, pos);
259         assertEquals(pos.getIndex(), parse.length() + 5);
260         assertParsed(parsed, expected);
261     }
262 
263     @Test(dataProvider="offsets")
test_parse_exactMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected)264     public void test_parse_exactMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception {
265         ParsePosition pos = new ParsePosition(0);
266         TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse, pos);
267         assertEquals(pos.getIndex(), parse.length());
268         assertParsed(parsed, expected);
269     }
270 
271     @Test(dataProvider="offsets")
test_parse_startStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected)272     public void test_parse_startStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception {
273         ParsePosition pos = new ParsePosition(0);
274         TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse + ":OTHER", pos);
275         assertEquals(pos.getIndex(), parse.length());
276         assertParsed(parsed, expected);
277     }
278 
279     @Test(dataProvider="offsets")
test_parse_midStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected)280     public void test_parse_midStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception {
281         ParsePosition pos = new ParsePosition(5);
282         TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved("OTHER" + parse + ":OTHER", pos);
283         assertEquals(pos.getIndex(), parse.length() + 5);
284         assertParsed(parsed, expected);
285     }
286 
287     @Test(dataProvider="offsets")
test_parse_endStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected)288     public void test_parse_endStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception {
289         ParsePosition pos = new ParsePosition(5);
290         TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved("OTHER" + parse, pos);
291         assertEquals(pos.getIndex(), parse.length() + 5);
292         assertParsed(parsed, expected);
293     }
294 
295     //-----------------------------------------------------------------------
296     @DataProvider(name="bigOffsets")
provider_bigOffsets()297     Object[][] provider_bigOffsets() {
298         return new Object[][] {
299             {"+HH", "+59", 59 * 3600},
300             {"+HH", "-19", -(19 * 3600)},
301 
302             {"+HHMM", "+1801", 18 * 3600 + 1 * 60},
303             {"+HHMM", "-1801", -(18 * 3600 + 1 * 60)},
304 
305             {"+HH:MM", "+18:01", 18 * 3600 + 1 * 60},
306             {"+HH:MM", "-18:01", -(18 * 3600 + 1 * 60)},
307 
308             {"+HHMMss", "+180103", 18 * 3600 + 1 * 60 + 3},
309             {"+HHMMss", "-180103", -(18 * 3600 + 1 * 60 + 3)},
310 
311             {"+HH:MM:ss", "+18:01:03", 18 * 3600 + 1 * 60 + 3},
312             {"+HH:MM:ss", "-18:01:03", -(18 * 3600 + 1 * 60 + 3)},
313 
314             {"+HHMMSS", "+180103", 18 * 3600 + 1 * 60 + 3},
315             {"+HHMMSS", "-180103", -(18 * 3600 + 1 * 60 + 3)},
316 
317             {"+HH:MM:SS", "+18:01:03", 18 * 3600 + 1 * 60 + 3},
318             {"+HH:MM:SS", "-18:01:03", -(18 * 3600 + 1 * 60 + 3)},
319         };
320     }
321 
322     @Test(dataProvider="bigOffsets")
test_parse_bigOffsets(String pattern, String parse, long offsetSecs)323     public void test_parse_bigOffsets(String pattern, String parse, long offsetSecs) throws Exception {
324         ParsePosition pos = new ParsePosition(0);
325         TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse, pos);
326         assertEquals(pos.getIndex(), parse.length());
327         assertEquals(parsed.getLong(OFFSET_SECONDS), offsetSecs);
328     }
329 
330     //-----------------------------------------------------------------------
331     @DataProvider(name="badOffsets")
provider_badOffsets()332     Object[][] provider_badOffsets() {
333         return new Object[][] {
334             {"+HH", "+1", 0},
335             {"+HH", "-1", 0},
336             {"+HH", "01", 0},
337             {"+HH", "01", 0},
338             {"+HH", "+AA", 0},
339 
340             {"+HHMM", "+1", 0},
341             {"+HHMM", "+01", 0},
342             {"+HHMM", "+001", 0},
343             {"+HHMM", "0102", 0},
344             {"+HHMM", "+01:02", 0},
345             {"+HHMM", "+AAAA", 0},
346 
347             {"+HH:MM", "+1", 0},
348             {"+HH:MM", "+01", 0},
349             {"+HH:MM", "+0:01", 0},
350             {"+HH:MM", "+00:1", 0},
351             {"+HH:MM", "+0:1", 0},
352             {"+HH:MM", "+:", 0},
353             {"+HH:MM", "01:02", 0},
354             {"+HH:MM", "+0102", 0},
355             {"+HH:MM", "+AA:AA", 0},
356 
357             {"+HHMMss", "+1", 0},
358             {"+HHMMss", "+01", 0},
359             {"+HHMMss", "+001", 0},
360             {"+HHMMss", "0102", 0},
361             {"+HHMMss", "+01:02", 0},
362             {"+HHMMss", "+AAAA", 0},
363 
364             {"+HH:MM:ss", "+1", 0},
365             {"+HH:MM:ss", "+01", 0},
366             {"+HH:MM:ss", "+0:01", 0},
367             {"+HH:MM:ss", "+00:1", 0},
368             {"+HH:MM:ss", "+0:1", 0},
369             {"+HH:MM:ss", "+:", 0},
370             {"+HH:MM:ss", "01:02", 0},
371             {"+HH:MM:ss", "+0102", 0},
372             {"+HH:MM:ss", "+AA:AA", 0},
373 
374             {"+HHMMSS", "+1", 0},
375             {"+HHMMSS", "+01", 0},
376             {"+HHMMSS", "+001", 0},
377             {"+HHMMSS", "0102", 0},
378             {"+HHMMSS", "+01:02", 0},
379             {"+HHMMSS", "+AAAA", 0},
380 
381             {"+HH:MM:SS", "+1", 0},
382             {"+HH:MM:SS", "+01", 0},
383             {"+HH:MM:SS", "+0:01", 0},
384             {"+HH:MM:SS", "+00:1", 0},
385             {"+HH:MM:SS", "+0:1", 0},
386             {"+HH:MM:SS", "+:", 0},
387             {"+HH:MM:SS", "01:02", 0},
388             {"+HH:MM:SS", "+0102", 0},
389             {"+HH:MM:SS", "+AA:AA", 0},
390         };
391     }
392 
393     @Test(dataProvider="badOffsets")
test_parse_invalid(String pattern, String parse, int expectedPosition)394     public void test_parse_invalid(String pattern, String parse, int expectedPosition) throws Exception {
395         ParsePosition pos = new ParsePosition(0);
396         TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse, pos);
397         assertEquals(pos.getErrorIndex(), expectedPosition);
398         assertEquals(parsed, null);
399     }
400 
401     //-----------------------------------------------------------------------
402     //-----------------------------------------------------------------------
403     //-----------------------------------------------------------------------
test_parse_caseSensitiveUTC_matchedCase()404     public void test_parse_caseSensitiveUTC_matchedCase() throws Exception {
405         setCaseSensitive(true);
406         ParsePosition pos = new ParsePosition(0);
407         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos);
408         assertEquals(pos.getIndex(), 1);
409         assertParsed(parsed, ZoneOffset.UTC);
410     }
411 
test_parse_caseSensitiveUTC_unmatchedCase()412     public void test_parse_caseSensitiveUTC_unmatchedCase() throws Exception {
413         setCaseSensitive(true);
414         ParsePosition pos = new ParsePosition(0);
415         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("z", pos);
416         assertEquals(pos.getErrorIndex(), 0);
417         assertEquals(parsed, null);
418     }
419 
test_parse_caseInsensitiveUTC_matchedCase()420     public void test_parse_caseInsensitiveUTC_matchedCase() throws Exception {
421         setCaseSensitive(false);
422         ParsePosition pos = new ParsePosition(0);
423         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos);
424         assertEquals(pos.getIndex(), 1);
425         assertParsed(parsed, ZoneOffset.UTC);
426     }
427 
test_parse_caseInsensitiveUTC_unmatchedCase()428     public void test_parse_caseInsensitiveUTC_unmatchedCase() throws Exception {
429         setCaseSensitive(false);
430         ParsePosition pos = new ParsePosition(0);
431         TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("z", pos);
432         assertEquals(pos.getIndex(), 1);
433         assertParsed(parsed, ZoneOffset.UTC);
434     }
435 
assertParsed(TemporalAccessor parsed, ZoneOffset expectedOffset)436     private void assertParsed(TemporalAccessor parsed, ZoneOffset expectedOffset) {
437         if (expectedOffset == null) {
438             assertEquals(parsed, null);
439         } else {
440             assertEquals(parsed.isSupported(OFFSET_SECONDS), true);
441             assertEquals(parsed.getLong(OFFSET_SECONDS), (long) expectedOffset.getTotalSeconds());
442         }
443     }
444 
445 }
446