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.chrono;
  58 
  59 import static org.testng.Assert.assertEquals;
  60 import static org.testng.Assert.fail;
  61 
  62 import java.time.DateTimeException;
  63 import java.time.LocalDate;
  64 import java.time.LocalDateTime;
  65 import java.time.LocalTime;
  66 import java.time.OffsetDateTime;
  67 import java.time.Year;
  68 import java.time.ZonedDateTime;
  69 import java.time.ZoneId;
  70 import java.time.ZoneOffset;
  71 import java.time.chrono.Chronology;
  72 import java.time.chrono.Era;
  73 import java.time.chrono.HijrahEra;
  74 import java.time.chrono.IsoChronology;
  75 import java.time.chrono.IsoEra;
  76 import java.time.format.ResolverStyle;
  77 import java.time.temporal.ChronoField;
  78 import java.time.temporal.TemporalAccessor;
  79 import java.time.temporal.TemporalAdjusters;
  80 import java.time.temporal.TemporalField;
  81 import java.time.temporal.TemporalQueries;
  82 import java.time.temporal.TemporalQuery;
  83 import java.util.HashMap;
  84 import java.util.Map;
  85 
  86 import org.testng.annotations.DataProvider;
  87 import org.testng.annotations.Test;
  88 
  89 /**
  90  * Test.
  91  */
  92 @Test
  93 public class TCKIsoChronology {
  94     // Can only work with IsoChronology here
  95     // others may be in separate module
  96     private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1);
  97     private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1);
  98 
  99     @Test
 100     public void factory_from_TemporalAccessor_dateWithChronlogy() {
 101         assertEquals(Chronology.from(LocalDate.of(2012, 6, 30)), IsoChronology.INSTANCE);
 102     }
 103 
 104     @Test
 105     public void factory_from_TemporalAccessor_chronology() {
 106         assertEquals(Chronology.from(new TemporalAccessor() {
 107             @Override
 108             public boolean isSupported(TemporalField field) {
 109                 throw new UnsupportedOperationException();
 110             }
 111 
 112             @Override
 113             public long getLong(TemporalField field) {
 114                 throw new UnsupportedOperationException();
 115             }
 116 
 117             @SuppressWarnings("unchecked")
 118             @Override
 119             public <R> R query(TemporalQuery<R> query) {
 120                 if (query == TemporalQueries.chronology()) {
 121                     return (R) IsoChronology.INSTANCE;
 122                 }
 123                 throw new UnsupportedOperationException();
 124             }
 125         }), IsoChronology.INSTANCE);
 126     }
 127 
 128     @Test
 129     public void factory_from_TemporalAccessor_noChronology() {
 130         assertEquals(Chronology.from(new TemporalAccessor() {
 131             @Override
 132             public boolean isSupported(TemporalField field) {
 133                 throw new UnsupportedOperationException();
 134             }
 135 
 136             @Override
 137             public long getLong(TemporalField field) {
 138                 throw new UnsupportedOperationException();
 139             }
 140 
 141             @Override
 142             public <R> R query(TemporalQuery<R> query) {
 143                 if (query == TemporalQueries.chronology()) {
 144                     return null;
 145                 }
 146                 throw new UnsupportedOperationException();
 147             }
 148         }), IsoChronology.INSTANCE);
 149     }
 150 
 151     @Test(expectedExceptions=NullPointerException.class)
 152     public void factory_from_TemporalAccessor_null() {
 153         Chronology.from(null);
 154     }
 155 
 156     //-----------------------------------------------------------------------
 157     @Test
 158     public void test_date_TemporalAccessor() {
 159         assertEquals(IsoChronology.INSTANCE.date(new TemporalAccessor() {
 160             @Override
 161             public boolean isSupported(TemporalField field) {
 162                 if (field == ChronoField.EPOCH_DAY) {
 163                     return true;
 164                 }
 165                 throw new UnsupportedOperationException();
 166             }
 167 
 168             @Override
 169             public long getLong(TemporalField field) {
 170                 if (field == ChronoField.EPOCH_DAY) {
 171                     return LocalDate.of(2012, 6, 30).toEpochDay();
 172                 }
 173                 throw new UnsupportedOperationException();
 174             }
 175 
 176             @SuppressWarnings("unchecked")
 177             @Override
 178             public <R> R query(TemporalQuery<R> query) {
 179                 if (query == TemporalQueries.localDate()) {
 180                     return (R) LocalDate.of(2012, 6, 30);
 181                 }
 182                 throw new UnsupportedOperationException();
 183             }
 184         }), LocalDate.of(2012, 6, 30));
 185     }
 186 
 187     @Test(expectedExceptions=NullPointerException.class)
 188     public void test_date_TemporalAccessor_null() {
 189         IsoChronology.INSTANCE.date(null);
 190     }
 191 
 192     //-----------------------------------------------------------------------
 193     @Test
 194     public void test_localDateTime_TemporalAccessor() {
 195         assertEquals(IsoChronology.INSTANCE.localDateTime(new TemporalAccessor() {
 196             @Override
 197             public boolean isSupported(TemporalField field) {
 198                 if (field == ChronoField.EPOCH_DAY || field == ChronoField.NANO_OF_DAY) {
 199                     return true;
 200                 }
 201                 throw new UnsupportedOperationException();
 202             }
 203 
 204             @Override
 205             public long getLong(TemporalField field) {
 206                 if (field == ChronoField.EPOCH_DAY) {
 207                     return LocalDate.of(2012, 6, 30).toEpochDay();
 208                 }
 209                 if (field == ChronoField.NANO_OF_DAY) {
 210                     return LocalTime.of(12, 30, 40).toNanoOfDay();
 211                 }
 212                 throw new UnsupportedOperationException();
 213             }
 214 
 215             @SuppressWarnings("unchecked")
 216             @Override
 217             public <R> R query(TemporalQuery<R> query) {
 218                 if (query == TemporalQueries.localDate()) {
 219                     return (R) LocalDate.of(2012, 6, 30);
 220                 }
 221                 if (query == TemporalQueries.localTime()) {
 222                     return (R) LocalTime.of(12, 30, 40);
 223                 }
 224                 throw new UnsupportedOperationException();
 225             }
 226         }), LocalDateTime.of(2012, 6, 30, 12, 30, 40));
 227     }
 228 
 229     @Test(expectedExceptions=NullPointerException.class)
 230     public void test_localDateTime_TemporalAccessor_null() {
 231         IsoChronology.INSTANCE.localDateTime(null);
 232     }
 233 
 234     //-----------------------------------------------------------------------
 235     @Test
 236     public void test_zonedDateTime_TemporalAccessor() {
 237         assertEquals(IsoChronology.INSTANCE.zonedDateTime(new TemporalAccessor() {
 238             @Override
 239             public boolean isSupported(TemporalField field) {
 240                 if (field == ChronoField.EPOCH_DAY || field == ChronoField.NANO_OF_DAY ||
 241                         field == ChronoField.INSTANT_SECONDS || field == ChronoField.NANO_OF_SECOND) {
 242                     return true;
 243                 }
 244                 throw new UnsupportedOperationException();
 245             }
 246 
 247             @Override
 248             public long getLong(TemporalField field) {
 249                 if (field == ChronoField.INSTANT_SECONDS) {
 250                     return ZonedDateTime.of(2012, 6, 30, 12, 30, 40, 0, ZoneId.of("Europe/London")).toEpochSecond();
 251                 }
 252                 if (field == ChronoField.NANO_OF_SECOND) {
 253                     return 0;
 254                 }
 255                 if (field == ChronoField.EPOCH_DAY) {
 256                     return LocalDate.of(2012, 6, 30).toEpochDay();
 257                 }
 258                 if (field == ChronoField.NANO_OF_DAY) {
 259                     return LocalTime.of(12, 30, 40).toNanoOfDay();
 260                 }
 261                 throw new UnsupportedOperationException();
 262             }
 263 
 264             @SuppressWarnings("unchecked")
 265             @Override
 266             public <R> R query(TemporalQuery<R> query) {
 267                 if (query == TemporalQueries.localDate()) {
 268                     return (R) LocalDate.of(2012, 6, 30);
 269                 }
 270                 if (query == TemporalQueries.localTime()) {
 271                     return (R) LocalTime.of(12, 30, 40);
 272                 }
 273                 if (query == TemporalQueries.zoneId() || query == TemporalQueries.zone()) {
 274                     return (R) ZoneId.of("Europe/London");
 275                 }
 276                 throw new UnsupportedOperationException();
 277             }
 278         }), ZonedDateTime.of(2012, 6, 30, 12, 30, 40, 0, ZoneId.of("Europe/London")));
 279     }
 280 
 281     @Test(expectedExceptions=NullPointerException.class)
 282     public void test_zonedDateTime_TemporalAccessor_null() {
 283         IsoChronology.INSTANCE.zonedDateTime(null);
 284     }
 285 
 286     //-----------------------------------------------------------------------
 287     //-----------------------------------------------------------------------
 288     @DataProvider(name = "resolve_yearOfEra")
 289     Object[][] data_resolve_yearOfEra() {
 290         return new Object[][] {
 291                 // era only
 292                 {ResolverStyle.STRICT, -1, null, null, null, null},
 293                 {ResolverStyle.SMART, -1, null, null, null, null},
 294                 {ResolverStyle.LENIENT, -1, null, null, null, null},
 295 
 296                 {ResolverStyle.STRICT, 0, null, null, ChronoField.ERA, 0},
 297                 {ResolverStyle.SMART, 0, null, null, ChronoField.ERA, 0},
 298                 {ResolverStyle.LENIENT, 0, null, null, ChronoField.ERA, 0},
 299 
 300                 {ResolverStyle.STRICT, 1, null, null, ChronoField.ERA, 1},
 301                 {ResolverStyle.SMART, 1, null, null, ChronoField.ERA, 1},
 302                 {ResolverStyle.LENIENT, 1, null, null, ChronoField.ERA, 1},
 303 
 304                 {ResolverStyle.STRICT, 2, null, null, null, null},
 305                 {ResolverStyle.SMART, 2, null, null, null, null},
 306                 {ResolverStyle.LENIENT, 2, null, null, null, null},
 307 
 308                 // era and year-of-era
 309                 {ResolverStyle.STRICT, -1, 2012, null, null, null},
 310                 {ResolverStyle.SMART, -1, 2012, null, null, null},
 311                 {ResolverStyle.LENIENT, -1, 2012, null, null, null},
 312 
 313                 {ResolverStyle.STRICT, 0, 2012, null, ChronoField.YEAR, -2011},
 314                 {ResolverStyle.SMART, 0, 2012, null, ChronoField.YEAR, -2011},
 315                 {ResolverStyle.LENIENT, 0, 2012, null, ChronoField.YEAR, -2011},
 316 
 317                 {ResolverStyle.STRICT, 1, 2012, null, ChronoField.YEAR, 2012},
 318                 {ResolverStyle.SMART, 1, 2012, null, ChronoField.YEAR, 2012},
 319                 {ResolverStyle.LENIENT, 1, 2012, null, ChronoField.YEAR, 2012},
 320 
 321                 {ResolverStyle.STRICT, 2, 2012, null, null, null},
 322                 {ResolverStyle.SMART, 2, 2012, null, null, null},
 323                 {ResolverStyle.LENIENT, 2, 2012, null, null, null},
 324 
 325                 // year-of-era only
 326                 {ResolverStyle.STRICT, null, 2012, null, ChronoField.YEAR_OF_ERA, 2012},
 327                 {ResolverStyle.SMART, null, 2012, null, ChronoField.YEAR, 2012},
 328                 {ResolverStyle.LENIENT, null, 2012, null, ChronoField.YEAR, 2012},
 329 
 330                 {ResolverStyle.STRICT, null, Integer.MAX_VALUE, null, null, null},
 331                 {ResolverStyle.SMART, null, Integer.MAX_VALUE, null, null, null},
 332                 {ResolverStyle.LENIENT, null, Integer.MAX_VALUE, null, ChronoField.YEAR, Integer.MAX_VALUE},
 333 
 334                 // year-of-era and year
 335                 {ResolverStyle.STRICT, null, 2012, 2012, ChronoField.YEAR, 2012},
 336                 {ResolverStyle.SMART, null, 2012, 2012, ChronoField.YEAR, 2012},
 337                 {ResolverStyle.LENIENT, null, 2012, 2012, ChronoField.YEAR, 2012},
 338 
 339                 {ResolverStyle.STRICT, null, 2012, -2011, ChronoField.YEAR, -2011},
 340                 {ResolverStyle.SMART, null, 2012, -2011, ChronoField.YEAR, -2011},
 341                 {ResolverStyle.LENIENT, null, 2012, -2011, ChronoField.YEAR, -2011},
 342 
 343                 {ResolverStyle.STRICT, null, 2012, 2013, null, null},
 344                 {ResolverStyle.SMART, null, 2012, 2013, null, null},
 345                 {ResolverStyle.LENIENT, null, 2012, 2013, null, null},
 346 
 347                 {ResolverStyle.STRICT, null, 2012, -2013, null, null},
 348                 {ResolverStyle.SMART, null, 2012, -2013, null, null},
 349                 {ResolverStyle.LENIENT, null, 2012, -2013, null, null},
 350         };
 351     }
 352 
 353     @Test(dataProvider = "resolve_yearOfEra")
 354     public void test_resolve_yearOfEra(ResolverStyle style, Integer e, Integer yoe, Integer y, ChronoField field, Integer expected) {
 355         Map<TemporalField, Long> fieldValues = new HashMap<>();
 356         if (e != null) {
 357             fieldValues.put(ChronoField.ERA, (long) e);
 358         }
 359         if (yoe != null) {
 360             fieldValues.put(ChronoField.YEAR_OF_ERA, (long) yoe);
 361         }
 362         if (y != null) {
 363             fieldValues.put(ChronoField.YEAR, (long) y);
 364         }
 365         if (field != null) {
 366             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, style);
 367             assertEquals(date, null);
 368             assertEquals(fieldValues.get(field), (Long) expected.longValue());
 369             assertEquals(fieldValues.size(), 1);
 370         } else {
 371             try {
 372                 IsoChronology.INSTANCE.resolveDate(fieldValues, style);
 373                 fail("Should have failed");
 374             } catch (DateTimeException ex) {
 375                 // expected
 376             }
 377         }
 378     }
 379 
 380     //-----------------------------------------------------------------------
 381     //-----------------------------------------------------------------------
 382     @DataProvider(name = "resolve_ymd")
 383     Object[][] data_resolve_ymd() {
 384         return new Object[][] {
 385                 {2012, 1, -365, date(2010, 12, 31), false, false},
 386                 {2012, 1, -364, date(2011, 1, 1), false, false},
 387                 {2012, 1, -31, date(2011, 11, 30), false, false},
 388                 {2012, 1, -30, date(2011, 12, 1), false, false},
 389                 {2012, 1, -12, date(2011, 12, 19), false, false},
 390                 {2012, 1, 1, date(2012, 1, 1), true, true},
 391                 {2012, 1, 27, date(2012, 1, 27), true, true},
 392                 {2012, 1, 28, date(2012, 1, 28), true, true},
 393                 {2012, 1, 29, date(2012, 1, 29), true, true},
 394                 {2012, 1, 30, date(2012, 1, 30), true, true},
 395                 {2012, 1, 31, date(2012, 1, 31), true, true},
 396                 {2012, 1, 59, date(2012, 2, 28), false, false},
 397                 {2012, 1, 60, date(2012, 2, 29), false, false},
 398                 {2012, 1, 61, date(2012, 3, 1), false, false},
 399                 {2012, 1, 365, date(2012, 12, 30), false, false},
 400                 {2012, 1, 366, date(2012, 12, 31), false, false},
 401                 {2012, 1, 367, date(2013, 1, 1), false, false},
 402                 {2012, 1, 367 + 364, date(2013, 12, 31), false, false},
 403                 {2012, 1, 367 + 365, date(2014, 1, 1), false, false},
 404 
 405                 {2012, 2, 1, date(2012, 2, 1), true, true},
 406                 {2012, 2, 28, date(2012, 2, 28), true, true},
 407                 {2012, 2, 29, date(2012, 2, 29), true, true},
 408                 {2012, 2, 30, date(2012, 3, 1), date(2012, 2, 29), false},
 409                 {2012, 2, 31, date(2012, 3, 2), date(2012, 2, 29), false},
 410                 {2012, 2, 32, date(2012, 3, 3), false, false},
 411 
 412                 {2012, -12, 1, date(2010, 12, 1), false, false},
 413                 {2012, -11, 1, date(2011, 1, 1), false, false},
 414                 {2012, -1, 1, date(2011, 11, 1), false, false},
 415                 {2012, 0, 1, date(2011, 12, 1), false, false},
 416                 {2012, 1, 1, date(2012, 1, 1), true, true},
 417                 {2012, 12, 1, date(2012, 12, 1), true, true},
 418                 {2012, 13, 1, date(2013, 1, 1), false, false},
 419                 {2012, 24, 1, date(2013, 12, 1), false, false},
 420                 {2012, 25, 1, date(2014, 1, 1), false, false},
 421 
 422                 {2012, 6, -31, date(2012, 4, 30), false, false},
 423                 {2012, 6, -30, date(2012, 5, 1), false, false},
 424                 {2012, 6, -1, date(2012, 5, 30), false, false},
 425                 {2012, 6, 0, date(2012, 5, 31), false, false},
 426                 {2012, 6, 1, date(2012, 6, 1), true, true},
 427                 {2012, 6, 30, date(2012, 6, 30), true, true},
 428                 {2012, 6, 31, date(2012, 7, 1), date(2012, 6, 30), false},
 429                 {2012, 6, 61, date(2012, 7, 31), false, false},
 430                 {2012, 6, 62, date(2012, 8, 1), false, false},
 431 
 432                 {2011, 2, 1, date(2011, 2, 1), true, true},
 433                 {2011, 2, 28, date(2011, 2, 28), true, true},
 434                 {2011, 2, 29, date(2011, 3, 1), date(2011, 2, 28), false},
 435                 {2011, 2, 30, date(2011, 3, 2), date(2011, 2, 28), false},
 436                 {2011, 2, 31, date(2011, 3, 3), date(2011, 2, 28), false},
 437                 {2011, 2, 32, date(2011, 3, 4), false, false},
 438         };
 439     }
 440 
 441     @Test(dataProvider = "resolve_ymd")
 442     public void test_resolve_ymd_lenient(int y, int m, int d, LocalDate expected, Object smart, boolean strict) {
 443         Map<TemporalField, Long> fieldValues = new HashMap<>();
 444         fieldValues.put(ChronoField.YEAR, (long) y);
 445         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 446         fieldValues.put(ChronoField.DAY_OF_MONTH, (long) d);
 447         LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT);
 448         assertEquals(date, expected);
 449         assertEquals(fieldValues.size(), 0);
 450     }
 451 
 452     @Test(dataProvider = "resolve_ymd")
 453     public void test_resolve_ymd_smart(int y, int m, int d, LocalDate expected, Object smart, boolean strict) {
 454         Map<TemporalField, Long> fieldValues = new HashMap<>();
 455         fieldValues.put(ChronoField.YEAR, (long) y);
 456         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 457         fieldValues.put(ChronoField.DAY_OF_MONTH, (long) d);
 458         if (Boolean.TRUE.equals(smart)) {
 459             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 460             assertEquals(date, expected);
 461             assertEquals(fieldValues.size(), 0);
 462         } else if (smart instanceof LocalDate) {
 463             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 464             assertEquals(date, smart);
 465         } else {
 466             try {
 467                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 468                 fail("Should have failed");
 469             } catch (DateTimeException ex) {
 470                 // expected
 471             }
 472         }
 473     }
 474 
 475     @Test(dataProvider = "resolve_ymd")
 476     public void test_resolve_ymd_strict(int y, int m, int d, LocalDate expected, Object smart, boolean strict) {
 477         Map<TemporalField, Long> fieldValues = new HashMap<>();
 478         fieldValues.put(ChronoField.YEAR, (long) y);
 479         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 480         fieldValues.put(ChronoField.DAY_OF_MONTH, (long) d);
 481         if (strict) {
 482             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 483             assertEquals(date, expected);
 484             assertEquals(fieldValues.size(), 0);
 485         } else {
 486             try {
 487                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 488                 fail("Should have failed");
 489             } catch (DateTimeException ex) {
 490                 // expected
 491             }
 492         }
 493     }
 494 
 495     //-----------------------------------------------------------------------
 496     //-----------------------------------------------------------------------
 497     @DataProvider(name = "resolve_yd")
 498     Object[][] data_resolve_yd() {
 499         return new Object[][] {
 500                 {2012, -365, date(2010, 12, 31), false, false},
 501                 {2012, -364, date(2011, 1, 1), false, false},
 502                 {2012, -31, date(2011, 11, 30), false, false},
 503                 {2012, -30, date(2011, 12, 1), false, false},
 504                 {2012, -12, date(2011, 12, 19), false, false},
 505                 {2012, -1, date(2011, 12, 30), false, false},
 506                 {2012, 0, date(2011, 12, 31), false, false},
 507                 {2012, 1, date(2012, 1, 1), true, true},
 508                 {2012, 2, date(2012, 1, 2), true, true},
 509                 {2012, 31, date(2012, 1, 31), true, true},
 510                 {2012, 32, date(2012, 2, 1), true, true},
 511                 {2012, 59, date(2012, 2, 28), true, true},
 512                 {2012, 60, date(2012, 2, 29), true, true},
 513                 {2012, 61, date(2012, 3, 1), true, true},
 514                 {2012, 365, date(2012, 12, 30), true, true},
 515                 {2012, 366, date(2012, 12, 31), true, true},
 516                 {2012, 367, date(2013, 1, 1), false, false},
 517                 {2012, 367 + 364, date(2013, 12, 31), false, false},
 518                 {2012, 367 + 365, date(2014, 1, 1), false, false},
 519 
 520                 {2011, 59, date(2011, 2, 28), true, true},
 521                 {2011, 60, date(2011, 3, 1), true, true},
 522         };
 523     }
 524 
 525     @Test(dataProvider = "resolve_yd")
 526     public void test_resolve_yd_lenient(int y, int d, LocalDate expected, boolean smart, boolean strict) {
 527         Map<TemporalField, Long> fieldValues = new HashMap<>();
 528         fieldValues.put(ChronoField.YEAR, (long) y);
 529         fieldValues.put(ChronoField.DAY_OF_YEAR, (long) d);
 530         LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT);
 531         assertEquals(date, expected);
 532         assertEquals(fieldValues.size(), 0);
 533     }
 534 
 535     @Test(dataProvider = "resolve_yd")
 536     public void test_resolve_yd_smart(int y, int d, LocalDate expected, boolean smart, boolean strict) {
 537         Map<TemporalField, Long> fieldValues = new HashMap<>();
 538         fieldValues.put(ChronoField.YEAR, (long) y);
 539         fieldValues.put(ChronoField.DAY_OF_YEAR, (long) d);
 540         if (smart) {
 541             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 542             assertEquals(date, expected);
 543             assertEquals(fieldValues.size(), 0);
 544         } else {
 545             try {
 546                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 547                 fail("Should have failed");
 548             } catch (DateTimeException ex) {
 549                 // expected
 550             }
 551         }
 552     }
 553 
 554     @Test(dataProvider = "resolve_yd")
 555     public void test_resolve_yd_strict(int y, int d, LocalDate expected, boolean smart, boolean strict) {
 556         Map<TemporalField, Long> fieldValues = new HashMap<>();
 557         fieldValues.put(ChronoField.YEAR, (long) y);
 558         fieldValues.put(ChronoField.DAY_OF_YEAR, (long) d);
 559         if (strict) {
 560             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 561             assertEquals(date, expected);
 562             assertEquals(fieldValues.size(), 0);
 563         } else {
 564             try {
 565                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 566                 fail("Should have failed");
 567             } catch (DateTimeException ex) {
 568                 // expected
 569             }
 570         }
 571     }
 572 
 573     //-----------------------------------------------------------------------
 574     //-----------------------------------------------------------------------
 575     @DataProvider(name = "resolve_ymaa")
 576     Object[][] data_resolve_ymaa() {
 577         return new Object[][] {
 578                 {2012, 1, 1, -365, date(2010, 12, 31), false, false},
 579                 {2012, 1, 1, -364, date(2011, 1, 1), false, false},
 580                 {2012, 1, 1, -31, date(2011, 11, 30), false, false},
 581                 {2012, 1, 1, -30, date(2011, 12, 1), false, false},
 582                 {2012, 1, 1, -12, date(2011, 12, 19), false, false},
 583                 {2012, 1, 1, 1, date(2012, 1, 1), true, true},
 584                 {2012, 1, 1, 59, date(2012, 2, 28), false, false},
 585                 {2012, 1, 1, 60, date(2012, 2, 29), false, false},
 586                 {2012, 1, 1, 61, date(2012, 3, 1), false, false},
 587                 {2012, 1, 1, 365, date(2012, 12, 30), false, false},
 588                 {2012, 1, 1, 366, date(2012, 12, 31), false, false},
 589                 {2012, 1, 1, 367, date(2013, 1, 1), false, false},
 590                 {2012, 1, 1, 367 + 364, date(2013, 12, 31), false, false},
 591                 {2012, 1, 1, 367 + 365, date(2014, 1, 1), false, false},
 592 
 593                 {2012, 2, 0, 1, date(2012, 1, 25), false, false},
 594                 {2012, 2, 0, 7, date(2012, 1, 31), false, false},
 595                 {2012, 2, 1, 1, date(2012, 2, 1), true, true},
 596                 {2012, 2, 1, 7, date(2012, 2, 7), true, true},
 597                 {2012, 2, 2, 1, date(2012, 2, 8), true, true},
 598                 {2012, 2, 2, 7, date(2012, 2, 14), true, true},
 599                 {2012, 2, 3, 1, date(2012, 2, 15), true, true},
 600                 {2012, 2, 3, 7, date(2012, 2, 21), true, true},
 601                 {2012, 2, 4, 1, date(2012, 2, 22), true, true},
 602                 {2012, 2, 4, 7, date(2012, 2, 28), true, true},
 603                 {2012, 2, 5, 1, date(2012, 2, 29), true, true},
 604                 {2012, 2, 5, 2, date(2012, 3, 1), true, false},
 605                 {2012, 2, 5, 7, date(2012, 3, 6), true, false},
 606                 {2012, 2, 6, 1, date(2012, 3, 7), false, false},
 607                 {2012, 2, 6, 7, date(2012, 3, 13), false, false},
 608 
 609                 {2012, 12, 1, 1, date(2012, 12, 1), true, true},
 610                 {2012, 12, 5, 1, date(2012, 12, 29), true, true},
 611                 {2012, 12, 5, 2, date(2012, 12, 30), true, true},
 612                 {2012, 12, 5, 3, date(2012, 12, 31), true, true},
 613                 {2012, 12, 5, 4, date(2013, 1, 1), true, false},
 614                 {2012, 12, 5, 7, date(2013, 1, 4), true, false},
 615 
 616                 {2012, -12, 1, 1, date(2010, 12, 1), false, false},
 617                 {2012, -11, 1, 1, date(2011, 1, 1), false, false},
 618                 {2012, -1, 1, 1, date(2011, 11, 1), false, false},
 619                 {2012, 0, 1, 1, date(2011, 12, 1), false, false},
 620                 {2012, 1, 1, 1, date(2012, 1, 1), true, true},
 621                 {2012, 12, 1, 1, date(2012, 12, 1), true, true},
 622                 {2012, 13, 1, 1, date(2013, 1, 1), false, false},
 623                 {2012, 24, 1, 1, date(2013, 12, 1), false, false},
 624                 {2012, 25, 1, 1, date(2014, 1, 1), false, false},
 625 
 626                 {2011, 2, 1, 1, date(2011, 2, 1), true, true},
 627                 {2011, 2, 4, 7, date(2011, 2, 28), true, true},
 628                 {2011, 2, 5, 1, date(2011, 3, 1), true, false},
 629         };
 630     }
 631 
 632     @Test(dataProvider = "resolve_ymaa")
 633     public void test_resolve_ymaa_lenient(int y, int m, int w, int d, LocalDate expected, boolean smart, boolean strict) {
 634         Map<TemporalField, Long> fieldValues = new HashMap<>();
 635         fieldValues.put(ChronoField.YEAR, (long) y);
 636         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 637         fieldValues.put(ChronoField.ALIGNED_WEEK_OF_MONTH, (long) w);
 638         fieldValues.put(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH, (long) d);
 639         LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.LENIENT);
 640         assertEquals(date, expected);
 641         assertEquals(fieldValues.size(), 0);
 642     }
 643 
 644     @Test(dataProvider = "resolve_ymaa")
 645     public void test_resolve_ymaa_smart(int y, int m, int w, int d, LocalDate expected, boolean smart, boolean strict) {
 646         Map<TemporalField, Long> fieldValues = new HashMap<>();
 647         fieldValues.put(ChronoField.YEAR, (long) y);
 648         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 649         fieldValues.put(ChronoField.ALIGNED_WEEK_OF_MONTH, (long) w);
 650         fieldValues.put(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH, (long) d);
 651         if (smart) {
 652             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 653             assertEquals(date, expected);
 654             assertEquals(fieldValues.size(), 0);
 655         } else {
 656             try {
 657                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.SMART);
 658                 fail("Should have failed");
 659             } catch (DateTimeException ex) {
 660                 // expected
 661             }
 662         }
 663     }
 664 
 665     @Test(dataProvider = "resolve_ymaa")
 666     public void test_resolve_ymaa_strict(int y, int m, int w, int d, LocalDate expected, boolean smart, boolean strict) {
 667         Map<TemporalField, Long> fieldValues = new HashMap<>();
 668         fieldValues.put(ChronoField.YEAR, (long) y);
 669         fieldValues.put(ChronoField.MONTH_OF_YEAR, (long) m);
 670         fieldValues.put(ChronoField.ALIGNED_WEEK_OF_MONTH, (long) w);
 671         fieldValues.put(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH, (long) d);
 672         if (strict) {
 673             LocalDate date = IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 674             assertEquals(date, expected);
 675             assertEquals(fieldValues.size(), 0);
 676         } else {
 677             try {
 678                 IsoChronology.INSTANCE.resolveDate(fieldValues, ResolverStyle.STRICT);
 679                 fail("Should have failed");
 680             } catch (DateTimeException ex) {
 681                 // expected
 682             }
 683         }
 684     }
 685 
 686     @DataProvider(name = "epochSecond_dataProvider")
 687     Object[][] data_epochSecond() {
 688         return new Object[][] {
 689                 {2008, 3, 3, 1, 2, 2, OFFSET_P0100},
 690                 {2008, 3, 3, 1, 2, 2, OFFSET_M0100},
 691                 {2008, 2, 28, 1, 2, 2, OFFSET_P0100},
 692                 {2009, 3, 3, 1, 2, 2, OFFSET_P0100},
 693                 {2009, 3, 3, 1, 2, 2, OFFSET_M0100},
 694                 {2009, 2, 28, 1, 2, 2, OFFSET_P0100},
 695                 {1968, 3, 3, 1, 2, 2, OFFSET_P0100},
 696                 {1968, 3, 3, 1, 2, 2, OFFSET_M0100},
 697                 {1968, 2, 28, 1, 2, 2, OFFSET_P0100},
 698                 {1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
 699                 {1969, 3, 3, 1, 2, 2, OFFSET_M0100},
 700                 {1969, 2, 28, 1, 2, 2, OFFSET_P0100},
 701                 {1970, 1, 1, 1, 2, 2, OFFSET_P0100},
 702                 {1970, 1, 1, 1, 2, 2, OFFSET_M0100},
 703                 {-4, 3, 3 , 1, 2, 2, OFFSET_P0100},
 704                 {-1, 3, 3 , 1, 2, 2, OFFSET_P0100},
 705         };
 706     }
 707 
 708     @Test(dataProvider = "epochSecond_dataProvider")
 709     public void test_epochSecond_1(int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
 710         assertEquals(IsoChronology.INSTANCE.epochSecond(y, m, d, h, min, s, offset),
 711                      OffsetDateTime.of(y, m, d, h, min, s, 0, offset).toEpochSecond());
 712     }
 713 
 714     @Test
 715     public void test_epochSecond_2() {
 716         assertEquals(IsoChronology.INSTANCE.epochSecond(2008, 3, 3, 1, 2, 2, OFFSET_P0100),
 717                      ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
 718         assertEquals(IsoChronology.INSTANCE.epochSecond(1969, 3, 3, 1, 2, 2, OFFSET_P0100),
 719                      ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
 720     }
 721 
 722     @Test
 723     public void test_epochSecond_max() {
 724         assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MAX_VALUE, 12, 31, 23, 59, 59, ZoneOffset.MIN),
 725                      OffsetDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 59, 0, ZoneOffset.MIN).toEpochSecond());
 726     }
 727 
 728     @Test
 729     public void test_epochSecond_min() {
 730         assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MIN_VALUE, 1, 1, 0, 0, 0, ZoneOffset.MAX),
 731                      OffsetDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0, 0, 0, ZoneOffset.MAX).toEpochSecond());
 732     }
 733 
 734     @Test(expectedExceptions=DateTimeException.class)
 735     public void test_epochSecond_bad() {
 736         IsoChronology.INSTANCE.epochSecond(2009, 2, 29, 1, 2, 2, OFFSET_P0100);
 737     }
 738 
 739     @DataProvider(name = "era_epochSecond_dataProvider")
 740     Object[][] data_era_epochSecond() {
 741         return new Object[][] {
 742                 {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100},
 743                 {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_M0100},
 744                 {IsoEra.CE, 2008, 2, 28, 1, 2, 2, OFFSET_P0100},
 745                 {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_P0100},
 746                 {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_M0100},
 747                 {IsoEra.CE, 2009, 2, 28, 1, 2, 2, OFFSET_P0100},
 748                 {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_P0100},
 749                 {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_M0100},
 750                 {IsoEra.CE, 1968, 2, 28, 1, 2, 2, OFFSET_P0100},
 751                 {IsoEra.CE, 1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
 752                 {IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_M0100},
 753                 {IsoEra.CE, 1969, 2, 28, 1, 2, 2, OFFSET_P0100},
 754                 {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_P0100},
 755                 {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_M0100},
 756                 {IsoEra.BCE, 5, 3, 3 , 1, 2, 2, OFFSET_P0100},
 757                 {IsoEra.BCE, 2, 3, 3 , 1, 2, 2, OFFSET_P0100},
 758         };
 759     }
 760 
 761     @Test(dataProvider = "era_epochSecond_dataProvider")
 762     public void test_era_epochSecond_1(Era era, int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
 763         assertEquals(IsoChronology.INSTANCE.epochSecond(era, y, m, d, h, min, s, offset),
 764                      OffsetDateTime.of(IsoChronology.INSTANCE.date(era, y, m, d), LocalTime.of(h, min, s), offset)
 765                                    .toEpochSecond());
 766     }
 767 
 768     @Test
 769     public void test_era_epochSecond_2() {
 770         assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100),
 771                      ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
 772         assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_P0100),
 773                      ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
 774     }
 775 
 776     @Test(expectedExceptions=ClassCastException.class)
 777     public void test_era_epochSecond_bad() {
 778         IsoChronology.INSTANCE.epochSecond(HijrahEra.AH, 2009, 2, 29, 1, 2, 2, OFFSET_P0100);
 779     }
 780 
 781 
 782     //-----------------------------------------------------------------------
 783     private static LocalDate date(int y, int m, int d) {
 784         return LocalDate.of(y, m, d);
 785     }
 786 }