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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
28  *
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions are met:
33  *
34  *  * Redistributions of source code must retain the above copyright notice,
35  *    this list of conditions and the following disclaimer.
36  *
37  *  * Redistributions in binary form must reproduce the above copyright notice,
38  *    this list of conditions and the following disclaimer in the documentation
39  *    and/or other materials provided with the distribution.
40  *
41  *  * Neither the name of JSR-310 nor the names of its contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
49  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  */
57 package tck.java.time.temporal;
58 
59 import static java.time.format.ResolverStyle.LENIENT;
60 import static java.time.format.ResolverStyle.SMART;
61 import static java.time.format.ResolverStyle.STRICT;
62 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
63 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
64 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
65 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
66 import static java.time.temporal.ChronoField.YEAR;
67 import static org.testng.Assert.assertEquals;
68 import static org.testng.Assert.assertFalse;
69 import static org.testng.Assert.assertNotEquals;
70 import static org.testng.Assert.assertSame;
71 import static org.testng.Assert.assertTrue;
72 
73 import android.platform.test.annotations.LargeTest;
74 
75 import java.io.IOException;
76 import java.time.DateTimeException;
77 import java.time.DayOfWeek;
78 import java.time.LocalDate;
79 import java.time.format.DateTimeFormatter;
80 import java.time.format.DateTimeFormatterBuilder;
81 import java.time.temporal.ChronoUnit;
82 import java.time.temporal.TemporalField;
83 import java.time.temporal.ValueRange;
84 import java.time.temporal.WeekFields;
85 
86 import org.testng.annotations.DataProvider;
87 import org.testng.annotations.Test;
88 import tck.java.time.AbstractTCKTest;
89 
90 /**
91  * Test WeekFields.
92  */
93 @Test
94 public class TCKWeekFields extends AbstractTCKTest {
95 
96     @Test(dataProvider="weekFields")
test_of_DayOfWeek_int_singleton(DayOfWeek firstDayOfWeek, int minDays)97     public void test_of_DayOfWeek_int_singleton(DayOfWeek firstDayOfWeek, int minDays) {
98         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
99         assertEquals(week.getFirstDayOfWeek(), firstDayOfWeek, "Incorrect firstDayOfWeek");
100         assertEquals(week.getMinimalDaysInFirstWeek(), minDays, "Incorrect MinimalDaysInFirstWeek");
101         assertSame(WeekFields.of(firstDayOfWeek, minDays), week);
102     }
103 
104     //-----------------------------------------------------------------------
105     @Test(dataProvider="weekFields")
test_basics(DayOfWeek firstDayOfWeek, int minDays)106     public void test_basics(DayOfWeek firstDayOfWeek, int minDays) {
107         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
108         assertEquals(week.dayOfWeek().isDateBased(), true);
109         assertEquals(week.dayOfWeek().isTimeBased(), false);
110 
111         assertEquals(week.weekOfMonth().isDateBased(), true);
112         assertEquals(week.weekOfMonth().isTimeBased(), false);
113 
114         assertEquals(week.weekOfYear().isDateBased(), true);
115         assertEquals(week.weekOfYear().isTimeBased(), false);
116 
117         assertEquals(week.weekOfWeekBasedYear().isDateBased(), true);
118         assertEquals(week.weekOfWeekBasedYear().isTimeBased(), false);
119 
120         assertEquals(week.weekBasedYear().isDateBased(), true);
121         assertEquals(week.weekBasedYear().isTimeBased(), false);
122     }
123 
124     //-----------------------------------------------------------------------
125     @Test
test_dayOfWeekField_simpleGet()126     public void test_dayOfWeekField_simpleGet() {
127         LocalDate date = LocalDate.of(2000, 1, 10);  // Known to be ISO Monday
128         assertEquals(date.get(WeekFields.ISO.dayOfWeek()), 1);
129         assertEquals(date.get(WeekFields.of(DayOfWeek.MONDAY, 1).dayOfWeek()), 1);
130         assertEquals(date.get(WeekFields.of(DayOfWeek.MONDAY, 7).dayOfWeek()), 1);
131         assertEquals(date.get(WeekFields.SUNDAY_START.dayOfWeek()), 2);
132         assertEquals(date.get(WeekFields.of(DayOfWeek.SUNDAY, 1).dayOfWeek()), 2);
133         assertEquals(date.get(WeekFields.of(DayOfWeek.SUNDAY, 7).dayOfWeek()), 2);
134         assertEquals(date.get(WeekFields.of(DayOfWeek.SATURDAY, 1).dayOfWeek()), 3);
135         assertEquals(date.get(WeekFields.of(DayOfWeek.FRIDAY, 1).dayOfWeek()), 4);
136         assertEquals(date.get(WeekFields.of(DayOfWeek.TUESDAY, 1).dayOfWeek()), 7);
137     }
138 
139     @Test
test_dayOfWeekField_simpleSet()140     public void test_dayOfWeekField_simpleSet() {
141         LocalDate date = LocalDate.of(2000, 1, 10);  // Known to be ISO Monday
142         assertEquals(date.with(WeekFields.ISO.dayOfWeek(), 2), LocalDate.of(2000, 1, 11));
143         assertEquals(date.with(WeekFields.ISO.dayOfWeek(), 7), LocalDate.of(2000, 1, 16));
144 
145         assertEquals(date.with(WeekFields.SUNDAY_START.dayOfWeek(), 3), LocalDate.of(2000, 1, 11));
146         assertEquals(date.with(WeekFields.SUNDAY_START.dayOfWeek(), 7), LocalDate.of(2000, 1, 15));
147 
148         assertEquals(date.with(WeekFields.of(DayOfWeek.SATURDAY, 1).dayOfWeek(), 4), LocalDate.of(2000, 1, 11));
149         assertEquals(date.with(WeekFields.of(DayOfWeek.TUESDAY, 1).dayOfWeek(), 1), LocalDate.of(2000, 1, 4));
150     }
151 
152     @Test(dataProvider="weekFields")
test_dayOfWeekField(DayOfWeek firstDayOfWeek, int minDays)153     public void test_dayOfWeekField(DayOfWeek firstDayOfWeek, int minDays) {
154         LocalDate day = LocalDate.of(2000, 1, 10);  // Known to be ISO Monday
155         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
156         TemporalField f = week.dayOfWeek();
157 
158         for (int i = 1; i <= 7; i++) {
159             assertEquals(day.get(f), (7 + day.getDayOfWeek().getValue() - firstDayOfWeek.getValue()) % 7 + 1);
160             day = day.plusDays(1);
161         }
162     }
163 
164     @Test(dataProvider="weekFields")
test_weekOfMonthField(DayOfWeek firstDayOfWeek, int minDays)165     public void test_weekOfMonthField(DayOfWeek firstDayOfWeek, int minDays) {
166         LocalDate day = LocalDate.of(2012, 12, 31);  // Known to be ISO Monday
167         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
168         TemporalField dowField = week.dayOfWeek();
169         TemporalField womField = week.weekOfMonth();
170 
171         for (int i = 1; i <= 15; i++) {
172             int actualDOW = day.get(dowField);
173             int actualWOM = day.get(womField);
174 
175             // Verify that the combination of day of week and week of month can be used
176             // to reconstruct the same date.
177             LocalDate day1 = day.withDayOfMonth(1);
178             int offset = - (day1.get(dowField) - 1);
179 
180             int week1 = day1.get(womField);
181             if (week1 == 0) {
182                 // week of the 1st is partial; start with first full week
183                 offset += 7;
184             }
185 
186             offset += actualDOW - 1;
187             offset += (actualWOM - 1) * 7;
188             LocalDate result = day1.plusDays(offset);
189 
190             assertEquals(result, day, "Incorrect dayOfWeek or weekOfMonth: "
191                     + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n",
192                     week, day.getDayOfWeek(), offset, actualDOW, actualWOM, day, result));
193             day = day.plusDays(1);
194         }
195     }
196 
197     @Test(dataProvider="weekFields")
test_weekOfYearField(DayOfWeek firstDayOfWeek, int minDays)198     public void test_weekOfYearField(DayOfWeek firstDayOfWeek, int minDays) {
199         LocalDate day = LocalDate.of(2012, 12, 31);  // Known to be ISO Monday
200         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
201         TemporalField dowField = week.dayOfWeek();
202         TemporalField woyField = week.weekOfYear();
203 
204         for (int i = 1; i <= 15; i++) {
205             int actualDOW = day.get(dowField);
206             int actualWOY = day.get(woyField);
207 
208             // Verify that the combination of day of week and week of month can be used
209             // to reconstruct the same date.
210             LocalDate day1 = day.withDayOfYear(1);
211             int offset = - (day1.get(dowField) - 1);
212             int week1 = day1.get(woyField);
213             if (week1 == 0) {
214                 // week of the 1st is partial; start with first full week
215                 offset += 7;
216             }
217             offset += actualDOW - 1;
218             offset += (actualWOY - 1) * 7;
219             LocalDate result = day1.plusDays(offset);
220 
221             assertEquals(result, day, "Incorrect dayOfWeek or weekOfYear "
222                     + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n",
223                     week, day.getDayOfWeek(), offset, actualDOW, actualWOY, day, result));
224             day = day.plusDays(1);
225         }
226     }
227 
228     /**
229      * Verify that the date can be reconstructed from the DOW, WeekOfWeekBasedYear,
230      * and WeekBasedYear for every combination of start of week
231      * and minimal days in week.
232      * @param firstDayOfWeek the first day of the week
233      * @param minDays the minimum number of days in the week
234      */
235     @Test(dataProvider="weekFields")
test_weekOfWeekBasedYearField(DayOfWeek firstDayOfWeek, int minDays)236     public void test_weekOfWeekBasedYearField(DayOfWeek firstDayOfWeek, int minDays) {
237         LocalDate day = LocalDate.of(2012, 12, 31);  // Known to be ISO Monday
238         WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays);
239         TemporalField dowField = weekDef.dayOfWeek();
240         TemporalField wowbyField = weekDef.weekOfWeekBasedYear();
241         TemporalField yowbyField = weekDef.weekBasedYear();
242 
243         for (int i = 1; i <= 15; i++) {
244             int actualDOW = day.get(dowField);
245             int actualWOWBY = day.get(wowbyField);
246             int actualYOWBY = day.get(yowbyField);
247 
248             // Verify that the combination of day of week and week of month can be used
249             // to reconstruct the same date.
250             LocalDate day1 = LocalDate.of(actualYOWBY, 1, 1);
251             DayOfWeek isoDOW = day1.getDayOfWeek();
252             int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1;
253 
254             int weekStart = Math.floorMod(1 - dow, 7);
255             if (weekStart + 1 > weekDef.getMinimalDaysInFirstWeek()) {
256                 // The previous week has the minimum days in the current month to be a 'week'
257                 weekStart -= 7;
258             }
259             weekStart += actualDOW - 1;
260             weekStart += (actualWOWBY - 1) * 7;
261             LocalDate result = day1.plusDays(weekStart);
262 
263             assertEquals(result, day, "Incorrect dayOfWeek or weekOfYear "
264                     + String.format("%s, ISO Dow: %s, weekStart: %s, actualDOW: %s, actualWOWBY: %s, YearOfWBY: %d, expected day: %s, result: %s%n",
265                     weekDef, day.getDayOfWeek(), weekStart, actualDOW, actualWOWBY, actualYOWBY, day, result));
266             day = day.plusDays(1);
267         }
268     }
269 
270     @Test(dataProvider="weekFields")
test_fieldRanges(DayOfWeek firstDayOfWeek, int minDays)271     public void test_fieldRanges(DayOfWeek firstDayOfWeek, int minDays) {
272         WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays);
273         TemporalField womField = weekDef.weekOfMonth();
274         TemporalField woyField = weekDef.weekOfYear();
275 
276         LocalDate day = LocalDate.of(2012, 11, 30);
277         LocalDate endDay = LocalDate.of(2013, 1, 2);
278         while (day.isBefore(endDay)) {
279             LocalDate last = day.with(DAY_OF_MONTH, day.lengthOfMonth());
280             int lastWOM = last.get(womField);
281             LocalDate first = day.with(DAY_OF_MONTH, 1);
282             int firstWOM = first.get(womField);
283             ValueRange rangeWOM = day.range(womField);
284             assertEquals(rangeWOM.getMinimum(), firstWOM,
285                     "Range min should be same as WeekOfMonth for first day of month: "
286                     + first + ", " + weekDef);
287             assertEquals(rangeWOM.getMaximum(), lastWOM,
288                     "Range max should be same as WeekOfMonth for last day of month: "
289                     + last + ", " + weekDef);
290 
291             last = day.with(DAY_OF_YEAR, day.lengthOfYear());
292             int lastWOY = last.get(woyField);
293             first = day.with(DAY_OF_YEAR, 1);
294             int firstWOY = first.get(woyField);
295             ValueRange rangeWOY = day.range(woyField);
296             assertEquals(rangeWOY.getMinimum(), firstWOY,
297                     "Range min should be same as WeekOfYear for first day of Year: "
298                     + day + ", " + weekDef);
299             assertEquals(rangeWOY.getMaximum(), lastWOY,
300                     "Range max should be same as WeekOfYear for last day of Year: "
301                     + day + ", " + weekDef);
302 
303             day = day.plusDays(1);
304         }
305     }
306 
307     //-----------------------------------------------------------------------
308     // withDayOfWeek()
309     //-----------------------------------------------------------------------
310     @Test(dataProvider="weekFields")
test_withDayOfWeek(DayOfWeek firstDayOfWeek, int minDays)311     public void test_withDayOfWeek(DayOfWeek firstDayOfWeek, int minDays) {
312         LocalDate day = LocalDate.of(2012, 12, 15);  // Safely in the middle of a month
313         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
314         TemporalField dowField = week.dayOfWeek();
315         TemporalField womField = week.weekOfMonth();
316         TemporalField woyField = week.weekOfYear();
317 
318         int wom = day.get(womField);
319         int woy = day.get(woyField);
320         for (int dow = 1; dow <= 7; dow++) {
321             LocalDate result = day.with(dowField, dow);
322             assertEquals(result.get(dowField), dow, String.format("Incorrect new Day of week: %s", result));
323             assertEquals(result.get(womField), wom, "Week of Month should not change");
324             assertEquals(result.get(woyField), woy, "Week of Year should not change");
325         }
326     }
327 
328     @Test(dataProvider="weekFields")
test_rangeWeekOfWeekBasedYear(DayOfWeek firstDayOfWeek, int minDays)329     public void test_rangeWeekOfWeekBasedYear(DayOfWeek firstDayOfWeek, int minDays) {
330         WeekFields weekFields = WeekFields.of(firstDayOfWeek, minDays);
331         TemporalField dowField = weekFields.dayOfWeek();
332         TemporalField wowByField = weekFields.weekOfWeekBasedYear();
333 
334         LocalDate day1 = LocalDate.of(2012, 1, weekFields.getMinimalDaysInFirstWeek());
335         day1 = day1.with(wowByField, 1).with(dowField, 1);
336 
337         LocalDate day2 = LocalDate.of(2013, 1, weekFields.getMinimalDaysInFirstWeek());
338         day2 = day2.with(wowByField, 1).with(dowField, 1);
339 
340         int expectedWeeks = (int)ChronoUnit.DAYS.between(day1, day2) / 7;
341 
342         ValueRange range = day1.range(wowByField);
343         assertEquals(range.getMaximum(), expectedWeeks, "Range incorrect");
344     }
345 
346     @Test(dataProvider="weekFields")
test_withWeekOfWeekBasedYear(DayOfWeek firstDayOfWeek, int minDays)347     public void test_withWeekOfWeekBasedYear(DayOfWeek firstDayOfWeek, int minDays) {
348         LocalDate day = LocalDate.of(2012, 12, 31);
349         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
350         TemporalField dowField = week.dayOfWeek();
351         TemporalField wowbyField = week.weekOfWeekBasedYear();
352         TemporalField yowbyField = week.weekBasedYear();
353 
354         int dowExpected = (day.get(dowField) - 1) % 7 + 1;
355         LocalDate dowDate = day.with(dowField, dowExpected);
356         int dowResult = dowDate.get(dowField);
357         assertEquals(dowResult, dowExpected, "Localized DayOfWeek not correct; " + day + " -->" + dowDate);
358 
359         int weekExpected = day.get(wowbyField) + 1;
360         ValueRange range = day.range(wowbyField);
361         weekExpected = ((weekExpected - 1) % (int)range.getMaximum()) + 1;
362         LocalDate weekDate = day.with(wowbyField, weekExpected);
363         int weekResult = weekDate.get(wowbyField);
364         assertEquals(weekResult, weekExpected, "Localized WeekOfWeekBasedYear not correct; " + day + " -->" + weekDate);
365 
366         int yearExpected = day.get(yowbyField) + 1;
367 
368         LocalDate yearDate = day.with(yowbyField, yearExpected);
369         int yearResult = yearDate.get(yowbyField);
370         assertEquals(yearResult, yearExpected, "Localized WeekBasedYear not correct; " + day  + " --> " + yearDate);
371 
372         range = yearDate.range(wowbyField);
373         weekExpected = Math.min(day.get(wowbyField), (int)range.getMaximum());
374 
375         int weekActual = yearDate.get(wowbyField);
376         assertEquals(weekActual, weekExpected, "Localized WeekOfWeekBasedYear week should not change; " + day + " --> " + yearDate + ", actual: " + weekActual + ", weekExpected: " + weekExpected);
377     }
378 
379     //-----------------------------------------------------------------------
380     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWom(DayOfWeek firstDayOfWeek, int minDays)381     public void test_parse_resolve_localizedWom(DayOfWeek firstDayOfWeek, int minDays) {
382         LocalDate date = LocalDate.of(2012, 12, 15);
383         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
384         TemporalField womField = week.weekOfMonth();
385 
386         for (int i = 1; i <= 60; i++) {
387             DateTimeFormatter f = new DateTimeFormatterBuilder()
388                     .appendValue(YEAR).appendLiteral(':')
389                     .appendValue(MONTH_OF_YEAR).appendLiteral(':')
390                     .appendValue(womField).appendLiteral(':')
391                     .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(SMART);
392             String str = date.getYear() + ":" + date.getMonthValue() + ":" +
393                     date.get(womField) + ":" + date.get(DAY_OF_WEEK);
394             LocalDate parsed = LocalDate.parse(str, f);
395             assertEquals(parsed, date, " ::" + str + "::" + i);
396 
397             date = date.plusDays(1);
398         }
399     }
400 
401     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWom_lenient(DayOfWeek firstDayOfWeek, int minDays)402     public void test_parse_resolve_localizedWom_lenient(DayOfWeek firstDayOfWeek, int minDays) {
403         LocalDate date = LocalDate.of(2012, 12, 15);
404         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
405         TemporalField womField = week.weekOfMonth();
406 
407         for (int i = 1; i <= 60; i++) {
408             DateTimeFormatter f = new DateTimeFormatterBuilder()
409                     .appendValue(YEAR).appendLiteral(':')
410                     .appendValue(MONTH_OF_YEAR).appendLiteral(':')
411                     .appendValue(womField).appendLiteral(':')
412                     .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
413             int wom = date.get(womField);
414             int dow = date.get(DAY_OF_WEEK);
415             for (int j = wom - 10; j < wom + 10; j++) {
416                 String str = date.getYear() + ":" + date.getMonthValue() + ":" + j + ":" + dow;
417                 LocalDate parsed = LocalDate.parse(str, f);
418                 assertEquals(parsed, date.plusWeeks(j - wom), " ::" + str + ": :" + i + "::" + j);
419             }
420 
421             date = date.plusDays(1);
422         }
423     }
424 
425     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWom_strict(DayOfWeek firstDayOfWeek, int minDays)426     public void test_parse_resolve_localizedWom_strict(DayOfWeek firstDayOfWeek, int minDays) {
427         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
428         TemporalField womField = week.weekOfMonth();
429         DateTimeFormatter f = new DateTimeFormatterBuilder()
430                 .appendValue(YEAR).appendLiteral(':')
431                 .appendValue(MONTH_OF_YEAR).appendLiteral(':')
432                 .appendValue(womField).appendLiteral(':')
433                 .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
434         String str = "2012:1:0:1";
435         try {
436             LocalDate date = LocalDate.parse(str, f);
437             assertEquals(date.getYear(), 2012);
438             assertEquals(date.getMonthValue(), 1);
439             assertEquals(date.get(womField), 0);
440             assertEquals(date.get(DAY_OF_WEEK), 1);
441         } catch (DateTimeException ex) {
442             // expected
443         }
444     }
445 
446     //-----------------------------------------------------------------------
447     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWomDow(DayOfWeek firstDayOfWeek, int minDays)448     public void test_parse_resolve_localizedWomDow(DayOfWeek firstDayOfWeek, int minDays) {
449         LocalDate date = LocalDate.of(2012, 12, 15);
450         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
451         TemporalField dowField = week.dayOfWeek();
452         TemporalField womField = week.weekOfMonth();
453 
454         for (int i = 1; i <= 15; i++) {
455             DateTimeFormatter f = new DateTimeFormatterBuilder()
456                     .appendValue(YEAR).appendLiteral(':')
457                     .appendValue(MONTH_OF_YEAR).appendLiteral(':')
458                     .appendValue(womField).appendLiteral(':')
459                     .appendValue(dowField).toFormatter();
460             String str = date.getYear() + ":" + date.getMonthValue() + ":" +
461                     date.get(womField) + ":" + date.get(dowField);
462             LocalDate parsed = LocalDate.parse(str, f);
463             assertEquals(parsed, date, " :: " + str + " " + i);
464 
465             date = date.plusDays(1);
466         }
467     }
468 
469     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWomDow_lenient(DayOfWeek firstDayOfWeek, int minDays)470     public void test_parse_resolve_localizedWomDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
471         LocalDate date = LocalDate.of(2012, 12, 15);
472         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
473         TemporalField dowField = week.dayOfWeek();
474         TemporalField womField = week.weekOfMonth();
475 
476         for (int i = 1; i <= 60; i++) {
477             DateTimeFormatter f = new DateTimeFormatterBuilder()
478                     .appendValue(YEAR).appendLiteral(':')
479                     .appendValue(MONTH_OF_YEAR).appendLiteral(':')
480                     .appendValue(womField).appendLiteral(':')
481                     .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
482             int wom = date.get(womField);
483             int dow = date.get(dowField);
484             for (int j = wom - 10; j < wom + 10; j++) {
485                 String str = date.getYear() + ":" + date.getMonthValue() + ":" + j + ":" + dow;
486                 LocalDate parsed = LocalDate.parse(str, f);
487                 assertEquals(parsed, date.plusWeeks(j - wom), " ::" + str + ": :" + i + "::" + j);
488             }
489 
490             date = date.plusDays(1);
491         }
492     }
493 
494     //-----------------------------------------------------------------------
495     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoy(DayOfWeek firstDayOfWeek, int minDays)496     public void test_parse_resolve_localizedWoy(DayOfWeek firstDayOfWeek, int minDays) {
497         LocalDate date = LocalDate.of(2012, 12, 15);
498         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
499         TemporalField woyField = week.weekOfYear();
500 
501         for (int i = 1; i <= 60; i++) {
502             DateTimeFormatter f = new DateTimeFormatterBuilder()
503                     .appendValue(YEAR).appendLiteral(':')
504                     .appendValue(woyField).appendLiteral(':')
505                     .appendValue(DAY_OF_WEEK).toFormatter();
506             String str = date.getYear() + ":" +
507                     date.get(woyField) + ":" + date.get(DAY_OF_WEEK);
508             LocalDate parsed = LocalDate.parse(str, f);
509             assertEquals(parsed, date, " :: " + str + " " + i);
510 
511             date = date.plusDays(1);
512         }
513     }
514 
515     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoy_lenient(DayOfWeek firstDayOfWeek, int minDays)516     public void test_parse_resolve_localizedWoy_lenient(DayOfWeek firstDayOfWeek, int minDays) {
517         LocalDate date = LocalDate.of(2012, 12, 15);
518         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
519         TemporalField woyField = week.weekOfYear();
520 
521         for (int i = 1; i <= 60; i++) {
522             DateTimeFormatter f = new DateTimeFormatterBuilder()
523                     .appendValue(YEAR).appendLiteral(':')
524                     .appendValue(woyField).appendLiteral(':')
525                     .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
526             int woy = date.get(woyField);
527             int dow = date.get(DAY_OF_WEEK);
528             for (int j = woy - 60; j < woy + 60; j++) {
529                 String str = date.getYear() + ":" + j + ":" + dow;
530                 LocalDate parsed = LocalDate.parse(str, f);
531                 assertEquals(parsed, date.plusWeeks(j - woy), " ::" + str + ": :" + i + "::" + j);
532             }
533 
534             date = date.plusDays(1);
535         }
536     }
537 
538     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoy_strict(DayOfWeek firstDayOfWeek, int minDays)539     public void test_parse_resolve_localizedWoy_strict(DayOfWeek firstDayOfWeek, int minDays) {
540         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
541         TemporalField woyField = week.weekOfYear();
542         DateTimeFormatter f = new DateTimeFormatterBuilder()
543                 .appendValue(YEAR).appendLiteral(':')
544                 .appendValue(woyField).appendLiteral(':')
545                 .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
546         String str = "2012:0:1";
547         try {
548             LocalDate date = LocalDate.parse(str, f);
549             assertEquals(date.getYear(), 2012);
550             assertEquals(date.get(woyField), 0);
551             assertEquals(date.get(DAY_OF_WEEK), 1);
552         } catch (DateTimeException ex) {
553             // expected
554         }
555     }
556 
557     //-----------------------------------------------------------------------
558     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoyDow(DayOfWeek firstDayOfWeek, int minDays)559     public void test_parse_resolve_localizedWoyDow(DayOfWeek firstDayOfWeek, int minDays) {
560         LocalDate date = LocalDate.of(2012, 12, 15);
561         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
562         TemporalField dowField = week.dayOfWeek();
563         TemporalField woyField = week.weekOfYear();
564 
565         for (int i = 1; i <= 60; i++) {
566             DateTimeFormatter f = new DateTimeFormatterBuilder()
567                     .appendValue(YEAR).appendLiteral(':')
568                     .appendValue(MONTH_OF_YEAR).appendLiteral(':')
569                     .appendValue(woyField).appendLiteral(':')
570                     .appendValue(dowField).toFormatter();
571             String str = date.getYear() + ":" + date.getMonthValue() + ":" +
572                     date.get(woyField) + ":" + date.get(dowField);
573             LocalDate parsed = LocalDate.parse(str, f);
574             assertEquals(parsed, date, " :: " + str + " " + i);
575 
576             date = date.plusDays(1);
577         }
578     }
579 
580     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoyDow_lenient(DayOfWeek firstDayOfWeek, int minDays)581     public void test_parse_resolve_localizedWoyDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
582         LocalDate date = LocalDate.of(2012, 12, 15);
583         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
584         TemporalField dowField = week.dayOfWeek();
585         TemporalField woyField = week.weekOfYear();
586 
587         for (int i = 1; i <= 60; i++) {
588             DateTimeFormatter f = new DateTimeFormatterBuilder()
589                     .appendValue(YEAR).appendLiteral(':')
590                     .appendValue(woyField).appendLiteral(':')
591                     .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
592             int woy = date.get(woyField);
593             int dow = date.get(dowField);
594             for (int j = woy - 60; j < woy + 60; j++) {
595                 String str = date.getYear() + ":" + j + ":" + dow;
596                 LocalDate parsed = LocalDate.parse(str, f);
597                 assertEquals(parsed, date.plusWeeks(j - woy), " ::" + str + ": :" + i + "::" + j);
598             }
599 
600             date = date.plusDays(1);
601         }
602     }
603 
604     //-----------------------------------------------------------------------
605     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoWBY(DayOfWeek firstDayOfWeek, int minDays)606     public void test_parse_resolve_localizedWoWBY(DayOfWeek firstDayOfWeek, int minDays) {
607         LocalDate date = LocalDate.of(2012, 12, 31);
608         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
609         TemporalField wowbyField = week.weekOfWeekBasedYear();
610         TemporalField yowbyField = week.weekBasedYear();
611 
612         for (int i = 1; i <= 60; i++) {
613             DateTimeFormatter f = new DateTimeFormatterBuilder()
614                     .appendValue(yowbyField).appendLiteral(':')
615                     .appendValue(wowbyField).appendLiteral(':')
616                     .appendValue(DAY_OF_WEEK).toFormatter();
617             String str = date.get(yowbyField) + ":" + date.get(wowbyField) + ":" +
618                     date.get(DAY_OF_WEEK);
619             LocalDate parsed = LocalDate.parse(str, f);
620             assertEquals(parsed, date, " :: " + str + " " + i);
621 
622             date = date.plusDays(1);
623         }
624     }
625 
626     @LargeTest
627     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoWBY_lenient(DayOfWeek firstDayOfWeek, int minDays)628     public void test_parse_resolve_localizedWoWBY_lenient(DayOfWeek firstDayOfWeek, int minDays) {
629         LocalDate date = LocalDate.of(2012, 12, 31);
630         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
631         TemporalField wowbyField = week.weekOfWeekBasedYear();
632         TemporalField yowbyField = week.weekBasedYear();
633 
634         for (int i = 1; i <= 60; i++) {
635             DateTimeFormatter f = new DateTimeFormatterBuilder()
636                     .appendValue(yowbyField).appendLiteral(':')
637                     .appendValue(wowbyField).appendLiteral(':')
638                     .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(LENIENT);
639             int wowby = date.get(wowbyField);
640             int dow = date.get(DAY_OF_WEEK);
641             for (int j = wowby - 60; j < wowby + 60; j++) {
642                 String str = date.get(yowbyField) + ":" + j + ":" + dow;
643                 LocalDate parsed = LocalDate.parse(str, f);
644                 assertEquals(parsed, date.plusWeeks(j - wowby), " ::" + str + ": :" + i + "::" + j);
645             }
646 
647             date = date.plusDays(1);
648         }
649     }
650 
651     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoWBY_strict(DayOfWeek firstDayOfWeek, int minDays)652     public void test_parse_resolve_localizedWoWBY_strict(DayOfWeek firstDayOfWeek, int minDays) {
653         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
654         TemporalField wowbyField = week.weekOfWeekBasedYear();
655         TemporalField yowbyField = week.weekBasedYear();
656         DateTimeFormatter f = new DateTimeFormatterBuilder()
657                 .appendValue(yowbyField).appendLiteral(':')
658                 .appendValue(wowbyField).appendLiteral(':')
659                 .appendValue(DAY_OF_WEEK).toFormatter().withResolverStyle(STRICT);
660         String str = "2012:0:1";
661         try {
662             LocalDate date = LocalDate.parse(str, f);
663             assertEquals(date.get(yowbyField), 2012);
664             assertEquals(date.get(wowbyField), 0);
665             assertEquals(date.get(DAY_OF_WEEK), 1);
666         } catch (DateTimeException ex) {
667             // expected
668         }
669     }
670 
671     //-----------------------------------------------------------------------
672     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoWBYDow(DayOfWeek firstDayOfWeek, int minDays)673     public void test_parse_resolve_localizedWoWBYDow(DayOfWeek firstDayOfWeek, int minDays) {
674         LocalDate date = LocalDate.of(2012, 12, 31);
675         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
676         TemporalField dowField = week.dayOfWeek();
677         TemporalField wowbyField = week.weekOfWeekBasedYear();
678         TemporalField yowbyField = week.weekBasedYear();
679 
680         for (int i = 1; i <= 60; i++) {
681             DateTimeFormatter f = new DateTimeFormatterBuilder()
682                     .appendValue(yowbyField).appendLiteral(':')
683                     .appendValue(wowbyField).appendLiteral(':')
684                     .appendValue(dowField).toFormatter();
685             String str = date.get(yowbyField) + ":" + date.get(wowbyField) + ":" +
686                     date.get(dowField);
687             LocalDate parsed = LocalDate.parse(str, f);
688             assertEquals(parsed, date, " :: " + str + " " + i);
689 
690             date = date.plusDays(1);
691         }
692     }
693 
694     @Test(dataProvider="weekFields")
test_parse_resolve_localizedWoWBYDow_lenient(DayOfWeek firstDayOfWeek, int minDays)695     public void test_parse_resolve_localizedWoWBYDow_lenient(DayOfWeek firstDayOfWeek, int minDays) {
696         LocalDate date = LocalDate.of(2012, 12, 31);
697         WeekFields week = WeekFields.of(firstDayOfWeek, minDays);
698         TemporalField dowField = week.dayOfWeek();
699         TemporalField wowbyField = week.weekOfWeekBasedYear();
700         TemporalField yowbyField = week.weekBasedYear();
701 
702         for (int i = 1; i <= 60; i++) {
703             DateTimeFormatter f = new DateTimeFormatterBuilder()
704                     .appendValue(yowbyField).appendLiteral(':')
705                     .appendValue(wowbyField).appendLiteral(':')
706                     .appendValue(dowField).toFormatter().withResolverStyle(LENIENT);
707             int wowby = date.get(wowbyField);
708             int dow = date.get(dowField);
709             for (int j = wowby - 60; j < wowby + 60; j++) {
710                 String str = date.get(yowbyField) + ":" + j + ":" + dow;
711                 LocalDate parsed = LocalDate.parse(str, f);
712                 assertEquals(parsed, date.plusWeeks(j - wowby), " ::" + str + ": :" + i + "::" + j);
713             }
714 
715             date = date.plusDays(1);
716         }
717     }
718 
719 
720     //-----------------------------------------------------------------------
721     @DataProvider(name="weekFields")
data_weekFields()722     Object[][] data_weekFields() {
723         Object[][] objects = new Object[49][];
724         int i = 0;
725         for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) {
726             for (int minDays = 1; minDays <= 7; minDays++) {
727                 objects[i++] = new Object[] {firstDayOfWeek, minDays};
728             }
729         }
730         return objects;
731     }
732 
733     //-----------------------------------------------------------------------
734     @DataProvider(name="WeekBasedYearData")
provider_WeekBasedYearData()735     Object[][] provider_WeekBasedYearData() {
736         return new Object[][] {
737             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2008, 52, 7, LocalDate.of(2008, 12, 27)},
738             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  1, 1, LocalDate.of(2008, 12, 28)},
739             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  1, 2, LocalDate.of(2008, 12, 29)},
740             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  1, 3, LocalDate.of(2008, 12, 30)},
741             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  1, 4, LocalDate.of(2008, 12, 31)},
742             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  1, 5, LocalDate.of(2009, 1, 1)},
743             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  2, 1, LocalDate.of(2009, 1, 4)},
744             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  2, 2, LocalDate.of(2009, 1, 5)},
745             {WeekFields.of(DayOfWeek.SUNDAY, 1),  2009,  2, 3, LocalDate.of(2009, 1, 6)},
746        };
747     }
748 
749     @Test(dataProvider="WeekBasedYearData")
test_weekBasedYears(WeekFields weekDef, int weekBasedYear, int weekOfWeekBasedYear, int dayOfWeek, LocalDate date)750     public void test_weekBasedYears(WeekFields weekDef, int weekBasedYear,
751             int weekOfWeekBasedYear, int dayOfWeek, LocalDate date) {
752         TemporalField dowField = weekDef.dayOfWeek();
753         TemporalField wowbyField = weekDef.weekOfWeekBasedYear();
754         TemporalField yowbyField = weekDef.weekBasedYear();
755         assertEquals(date.get(dowField), dayOfWeek, "DayOfWeek mismatch");
756         assertEquals(date.get(wowbyField), weekOfWeekBasedYear, "Week of WeekBasedYear mismatch");
757         assertEquals(date.get(yowbyField), weekBasedYear, "Year of WeekBasedYear mismatch");
758     }
759 
760 
761     //-----------------------------------------------------------------------
762     @DataProvider(name="IsoWeekData")
data_week()763     Object[][] data_week() {
764         return new Object[][] {
765                 {LocalDate.of(1969, 12, 29), DayOfWeek.MONDAY, 1, 1970},
766                 {LocalDate.of(2012, 12, 23), DayOfWeek.SUNDAY, 51, 2012},
767                 {LocalDate.of(2012, 12, 24), DayOfWeek.MONDAY, 52, 2012},
768                 {LocalDate.of(2012, 12, 27), DayOfWeek.THURSDAY, 52, 2012},
769                 {LocalDate.of(2012, 12, 28), DayOfWeek.FRIDAY, 52, 2012},
770                 {LocalDate.of(2012, 12, 29), DayOfWeek.SATURDAY, 52, 2012},
771                 {LocalDate.of(2012, 12, 30), DayOfWeek.SUNDAY, 52, 2012},
772                 {LocalDate.of(2012, 12, 31), DayOfWeek.MONDAY, 1, 2013},
773                 {LocalDate.of(2013, 1, 1), DayOfWeek.TUESDAY, 1, 2013},
774                 {LocalDate.of(2013, 1, 2), DayOfWeek.WEDNESDAY, 1, 2013},
775                 {LocalDate.of(2013, 1, 6), DayOfWeek.SUNDAY, 1, 2013},
776                 {LocalDate.of(2013, 1, 7), DayOfWeek.MONDAY, 2, 2013},
777         };
778     }
779 
780     //-----------------------------------------------------------------------
781     // WEEK_OF_WEEK_BASED_YEAR
782     // Validate with the same data used by IsoFields.
783     //-----------------------------------------------------------------------
784     @Test(dataProvider="IsoWeekData")
test_WOWBY(LocalDate date, DayOfWeek dow, int week, int wby)785     public void test_WOWBY(LocalDate date, DayOfWeek dow, int week, int wby) {
786         WeekFields weekDef = WeekFields.ISO;
787         TemporalField dowField = weekDef.dayOfWeek();
788         TemporalField wowbyField = weekDef.weekOfWeekBasedYear();
789         TemporalField yowbyField = weekDef.weekBasedYear();
790 
791         assertEquals(date.get(dowField), dow.getValue());
792         assertEquals(date.get(wowbyField), week);
793         assertEquals(date.get(yowbyField), wby);
794     }
795 
796     //-----------------------------------------------------------------------
797     // equals() and hashCode().
798     //-----------------------------------------------------------------------
799     @Test
test_equals()800     public void test_equals() {
801         WeekFields weekDef_iso = WeekFields.ISO;
802         WeekFields weekDef_sundayStart = WeekFields.SUNDAY_START;
803 
804         assertTrue(weekDef_iso.equals(WeekFields.of(DayOfWeek.MONDAY, 4)));
805         assertTrue(weekDef_sundayStart.equals(WeekFields.of(DayOfWeek.SUNDAY, 1)));
806         assertEquals(weekDef_iso.hashCode(), WeekFields.of(DayOfWeek.MONDAY, 4).hashCode());
807         assertEquals(weekDef_sundayStart.hashCode(), WeekFields.of(DayOfWeek.SUNDAY, 1).hashCode());
808 
809         assertFalse(weekDef_iso.equals(weekDef_sundayStart));
810         assertNotEquals(weekDef_iso.hashCode(), weekDef_sundayStart.hashCode());
811     }
812 
813 }
814