Home | History | Annotate | Download | only in temporal
      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.DayOfWeek.FRIDAY;
     60 import static java.time.DayOfWeek.MONDAY;
     61 import static java.time.DayOfWeek.SATURDAY;
     62 import static java.time.DayOfWeek.SUNDAY;
     63 import static java.time.DayOfWeek.THURSDAY;
     64 import static java.time.DayOfWeek.TUESDAY;
     65 import static java.time.DayOfWeek.WEDNESDAY;
     66 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
     67 import static java.time.temporal.ChronoField.YEAR;
     68 import static org.testng.Assert.assertEquals;
     69 import static org.testng.Assert.fail;
     70 
     71 import java.time.DayOfWeek;
     72 import java.time.LocalDate;
     73 import java.time.LocalDateTime;
     74 import java.time.format.DateTimeFormatter;
     75 import java.time.format.DateTimeFormatterBuilder;
     76 import java.time.format.DateTimeParseException;
     77 import java.time.format.ResolverStyle;
     78 import java.time.temporal.IsoFields;
     79 import java.time.temporal.Temporal;
     80 import java.time.temporal.ValueRange;
     81 
     82 import org.testng.annotations.DataProvider;
     83 import org.testng.annotations.Test;
     84 
     85 /**
     86  * Test.
     87  */
     88 @Test
     89 public class TCKIsoFields {
     90 
     91     @DataProvider(name="quarter")
     92     Object[][] data_quarter() {
     93         return new Object[][] {
     94                 {LocalDate.of(1969, 12, 29), 90, 4},
     95                 {LocalDate.of(1969, 12, 30), 91, 4},
     96                 {LocalDate.of(1969, 12, 31), 92, 4},
     97 
     98                 {LocalDate.of(1970, 1, 1), 1, 1},
     99                 {LocalDate.of(1970, 1, 2), 2, 1},
    100                 {LocalDate.of(1970, 2, 28), 59, 1},
    101                 {LocalDate.of(1970, 3, 1), 60, 1},
    102                 {LocalDate.of(1970, 3, 31), 90, 1},
    103 
    104                 {LocalDate.of(1970, 4, 1), 1, 2},
    105                 {LocalDate.of(1970, 6, 30), 91, 2},
    106 
    107                 {LocalDate.of(1970, 7, 1), 1, 3},
    108                 {LocalDate.of(1970, 9, 30), 92, 3},
    109 
    110                 {LocalDate.of(1970, 10, 1), 1, 4},
    111                 {LocalDate.of(1970, 12, 31), 92, 4},
    112 
    113                 {LocalDate.of(1972, 2, 28), 59, 1},
    114                 {LocalDate.of(1972, 2, 29), 60, 1},
    115                 {LocalDate.of(1972, 3, 1), 61, 1},
    116                 {LocalDate.of(1972, 3, 31), 91, 1},
    117         };
    118     }
    119 
    120     //-----------------------------------------------------------------------
    121     // DAY_OF_QUARTER
    122     //-----------------------------------------------------------------------
    123     @Test(dataProvider = "quarter")
    124     public void test_DOQ(LocalDate date, int doq, int qoy) {
    125         assertEquals(IsoFields.DAY_OF_QUARTER.getFrom(date), doq);
    126         assertEquals(date.get(IsoFields.DAY_OF_QUARTER), doq);
    127     }
    128 
    129     public void test_DOQ_basics() {
    130         assertEquals(IsoFields.DAY_OF_QUARTER.isDateBased(), true);
    131         assertEquals(IsoFields.DAY_OF_QUARTER.isTimeBased(), false);
    132     }
    133 
    134     //-----------------------------------------------------------------------
    135     // QUARTER_OF_YEAR
    136     //-----------------------------------------------------------------------
    137     @Test(dataProvider = "quarter")
    138     public void test_QOY(LocalDate date, int doq, int qoy) {
    139         assertEquals(IsoFields.QUARTER_OF_YEAR.getFrom(date), qoy);
    140         assertEquals(date.get(IsoFields.QUARTER_OF_YEAR), qoy);
    141     }
    142 
    143     public void test_QOY_basics() {
    144         assertEquals(IsoFields.QUARTER_OF_YEAR.isDateBased(), true);
    145         assertEquals(IsoFields.QUARTER_OF_YEAR.isTimeBased(), false);
    146     }
    147 
    148     //-----------------------------------------------------------------------
    149     // parse quarters
    150     //-----------------------------------------------------------------------
    151     @Test(dataProvider = "quarter")
    152     public void test_parse_quarters(LocalDate date, int doq, int qoy) {
    153         DateTimeFormatter f = new DateTimeFormatterBuilder()
    154                 .appendValue(YEAR).appendLiteral('-')
    155                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral('-')
    156                 .appendValue(IsoFields.DAY_OF_QUARTER)
    157                 .toFormatter().withResolverStyle(ResolverStyle.STRICT);
    158         LocalDate parsed = LocalDate.parse(date.getYear() + "-" + qoy + "-" + doq, f);
    159         assertEquals(parsed, date);
    160     }
    161 
    162     @Test(dataProvider = "quarter")
    163     public void test_parse_quarters_SMART(LocalDate date, int doq, int qoy) {
    164         DateTimeFormatter f = new DateTimeFormatterBuilder()
    165                 .appendValue(YEAR).appendLiteral('-')
    166                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral('-')
    167                 .appendValue(IsoFields.DAY_OF_QUARTER)
    168                 .toFormatter().withResolverStyle(ResolverStyle.SMART);
    169         LocalDate parsed = LocalDate.parse(date.getYear() + "-" + qoy + "-" + doq, f);
    170         assertEquals(parsed, date);
    171     }
    172 
    173     @Test(dataProvider = "quarter")
    174     public void test_parse_quarters_LENIENT(LocalDate date, int doq, int qoy) {
    175         DateTimeFormatter f = new DateTimeFormatterBuilder()
    176                 .appendValue(YEAR).appendLiteral('-')
    177                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral('-')
    178                 .appendValue(IsoFields.DAY_OF_QUARTER)
    179                 .toFormatter().withResolverStyle(ResolverStyle.LENIENT);
    180         LocalDate parsed = LocalDate.parse(date.getYear() + "-" + qoy + "-" + doq, f);
    181         assertEquals(parsed, date);
    182     }
    183 
    184     //-----------------------------------------------------------------------
    185     @DataProvider(name="parseLenientQuarter")
    186     Object[][] data_parseLenientQuarter() {
    187         return new Object[][] {
    188                 {"2012:0:1", LocalDate.of(2011, 10, 1), false},
    189                 {"2012:5:1", LocalDate.of(2013, 1, 1), false},
    190 
    191                 {"2012:1:-1", LocalDate.of(2011, 12, 30), false},
    192                 {"2012:1:0", LocalDate.of(2011, 12, 31), false},
    193                 {"2012:0:0", LocalDate.of(2011, 9, 30), false},
    194 
    195                 {"2012:1:92", LocalDate.of(2012, 4, 1), true},
    196                 {"2012:2:92", LocalDate.of(2012, 7, 1), true},
    197                 {"2012:2:93", LocalDate.of(2012, 7, 2), false},
    198                 {"2012:3:93", LocalDate.of(2012, 10, 1), false},
    199                 {"2012:4:93", LocalDate.of(2013, 1, 1), false},
    200                 {"2012:4:182", LocalDate.of(2013, 3, 31), false},
    201                 {"2012:4:183", LocalDate.of(2013, 4, 1), false},
    202 
    203                 {"2011:1:91", LocalDate.of(2011, 4, 1), true},
    204                 {"2011:1:92", LocalDate.of(2011, 4, 2), true},
    205         };
    206     }
    207 
    208     @Test(dataProvider = "parseLenientQuarter", expectedExceptions = DateTimeParseException.class)
    209     public void test_parse_parseLenientQuarter_STRICT(String str, LocalDate expected, boolean smart) {
    210         DateTimeFormatter f = new DateTimeFormatterBuilder()
    211                 .appendValue(YEAR).appendLiteral(':')
    212                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral(':')
    213                 .appendValue(IsoFields.DAY_OF_QUARTER)
    214                 .toFormatter().withResolverStyle(ResolverStyle.STRICT);
    215         LocalDate.parse(str, f);
    216     }
    217 
    218     @Test(dataProvider = "parseLenientQuarter")
    219     public void test_parse_parseLenientQuarter_SMART(String str, LocalDate expected, boolean smart) {
    220         DateTimeFormatter f = new DateTimeFormatterBuilder()
    221                 .appendValue(YEAR).appendLiteral(':')
    222                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral(':')
    223                 .appendValue(IsoFields.DAY_OF_QUARTER)
    224                 .toFormatter().withResolverStyle(ResolverStyle.SMART);
    225         if (smart) {
    226             LocalDate parsed = LocalDate.parse(str, f);
    227             assertEquals(parsed, expected);
    228         } else {
    229             try {
    230                 LocalDate.parse(str, f);
    231                 fail("Should have failed");
    232             } catch (DateTimeParseException ex) {
    233                 // expected
    234             }
    235         }
    236     }
    237 
    238     @Test(dataProvider = "parseLenientQuarter")
    239     public void test_parse_parseLenientQuarter_LENIENT(String str, LocalDate expected, boolean smart) {
    240         DateTimeFormatter f = new DateTimeFormatterBuilder()
    241                 .appendValue(YEAR).appendLiteral(':')
    242                 .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral(':')
    243                 .appendValue(IsoFields.DAY_OF_QUARTER)
    244                 .toFormatter().withResolverStyle(ResolverStyle.LENIENT);
    245         LocalDate parsed = LocalDate.parse(str, f);
    246         assertEquals(parsed, expected);
    247     }
    248 
    249     //-----------------------------------------------------------------------
    250     // quarters between
    251     //-----------------------------------------------------------------------
    252     @DataProvider(name="quartersBetween")
    253     Object[][] data_quartersBetween() {
    254         return new Object[][] {
    255                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 1), 0},
    256                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 2), 0},
    257                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 2, 1), 0},
    258                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 3, 1), 0},
    259                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 3, 31), 0},
    260                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 4, 1), 1},
    261                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 4, 2), 1},
    262                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 6, 30), 1},
    263                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 7, 1), 2},
    264                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 10, 1), 3},
    265                 {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 12, 31), 3},
    266                 {LocalDate.of(2000, 1, 1), LocalDate.of(2001, 1, 1), 4},
    267                 {LocalDate.of(2000, 1, 1), LocalDate.of(2002, 1, 1), 8},
    268 
    269                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 12, 31), 0},
    270                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 10, 2), 0},
    271                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 10, 1), -1},
    272                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 7, 2), -1},
    273                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 7, 1), -2},
    274                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 4, 2), -2},
    275                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 4, 1), -3},
    276                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 1, 2), -3},
    277                 {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 1, 1), -4},
    278                 {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 12, 31), -4},
    279                 {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 2), -4},
    280                 {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 1), -5},
    281 
    282                 {LocalDate.of(2000, 1, 1), LocalDateTime.of(2001, 4, 5, 0, 0), 5},
    283         };
    284     }
    285 
    286     @Test(dataProvider="quartersBetween")
    287     public void test_quarters_between(LocalDate start, Temporal end, long expected) {
    288         assertEquals(IsoFields.QUARTER_YEARS.between(start, end), expected);
    289     }
    290 
    291     @Test(dataProvider="quartersBetween")
    292     public void test_quarters_between_until(LocalDate start, Temporal end, long expected) {
    293         assertEquals(start.until(end, IsoFields.QUARTER_YEARS), expected);
    294     }
    295 
    296     //-----------------------------------------------------------------------
    297     //-----------------------------------------------------------------------
    298     //-----------------------------------------------------------------------
    299     @DataProvider(name="week")
    300     Object[][] data_week() {
    301         return new Object[][] {
    302                 {LocalDate.of(1969, 12, 29), MONDAY, 1, 1970},
    303                 {LocalDate.of(2012, 12, 23), SUNDAY, 51, 2012},
    304                 {LocalDate.of(2012, 12, 24), MONDAY, 52, 2012},
    305                 {LocalDate.of(2012, 12, 27), THURSDAY, 52, 2012},
    306                 {LocalDate.of(2012, 12, 28), FRIDAY, 52, 2012},
    307                 {LocalDate.of(2012, 12, 29), SATURDAY, 52, 2012},
    308                 {LocalDate.of(2012, 12, 30), SUNDAY, 52, 2012},
    309                 {LocalDate.of(2012, 12, 31), MONDAY, 1, 2013},
    310                 {LocalDate.of(2013, 1, 1), TUESDAY, 1, 2013},
    311                 {LocalDate.of(2013, 1, 2), WEDNESDAY, 1, 2013},
    312                 {LocalDate.of(2013, 1, 6), SUNDAY, 1, 2013},
    313                 {LocalDate.of(2013, 1, 7), MONDAY, 2, 2013},
    314         };
    315     }
    316 
    317     //-----------------------------------------------------------------------
    318     // WEEK_OF_WEEK_BASED_YEAR
    319     //-----------------------------------------------------------------------
    320     @Test(dataProvider="week")
    321     public void test_WOWBY(LocalDate date, DayOfWeek dow, int week, int wby) {
    322         assertEquals(date.getDayOfWeek(), dow);
    323         assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.getFrom(date), week);
    324         assertEquals(date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR), week);
    325     }
    326 
    327     public void test_WOWBY_basics() {
    328         assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.isDateBased(), true);
    329         assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.isTimeBased(), false);
    330     }
    331 
    332     //-----------------------------------------------------------------------
    333     // WEEK_BASED_YEAR
    334     //-----------------------------------------------------------------------
    335     @Test(dataProvider="week")
    336     public void test_WBY(LocalDate date, DayOfWeek dow, int week, int wby) {
    337         assertEquals(date.getDayOfWeek(), dow);
    338         assertEquals(IsoFields.WEEK_BASED_YEAR.getFrom(date), wby);
    339         assertEquals(date.get(IsoFields.WEEK_BASED_YEAR), wby);
    340     }
    341 
    342     public void test_WBY_basics() {
    343         assertEquals(IsoFields.WEEK_BASED_YEAR.isDateBased(), true);
    344         assertEquals(IsoFields.WEEK_BASED_YEAR.isTimeBased(), false);
    345     }
    346 
    347     //-----------------------------------------------------------------------
    348     // parse weeks
    349     //-----------------------------------------------------------------------
    350     @Test(dataProvider="week")
    351     public void test_parse_weeks_STRICT(LocalDate date, DayOfWeek dow, int week, int wby) {
    352         DateTimeFormatter f = new DateTimeFormatterBuilder()
    353                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral('-')
    354                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral('-')
    355                 .appendValue(DAY_OF_WEEK)
    356                 .toFormatter().withResolverStyle(ResolverStyle.STRICT);
    357         LocalDate parsed = LocalDate.parse(wby + "-" + week + "-" + dow.getValue(), f);
    358         assertEquals(parsed, date);
    359     }
    360 
    361     @Test(dataProvider="week")
    362     public void test_parse_weeks_SMART(LocalDate date, DayOfWeek dow, int week, int wby) {
    363         DateTimeFormatter f = new DateTimeFormatterBuilder()
    364                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral('-')
    365                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral('-')
    366                 .appendValue(DAY_OF_WEEK)
    367                 .toFormatter().withResolverStyle(ResolverStyle.SMART);
    368         LocalDate parsed = LocalDate.parse(wby + "-" + week + "-" + dow.getValue(), f);
    369         assertEquals(parsed, date);
    370     }
    371 
    372     @Test(dataProvider="week")
    373     public void test_parse_weeks_LENIENT(LocalDate date, DayOfWeek dow, int week, int wby) {
    374         DateTimeFormatter f = new DateTimeFormatterBuilder()
    375                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral('-')
    376                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral('-')
    377                 .appendValue(DAY_OF_WEEK)
    378                 .toFormatter().withResolverStyle(ResolverStyle.LENIENT);
    379         LocalDate parsed = LocalDate.parse(wby + "-" + week + "-" + dow.getValue(), f);
    380         assertEquals(parsed, date);
    381     }
    382 
    383     //-----------------------------------------------------------------------
    384     @DataProvider(name="parseLenientWeek")
    385     Object[][] data_parseLenientWeek() {
    386         return new Object[][] {
    387                 {"2012:52:-1", LocalDate.of(2012, 12, 22), false},
    388                 {"2012:52:0", LocalDate.of(2012, 12, 23), false},
    389                 {"2012:52:8", LocalDate.of(2012, 12, 31), false},
    390                 {"2012:52:9", LocalDate.of(2013, 1, 1), false},
    391 
    392                 {"2012:53:1", LocalDate.of(2012, 12, 31), true},
    393                 {"2012:54:1", LocalDate.of(2013, 1, 7), false},
    394 
    395                 {"2013:0:1", LocalDate.of(2012, 12, 24), false},
    396                 {"2013:0:0", LocalDate.of(2012, 12, 23), false},
    397         };
    398     }
    399 
    400     @Test(dataProvider = "parseLenientWeek", expectedExceptions = DateTimeParseException.class)
    401     public void test_parse_parseLenientWeek_STRICT(String str, LocalDate expected, boolean smart) {
    402         DateTimeFormatter f = new DateTimeFormatterBuilder()
    403                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral(':')
    404                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral(':')
    405                 .appendValue(DAY_OF_WEEK)
    406                 .toFormatter().withResolverStyle(ResolverStyle.STRICT);
    407         LocalDate.parse(str, f);
    408     }
    409 
    410     @Test(dataProvider = "parseLenientWeek")
    411     public void test_parse_parseLenientWeek_SMART(String str, LocalDate expected, boolean smart) {
    412         DateTimeFormatter f = new DateTimeFormatterBuilder()
    413                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral(':')
    414                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral(':')
    415                 .appendValue(DAY_OF_WEEK)
    416                 .toFormatter().withResolverStyle(ResolverStyle.SMART);
    417         if (smart) {
    418             LocalDate parsed = LocalDate.parse(str, f);
    419             assertEquals(parsed, expected);
    420         } else {
    421             try {
    422                 LocalDate.parse(str, f);
    423                 fail("Should have failed");
    424             } catch (DateTimeParseException ex) {
    425                 // expected
    426             }
    427         }
    428     }
    429 
    430     @Test(dataProvider = "parseLenientWeek")
    431     public void test_parse_parseLenientWeek_LENIENT(String str, LocalDate expected, boolean smart) {
    432         DateTimeFormatter f = new DateTimeFormatterBuilder()
    433                 .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral(':')
    434                 .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral(':')
    435                 .appendValue(DAY_OF_WEEK)
    436                 .toFormatter().withResolverStyle(ResolverStyle.LENIENT);
    437         LocalDate parsed = LocalDate.parse(str, f);
    438         assertEquals(parsed, expected);
    439     }
    440 
    441     //-----------------------------------------------------------------------
    442     public void test_loop() {
    443         // loop round at least one 400 year cycle, including before 1970
    444         LocalDate date = LocalDate.of(1960, 1, 5);  // Tuseday of week 1 1960
    445         int year = 1960;
    446         int wby = 1960;
    447         int weekLen = 52;
    448         int week = 1;
    449         while (date.getYear() < 2400) {
    450             DayOfWeek loopDow = date.getDayOfWeek();
    451             if (date.getYear() != year) {
    452                 year = date.getYear();
    453             }
    454             if (loopDow == MONDAY) {
    455                 week++;
    456                 if ((week == 53 && weekLen == 52) || week == 54) {
    457                     week = 1;
    458                     LocalDate firstDayOfWeekBasedYear = date.plusDays(14).withDayOfYear(1);
    459                     DayOfWeek firstDay = firstDayOfWeekBasedYear.getDayOfWeek();
    460                     weekLen = (firstDay == THURSDAY || (firstDay == WEDNESDAY && firstDayOfWeekBasedYear.isLeapYear()) ? 53 : 52);
    461                     wby++;
    462                 }
    463             }
    464             assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.rangeRefinedBy(date), ValueRange.of(1, weekLen), "Failed on " + date + " " + date.getDayOfWeek());
    465             assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.getFrom(date), week, "Failed on " + date + " " + date.getDayOfWeek());
    466             assertEquals(date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR), week, "Failed on " + date + " " + date.getDayOfWeek());
    467             assertEquals(IsoFields.WEEK_BASED_YEAR.getFrom(date), wby, "Failed on " + date + " " + date.getDayOfWeek());
    468             assertEquals(date.get(IsoFields.WEEK_BASED_YEAR), wby, "Failed on " + date + " " + date.getDayOfWeek());
    469             date = date.plusDays(1);
    470         }
    471     }
    472 
    473     // TODO: more tests
    474 }
    475