1 /*
   2  * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 4745761
  27  * @summary Unit test for Calendar.Builder.
  28  */
  29 
  30 import java.time.LocalDateTime;
  31 import java.util.*;
  32 import static java.util.Calendar.*;
  33 
  34 public class BuilderTest {
  35     private static final Locale jaJPJP = new Locale("ja", "JP", "JP");
  36     private static final Locale thTH = new Locale("th", "TH");
  37     private static final TimeZone LA = TimeZone.getTimeZone("America/Los_Angeles");
  38     private static final TimeZone TOKYO = TimeZone.getTimeZone("Asia/Tokyo");
  39     private static int error;
  40 
  41     public static void main(String[] args) {
  42         TimeZone tz = TimeZone.getDefault();
  43         Locale loc = Locale.getDefault();
  44         try {
  45             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
  46             Locale.setDefault(Locale.US);
  47             Calendar.Builder calb;
  48             Calendar cal, expected;
  49 
  50             // set instant
  51             calb = builder();
  52             long time = System.currentTimeMillis();
  53             cal = calb.setInstant(time).build();
  54             expected = new GregorianCalendar();
  55             expected.setTimeInMillis(time);
  56             check(cal, expected);
  57 
  58             calb = builder();
  59             cal = calb.setInstant(new Date(time)).build();
  60             check(cal, expected);
  61 
  62             // set time zone
  63             calb = builder();
  64             cal = calb.setTimeZone(LA).setInstant(time).build();
  65             expected = new GregorianCalendar(LA, Locale.US);
  66             expected.setTimeInMillis(time);
  67             check(cal, expected);
  68 
  69             calb = builder();
  70             cal = calb.setTimeZone(TOKYO).setInstant(time).build();
  71             expected = new GregorianCalendar(TOKYO, Locale.US);
  72             expected.setTimeInMillis(time);
  73             check(cal, expected);
  74 
  75             // set vs. setFields
  76             calb = builder();
  77             cal = calb.set(YEAR, 2013).set(MONTH, JANUARY).set(DAY_OF_MONTH, 31)
  78                       .set(HOUR_OF_DAY, 10).set(MINUTE, 20).set(SECOND, 30).set(MILLISECOND, 40).build();
  79             expected = new GregorianCalendar(2013, JANUARY, 31, 10, 20, 30);
  80             expected.set(MILLISECOND, 40);
  81             check(cal, expected);
  82 
  83             calb = builder();
  84             cal = calb.setFields(YEAR, 2013, MONTH, JANUARY, DAY_OF_MONTH, 31,
  85                                  HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40).build();
  86             check(cal, expected);
  87 
  88             // field resolution
  89             calb = builder();
  90             cal = calb.setFields(YEAR, 2013, MONTH, DECEMBER, DAY_OF_MONTH, 31,
  91                                  HOUR_OF_DAY, 10, MINUTE, 20, SECOND, 30, MILLISECOND, 40)
  92                       .set(DAY_OF_YEAR, 31).build();  // DAY_OF_YEAR wins.
  93             check(cal, expected);
  94 
  95             // setDate/setTimeOfDay
  96             calb = builder();
  97             cal = calb.setDate(2013, JANUARY, 31).setTimeOfDay(10, 20, 30, 40).build();
  98             check(cal, expected);
  99 
 100             // week date (ISO 8601)
 101             calb = builder().setCalendarType("iso8601");
 102             cal = calb.setWeekDate(2013, 1, MONDAY).setTimeOfDay(10, 20, 30).build();
 103             expected = getISO8601();
 104             expected.set(2012, DECEMBER, 31, 10, 20, 30);
 105             check(cal, expected);
 106 
 107             // default YEAR == 1970
 108             cal = builder().setFields(MONTH, JANUARY,
 109                                                    DAY_OF_MONTH, 9).build();
 110             check(cal, new GregorianCalendar(1970, JANUARY, 9));
 111 
 112             // no parameters are given.
 113             calb = builder();
 114             cal = calb.build();
 115             expected = new GregorianCalendar();
 116             expected.clear();
 117             check(cal, expected);
 118 
 119             // Thai Buddhist calendar
 120             calb = builder();
 121             cal = calb.setCalendarType("buddhist").setDate(2556, JANUARY, 31).build();
 122             expected = Calendar.getInstance(thTH);
 123             expected.clear();
 124             expected.set(2556, JANUARY, 31);
 125             check(cal, expected);
 126             // setLocale
 127             calb = builder();
 128             cal = calb.setLocale(thTH).setDate(2556, JANUARY, 31).build();
 129             check(cal, expected);
 130 
 131             // Japanese Imperial calendar
 132             cal = builder().setCalendarType("japanese")
 133                 .setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
 134             expected = Calendar.getInstance(jaJPJP);
 135             expected.clear();
 136             if (LocalDateTime.now().isBefore(LocalDateTime.of(2019, 5, 1, 0, 0))) {
 137             expected.set(1, JANUARY, 8);
 138             } else {
 139                 expected.set(1, MAY, 1);
 140             }
 141             check(cal, expected);
 142             // setLocale
 143             calb = builder();
 144             cal = calb.setLocale(jaJPJP).setFields(YEAR, 1, DAY_OF_YEAR, 1).build();
 145             check(cal, expected);
 146 
 147             testExceptions();
 148         } finally {
 149             // Restore default Locale and TimeZone
 150             Locale.setDefault(loc);
 151             TimeZone.setDefault(tz);
 152         }
 153         if (error > 0) {
 154             throw new RuntimeException("Failed");
 155         }
 156     }
 157 
 158     private static void testExceptions() {
 159         Calendar.Builder calb;
 160         Calendar cal;
 161 
 162         // NPE
 163         try {
 164             calb = builder().setInstant((Date)null);
 165             noException("setInstant((Date)null)");
 166         } catch (NullPointerException npe) {
 167         }
 168         try {
 169             calb = builder().setCalendarType(null);
 170             noException("setCalendarType(null)");
 171         } catch (NullPointerException npe) {
 172         }
 173         try {
 174             calb = builder().setLocale(null);
 175             noException("setLocale(null)");
 176         } catch (NullPointerException npe) {
 177         }
 178         try {
 179             calb = builder().setTimeZone(null);
 180             noException("setTimeZone(null)");
 181         } catch (NullPointerException npe) {
 182         }
 183 
 184         // IllegalArgumentException
 185         try {
 186             // invalid field index in set
 187             calb = builder().set(100, 2013);
 188             noException("set(100, 2013)");
 189         } catch (IllegalArgumentException e) {
 190         }
 191         try {
 192             // invalid field index in setField
 193             calb = builder().setFields(100, 2013);
 194             noException("setFields(100, 2013)");
 195         } catch (IllegalArgumentException e) {
 196         }
 197         try {
 198             // odd number of arguments
 199             calb = builder().setFields(YEAR, 2013, MONTH);
 200             noException("setFields(YEAR, 2013, MONTH)");
 201         } catch (IllegalArgumentException e) {
 202         }
 203         try {
 204             // unknown calendar type
 205             calb = builder().setCalendarType("foo");
 206             noException("setCalendarType(\"foo\")");
 207         } catch (IllegalArgumentException e) {
 208         }
 209         try {
 210             // invalid week definition parameter
 211             calb = builder().setWeekDefinition(8, 1);
 212             noException("setWeekDefinition(8, 1)");
 213         } catch (IllegalArgumentException e) {
 214         }
 215         try {
 216             // invalid week definition parameter
 217             calb = builder().setWeekDefinition(SUNDAY, 0);
 218             noException("setWeekDefinition(8, 1)");
 219         } catch (IllegalArgumentException e) {
 220         }
 221 
 222         try {
 223             // sets both instant and field parameters
 224             calb = builder().setInstant(new Date()).setDate(2013, JANUARY, 1);
 225             noException("setInstant(new Date()).setDate(2013, JANUARY, 1)");
 226         } catch (IllegalStateException e) {
 227         }
 228         try {
 229             // sets both field parameters and instant
 230             calb = builder().setDate(2013, JANUARY, 1).setInstant(new Date());
 231             noException("setDate(2013, JANUARY, 1).setInstant(new Date())");
 232         } catch (IllegalStateException e) {
 233         }
 234         try {
 235             // sets inconsistent calendar types
 236             calb = builder().setCalendarType("iso8601").setCalendarType("japanese");
 237             noException("setCalendarType(\"iso8601\").setCalendarType(\"japanese\")");
 238         } catch (IllegalStateException e) {
 239         }
 240 
 241         // IllegalArgumentException in build()
 242         calb = nonLenientBuilder().set(MONTH, 100);
 243         checkException(calb, IllegalArgumentException.class);
 244         calb = nonLenientBuilder().setTimeOfDay(23, 59, 70);
 245         checkException(calb, IllegalArgumentException.class);
 246         calb = builder().setCalendarType("japanese").setWeekDate(2013, 1, MONDAY);
 247         checkException(calb, IllegalArgumentException.class);
 248     }
 249 
 250     private static Calendar.Builder builder() {
 251         return new Calendar.Builder();
 252     }
 253 
 254     private static Calendar.Builder nonLenientBuilder() {
 255         return builder().setLenient(false);
 256     }
 257 
 258     private static Calendar getISO8601() {
 259         GregorianCalendar cal = new GregorianCalendar();
 260         cal.setFirstDayOfWeek(MONDAY);
 261         cal.setMinimalDaysInFirstWeek(4);
 262         cal.setGregorianChange(new Date(Long.MIN_VALUE));
 263         cal.clear();
 264         return cal;
 265     }
 266 
 267     private static void check(Calendar cal, Calendar expected) {
 268         if (!cal.equals(expected)) {
 269             error++;
 270             System.err.println("FAILED:");
 271             System.err.println("\t     cal = "+cal.getTime());
 272             System.err.println("\texpected = "+expected.getTime());
 273             System.err.printf("\tcal = %s%n\texp = %s%n", cal, expected);
 274         }
 275     }
 276 
 277     private static void checkException(Calendar.Builder calb, Class<? extends Exception> exception) {
 278         try {
 279             Calendar cal = calb.build();
 280             error++;
 281             System.err.println("expected exception: " + exception);
 282         } catch (Exception e) {
 283             if (!e.getClass().equals(exception)) {
 284                 error++;
 285                 System.err.println("unexpected exception: " + e.getClass() + ", expected: " + exception);
 286             }
 287         }
 288     }
 289 
 290     private static void noException(String msg) {
 291         error++;
 292         System.err.println("no exception with "+msg);
 293     }
 294 }