1 /*
   2  * Copyright (c) 2003, 2016, 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 4958050
  27  * @summary Make sure that add() and roll() handle time zone offset changes (both raw and DST) correctly.
  28  */
  29 
  30 import java.util.Locale;
  31 import java.util.TimeZone;
  32 import static java.util.Calendar.*;
  33 
  34 public class Bug4958050 {
  35     static int errorCount = 0;
  36 
  37     public static void main(String[] args) {
  38         // All the test cases depend on historical GMT offset changes
  39         // of Asia/Novosibirsk.
  40         Koyomi cal = new Koyomi(TimeZone.getTimeZone("Asia/Novosibirsk"), Locale.US);
  41         System.out.println("Time zone = " + cal.getTimeZone().getID());
  42 
  43         // Test the week fields
  44         int[] weekFields = { WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH };
  45         for (int i = 0; i < weekFields.length; i++) {
  46             int field = weekFields[i];
  47             // add()
  48             cal.clear();
  49             cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
  50             cal.add(weekFields[i], +1);
  51             if (!cal.checkDate(1919, DECEMBER, 14)) {
  52                 error("1919/12/07: add("+cal.getFieldName(weekFields[i])+", +1)\n"
  53                       + cal.getMessage()+" " + cal.toDateTimeString());
  54             }
  55             cal.clear();
  56             cal.set(1930, JUNE, 21-7);
  57             cal.add(weekFields[i], +1);
  58             if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
  59                 error("1930/6/14: add("+cal.getFieldName(weekFields[i])+", +1)\n"
  60                       + cal.getMessage()+" " + cal.toDateTimeString());
  61             }
  62 
  63             // roll()
  64             cal.clear();
  65             cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
  66             cal.roll(weekFields[i], +1);
  67             if (!cal.checkDate(1919, DECEMBER, 14)) {
  68                 error("1919/12/07: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
  69                       + cal.getMessage()+" " + cal.toDateTimeString());
  70             }
  71             cal.clear();
  72             cal.set(1930, JUNE, 21-7);
  73             cal.roll(weekFields[i], +1);
  74             if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
  75                 error("1930/6/14: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
  76                       + cal.getMessage()+" " + cal.toDateTimeString());
  77             }
  78         }
  79 
  80         // Test the day fields
  81         int[] dayFields = { DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK };
  82         for (int i = 0; i < dayFields.length; i++) {
  83             int field = dayFields[i];
  84             // add()
  85             cal.clear();
  86             cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
  87             cal.add(field, +1);
  88             if (!cal.checkDate(1919, DECEMBER, 14)) {
  89                 error("1919/12/13: add("+cal.getFieldName(field)+", +1)\n"
  90                       + cal.getMessage()+" " + cal.toDateTimeString());
  91             }
  92             cal.clear();
  93             cal.set(1919, DECEMBER, 14, 00, 00, 00);
  94             cal.add(field, -1);
  95             if (!cal.checkDate(1919, DECEMBER, 13)) {
  96                 error("1919/12/14: add("+cal.getFieldName(field)+", -1)\n"
  97                       + cal.getMessage()+" " + cal.toDateTimeString());
  98             }
  99             cal.clear();
 100             cal.set(1930, JUNE, 21-1);
 101             cal.add(field, +1);
 102             if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
 103                 error("1930/6/20: add("+cal.getFieldName(field)+", +1)\n"
 104                       + cal.getMessage() + cal.toDateTimeString());
 105             }
 106             cal.clear();
 107             cal.set(1930, JUNE, 21, 01, 00, 00);
 108             cal.add(field, -1);
 109             if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
 110                 error("1930/6/21: add("+cal.getFieldName(field)+", -1)\n"
 111                       + cal.getMessage()+" " + cal.toDateTimeString());
 112             }
 113 
 114             // roll()
 115             cal.clear();
 116             cal.set(1930, JUNE, 21-1);
 117             int amount = +1;
 118             if (field == DAY_OF_WEEK) {
 119                 amount += 700;
 120             }
 121             cal.roll(field, amount);
 122             if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
 123                 error("1930/6/20: roll("+cal.getFieldName(field)+", +"+amount+")\n"
 124                       + cal.getMessage() + " " + cal.toDateTimeString());
 125             }
 126             cal.clear();
 127             cal.set(1930, JUNE, 21, 01, 00, 00);
 128             amount = -1;
 129             if (field == DAY_OF_WEEK) {
 130                 amount -= 700;
 131             }
 132             cal.roll(field, amount);
 133             if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
 134                 error("1930/6/21: roll("+cal.getFieldName(field)+", "+amount+")\n"
 135                       + cal.getMessage()+" "+cal.toDateTimeString());
 136             }
 137         }
 138 
 139         // Test the AM_PM field
 140         // add()
 141         cal.clear();
 142         cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
 143         cal.add(AM_PM, +1);
 144         if (!cal.checkDate(1919, DECEMBER, 14)
 145             || !cal.checkFieldValue(AM_PM, AM)) {
 146             error("1919/12/13: add(AM_PM, +1)\n"
 147                   + cal.getMessage()+" "+cal.toDateTimeString());
 148         }
 149 
 150         cal.clear();
 151         cal.set(1930, JUNE, 21-1, 12, 00, 00);
 152         cal.add(AM_PM, +1);
 153         if (!cal.checkDate(1930, JUNE, 21)
 154             || !cal.checkFieldValue(AM_PM, AM)) {
 155             error("1930/6/20: add(AM_PM, +1)\n"
 156                   + cal.getMessage()+" "+cal.toDateTimeString());
 157         }
 158 
 159         cal.clear();
 160         cal.set(1930, JUNE, 21-2, 12, 00, 00);
 161         cal.add(AM_PM, +3);
 162         if (!cal.checkDate(1930, JUNE, 21)
 163             || !cal.checkFieldValue(AM_PM, AM)) {
 164             error("1930/6/10: add(AM_PM, +3)\n"
 165                   + cal.getMessage()+" "+cal.toDateTimeString());
 166         }
 167 
 168         cal.clear();
 169         cal.set(1919, DECEMBER, 14, 11, 50, 00);
 170         cal.add(AM_PM, -1);
 171         if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23, 50, 00, 000)
 172             || !cal.checkFieldValue(AM_PM, PM)) {
 173             error("1919/12/14 11:50:00: add(AM_PM, -1)\n"
 174                   + cal.getMessage()+" "+cal.toDateTimeString());
 175         }
 176 
 177         cal.clear();
 178         cal.set(1930, JUNE, 21, 01, 00, 00);
 179         cal.add(AM_PM, -1);
 180         if (!cal.checkDateTime(1930, JUNE, 21-1, 01+12, 00, 00, 000)
 181             || !cal.checkFieldValue(AM_PM, PM)) {
 182             error("1930/6/20: add(AM_PM, -1)\n"
 183                   + cal.getMessage()+" "+cal.toDateTimeString());
 184         }
 185 
 186         cal.clear();
 187         cal.set(1930, JUNE, 21, 01, 00, 00);
 188         cal.add(AM_PM, -3);
 189         if (!cal.checkDateTime(1930, JUNE, 21-2, 01+12, 00, 00, 000)
 190             || !cal.checkFieldValue(AM_PM, PM)) {
 191             error("1930/6/10: add(AM_PM, -3)\n"
 192                   + cal.getMessage()+" "+cal.toDateTimeString());
 193         }
 194 
 195         // roll() (should NOT change the date)
 196         cal.clear();
 197         cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
 198         cal.roll(AM_PM, +1);
 199         if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23-12, 50, 00, 000)
 200             || !cal.checkFieldValue(AM_PM, AM)) {
 201             error("1919/12/13: roll(AM_PM, +1)\n"
 202                   + cal.getMessage()+" "+cal.toDateTimeString());
 203         }
 204 
 205         cal.clear();
 206         cal.set(1930, JUNE, 21-1, 12, 00, 00);
 207         cal.roll(AM_PM, +1);
 208         if (!cal.checkDateTime(1930, JUNE, 21-1, 12-12, 00, 00, 000)
 209             || !cal.checkFieldValue(AM_PM, AM)) {
 210             error("1930/6/20: roll(AM_PM, +1)\n"
 211                   + cal.getMessage()+" "+cal.toDateTimeString());
 212         }
 213 
 214         cal.clear();
 215         cal.set(1930, JUNE, 21-2, 12, 00, 00);
 216         cal.roll(AM_PM, +3);
 217         if (!cal.checkDateTime(1930, JUNE, 21-2, 12-12, 00, 00, 000)
 218             || !cal.checkFieldValue(AM_PM, AM)) {
 219             error("1930/6/10: roll(AM_PM, +3)\n"
 220                   + cal.getMessage()+" "+cal.toDateTimeString());
 221         }
 222 
 223         // Test the HOUR_OF_DAY field
 224         // add()
 225         cal.clear();
 226         cal.set(1930, JUNE, 20, 23, 00, 00);
 227         cal.add(HOUR_OF_DAY, +1);
 228         if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
 229             error("1930/6/20 23:00:00: add(HOUR_OF_DAY, +1)\n"
 230                   + cal.getMessage()+" "+cal.toDateTimeString());
 231         }
 232 
 233         // roll() (should NOT change the date)
 234         cal.clear();
 235         cal.set(1930, JUNE, 20, 23, 00, 00);
 236         cal.roll(HOUR_OF_DAY, +1);
 237         if (!cal.checkDateTime(1930, JUNE, 20, 00, 00, 00, 000)) {
 238             error("1930/6/20 23:00:00: roll(HOUR_OF_DAY, +1)\n"
 239                   + cal.getMessage()+" "+cal.toDateTimeString());
 240         }
 241 
 242         checkErrors();
 243     }
 244 
 245     static void error(String s) {
 246         System.out.println(s);
 247         errorCount++;
 248     }
 249 
 250     static void checkErrors() {
 251         if (errorCount > 0) {
 252             throw new RuntimeException("Failed: " + errorCount + " error(s)");
 253         }
 254     }
 255 }