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