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