1 /*
   2  * Copyright (c) 2003, 2020, 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 4860664 4916815 4867075
  27  * @library /java/text/testlib
  28  * @build Koyomi
  29  * @run main FieldStateTest
  30  * @summary Unit tests for internal fields states.
  31  */
  32 
  33 import java.util.Date;
  34 import java.util.Locale;
  35 import java.util.TimeZone;
  36 
  37 import static java.util.Calendar.*;
  38 
  39 public class FieldStateTest extends IntlTest {
  40 
  41     public static void main(String[] args) throws Exception {
  42         Locale reservedLocale = Locale.getDefault();
  43         TimeZone reservedTimeZone = TimeZone.getDefault();
  44         try {
  45             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
  46             Locale.setDefault(Locale.US);
  47 
  48             new FieldStateTest().run(args);
  49         } finally {
  50             // restore the reserved locale and time zone
  51             Locale.setDefault(reservedLocale);
  52             TimeZone.setDefault(reservedTimeZone);
  53         }
  54     }
  55 
  56     public void TestFieldState() {
  57         Koyomi cal = new Koyomi();
  58         logln("Right after instantialtion:");
  59         if (!cal.checkAllSet()) {
  60             errln(cal.getMessage());
  61         }
  62 
  63         logln("Set date to 2003/10/31 after the instantiation:");
  64         cal.set(2003, OCTOBER, 31);
  65         // let cal calculate the time
  66         cal.getTime();
  67         // At this point, all fields have to be recalculated and
  68         // happen to have the set-state from the instantiation. The
  69         // three fields should have "externally set" and the rest of
  70         // the fields have "computed". But we can't distinguish them
  71         // outside the package.
  72         if (!cal.checkAllSet()) {
  73             errln(cal.getMessage());
  74         }
  75         // Make sure that the correct date was produced.
  76         if (!cal.checkInternalDate(2003, OCTOBER, 31, FRIDAY)) {
  77             errln(cal.getMessage());
  78         }
  79 
  80         logln("Change to Monday of the week, which is 2003/10/27:");
  81         cal.set(DAY_OF_WEEK, MONDAY);
  82         cal.getTime();
  83         if (!cal.checkDate(2003, OCTOBER, 27)) {
  84             errln(cal.getMessage());
  85         }
  86 
  87         // The same operation didn't work after calling clear() before
  88         // 1.5 because the set-state was just depends on its previous
  89         // operations. After the instantiation, all the fields are set
  90         // to "computed". But after calling clear(), the state becomes
  91         // "unset".
  92         logln("Set to 2003/10/31 after clear():");
  93         cal.clear();
  94         cal.set(2003, OCTOBER, 31);
  95         cal.getTime();
  96         cal.set(DAY_OF_WEEK, MONDAY);
  97         if (!cal.checkDate(2003, OCTOBER, 27, MONDAY)) {
  98             errln(cal.getMessage());
  99         }
 100 
 101         logln("Set to 2003/10/31 after clear(), then to the 51st week of year (12/19):");
 102         cal.clear();
 103         cal.set(2003, OCTOBER, 31);
 104         cal.getTime();
 105         cal.set(WEEK_OF_YEAR, 51);
 106         if (!cal.checkFieldValue(WEEK_OF_YEAR, 51)) {
 107             errln(cal.getMessage());
 108         }
 109         if (!cal.checkDate(2003, DECEMBER, 19, FRIDAY)) {
 110             errln(cal.getMessage());
 111         }
 112 
 113         logln("Set to 2003/10 Mon of 4th week (10/20: 43rd week of year, 293rd day):");
 114         cal.clear();
 115         cal.set(YEAR, 2003);
 116         cal.set(MONTH, OCTOBER);
 117         cal.set(DAY_OF_WEEK, MONDAY);
 118         cal.set(WEEK_OF_MONTH, 4);
 119         cal.getTime();
 120         if (!cal.checkFieldValue(DAY_OF_MONTH, 20)) {
 121             errln(cal.getMessage());
 122         }
 123         if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
 124             errln(cal.getMessage());
 125         }
 126         if (!cal.checkFieldValue(WEEK_OF_YEAR, 43)) {
 127             errln(cal.getMessage());
 128         }
 129 
 130         logln("Set to 2003/10 Mon of 43rd week of year (10/20: 4th week of month, 293rd day):");
 131         cal.clear();
 132         cal.set(YEAR, 2003);
 133         cal.set(DAY_OF_WEEK, MONDAY);
 134         cal.set(WEEK_OF_YEAR, 43);
 135         cal.getTime();
 136         if (!cal.checkDate(2003, OCTOBER, 20, MONDAY)) {
 137             errln(cal.getMessage());
 138         }
 139         if (!cal.checkFieldValue(WEEK_OF_MONTH, 4)) {
 140             errln(cal.getMessage());
 141         }
 142         if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
 143             errln(cal.getMessage());
 144         }
 145 
 146         logln("Set day of week to SUNDAY and date to 2003/10/31. "
 147                 + "Then, getTime and set week of year to 43.");
 148 
 149         @SuppressWarnings("deprecation")
 150         Date d = new Date(2003 - 1900, OCTOBER, 31);
 151         cal.setTime(d);
 152         cal.set(DAY_OF_WEEK, SUNDAY);
 153         cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday.
 154         cal.set(ZONE_OFFSET, 0);
 155         cal.set(DST_OFFSET, 0);
 156 
 157         // This call should change the day of week to FRIDAY since the
 158         // selected field combination should be YEAR, MONTH and
 159         // DAY_OF_MONTH. The other calendar fields must be normalized
 160         // with the selected date.
 161         cal.getTime();
 162         cal.set(WEEK_OF_YEAR, 43);
 163         if (!cal.checkDate(2003, OCTOBER, 24, FRIDAY)) {
 164             errln(cal.getMessage());
 165         }
 166     }
 167 
 168     /*
 169      * 4916815: REGRESSION: Problem with java.util.Calendar VM 1.4.2-b28
 170      */
 171     public void Test4916815() {
 172         logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. "
 173                 + "Set dayofweek to Sunday which should be 2003/9/21.");
 174         Koyomi cal = new Koyomi();
 175         cal.clear();
 176         // 2003/9/26 (Fri)
 177         cal.set(2003, SEPTEMBER, 26);
 178         // Go to August then back to September
 179         cal.roll(MONTH, -1);
 180         cal.roll(MONTH, +1);
 181         Koyomi cal2 = (Koyomi) cal.clone();
 182         cal2.getTime();
 183         // Sunday of the week should be 2003/9/21.
 184         cal2.set(DAY_OF_WEEK, SUNDAY);
 185         if (!cal2.checkDate(2003, SEPTEMBER, 21, SUNDAY)) {
 186             errln(cal2.getMessage());
 187         }
 188     }
 189 
 190     /*
 191      * 4867075: GregorianCalendar get() calls complete() internally, should getTime() too?
 192      */
 193     public void Test4867075() {
 194         Koyomi cal = new Koyomi(Locale.US);
 195         cal.clear();
 196         cal.set(YEAR, 2004);
 197         cal.set(WEEK_OF_YEAR, 1);
 198         checkDate(cal, SUNDAY, 2003, DECEMBER, 28);
 199         checkDate(cal, MONDAY, 2003, DECEMBER, 29);
 200         checkDate(cal, TUESDAY, 2003, DECEMBER, 30);
 201         checkDate(cal, WEDNESDAY, 2003, DECEMBER, 31);
 202         checkDate(cal, THURSDAY, 2004, JANUARY, 1);
 203         checkDate(cal, FRIDAY, 2004, JANUARY, 2);
 204         checkDate(cal, SATURDAY, 2004, JANUARY, 3);
 205     }
 206 
 207     private void checkDate(Koyomi cal, int dayOfWeek,
 208             int expectedYear, int expectedMonth, int expectedDayOfMonth) {
 209         cal.set(DAY_OF_WEEK, dayOfWeek);
 210         cal.getTime();
 211         if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) {
 212             errln(cal.getMessage());
 213         }
 214     }
 215 
 216     static String toHexString(int x) {
 217         return Integer.toHexString(x);
 218     }
 219 }