1 /* 2 * Copyright (c) 2001, 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 4322313 4833268 6302990 6304305 27 * @library /java/text/testlib 28 * @summary Make sure that new implementation for 29 * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly. 30 */ 31 32 import java.io.*; 33 import java.text.*; 34 import java.util.*; 35 36 public class Bug4322313 extends IntlTest { 37 38 public void Test4322313() { 39 Locale savedLocale = Locale.getDefault(); 40 TimeZone savedTimeZone = TimeZone.getDefault(); 41 boolean err = false; 42 long mpm = 60 * 1000; /* Milliseconds per a minute */ 43 44 Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")}; 45 46 String[] formats = { 47 "z", 48 "Z", 49 }; 50 51 Object[][] valids = { 52 /* given ID offset format('z'), ('Z') index */ 53 {"GMT+03:04", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)}, 54 {"GMT+13:42", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)}, 55 {"GMT+00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, 56 {"GMT+1:11", new Long(-71 * mpm), "GMT+01:11", "+0111", new Integer(8)}, 57 {"GMT +13:42", new Long(0), "GMT", "+0000", new Integer(3)}, 58 {" GMT", new Long(0), "GMT", "+0000", new Integer(4)}, 59 {"+0304", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)}, 60 {"+1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)}, 61 {"+0000", new Long(0), "GMT+00:00", "+0000", new Integer(5)}, 62 {" +1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)}, 63 /* ISO-LATIN-1 digits */ 64 {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)}, 65 66 /* In fact, this test case is skipped because TimeZone class can't 67 * recognize TimeZone IDs like "+00234" or "-00234". 68 */ 69 {"+00234", new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)}, 70 71 {"GMT-03:04", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)}, 72 {"GMT-13:42", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)}, 73 {"GMT-00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)}, 74 {"GMT-1:11", new Long(71 * mpm), "GMT-01:11", "-0111", new Integer(8)}, 75 {"GMT -13:42", new Long(0), "GMT", "+0000", new Integer(3)}, 76 {"-0304", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)}, 77 {"-1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)}, 78 {" -1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)}, 79 /* ISO-LATIN-1 digits */ 80 {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)}, 81 /* In fact, this test case is skipped because TimeZone class can't 82 * recognize TimeZone IDs like "+00234" or "-00234". 83 */ 84 {"-00234", new Long(23 * mpm), "GMT+00:23", "-0023", new Integer(5)}, 85 }; 86 87 Object[][] invalids = { 88 /* given ID error index */ 89 {"GMT+8", new Integer(5)}, 90 {"GMT+18", new Integer(6)}, 91 {"GMT+208", new Integer(6)}, 92 {"GMT+0304", new Integer(6)}, 93 {"GMT+42195", new Integer(5)}, 94 {"GMT+5:8", new Integer(7)}, 95 {"GMT+23:60", new Integer(8)}, 96 {"GMT+11:1", new Integer(8)}, 97 {"GMT+24:13", new Integer(5)}, 98 {"GMT+421:950", new Integer(5)}, 99 {"GMT+0a:0A", new Integer(5)}, 100 {"GMT+ 13:42", new Integer(4)}, 101 {"GMT+13 :42", new Integer(6)}, 102 {"GMT+13: 42", new Integer(7)}, 103 {"GMT+-13:42", new Integer(4)}, 104 {"G M T", new Integer(0)}, 105 {"+8", new Integer(2)}, 106 {"+18", new Integer(3)}, 107 {"+208", new Integer(4)}, 108 {"+2360", new Integer(4)}, 109 {"+2413", new Integer(2)}, 110 {"+42195", new Integer(2)}, 111 {"+0AbC", new Integer(2)}, 112 {"+ 1342", new Integer(1)}, 113 {"+-1342", new Integer(1)}, 114 {"1342", new Integer(0)}, 115 /* Arabic-Indic digits */ 116 {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)}, 117 /* Extended Arabic-Indic digits */ 118 {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, 119 /* Devanagari digits */ 120 {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)}, 121 /* Fullwidth digits */ 122 {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, 123 124 {"GMT-8", new Integer(5)}, 125 {"GMT-18", new Integer(6)}, 126 {"GMT-208", new Integer(6)}, 127 {"GMT-0304", new Integer(6)}, 128 {"GMT-42195", new Integer(5)}, 129 {"GMT-5:8", new Integer(7)}, 130 {"GMT-23:60", new Integer(8)}, 131 {"GMT-11:1", new Integer(8)}, 132 {"GMT-24:13", new Integer(5)}, 133 {"GMT-421:950", new Integer(5)}, 134 {"GMT-0a:0A", new Integer(5)}, 135 {"GMT- 13:42", new Integer(4)}, 136 {"GMT-13 :42", new Integer(6)}, 137 {"GMT-13: 42", new Integer(7)}, 138 {"GMT-+13:42", new Integer(4)}, 139 {"-8", new Integer(2)}, 140 {"-18", new Integer(3)}, 141 {"-208", new Integer(4)}, 142 {"-2360", new Integer(4)}, 143 {"-2413", new Integer(2)}, 144 {"-42195", new Integer(2)}, 145 {"-0AbC", new Integer(2)}, 146 {"- 1342", new Integer(1)}, 147 {"--1342", new Integer(1)}, 148 {"-802", new Integer(2)}, 149 /* Arabic-Indic digits */ 150 {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)}, 151 /* Extended Arabic-Indic digits */ 152 {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)}, 153 /* Devanagari digits */ 154 {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)}, 155 /* Fullwidth digits */ 156 {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)}, 157 }; 158 159 try { 160 for (int i=0; i < locs.length; i++) { 161 Locale locale = locs[i]; 162 Locale.setDefault(locale); 163 164 for (int j=0; j < formats.length; j++) { 165 TimeZone.setDefault(TimeZone.getTimeZone("GMT")); 166 SimpleDateFormat sdf = new SimpleDateFormat(formats[j]); 167 Date date; 168 169 /* Okay case */ 170 for (int k=0; k < valids.length; k++) { 171 ParsePosition pos = new ParsePosition(0); 172 try { 173 date = sdf.parse((String)valids[k][0], pos); 174 } 175 catch (Exception e) { 176 err = true; 177 System.err.println("\tParse Error [Locale=" + 178 locale + ", " + formats[j] + 179 "/\"" + valids[k][0] + 180 "\"] Unexpected Exception occurred: " + e); 181 continue; 182 } 183 184 int offset = pos.getIndex(); 185 if (offset != ((Integer)valids[k][4]).intValue()) { 186 err = true; 187 System.err.println("\tParse Error [Locale=" + 188 locale + ", " + formats[j] + 189 "/\"" + valids[k][0] + 190 "\"] invalid index: expected:" + valids[k][4] + 191 ", got:" + offset); 192 } 193 194 if (date.getTime() != ((Long)valids[k][1]).longValue()) { 195 err = true; 196 System.err.println("\tParse Error [Locale=" + 197 locale + ", " + formats[j] + 198 "/\"" + valids[k][0] + 199 "\"] expected:" + valids[k][1] + 200 ", got:" + date.getTime() + ", " + date); 201 } else { 202 /* 203 logln("\tParse Okay [Locale=" + 204 locale) + ", " + formats[j] + 205 "/\"" + valids[k][0] + 206 "\"] expected:" + valids[k][1] + 207 ", got:" + date.getTime() + ", " + date); 208 */ 209 210 try { 211 date = sdf.parse((String)valids[k][0]); 212 } 213 catch (Exception e) { 214 err = true; 215 System.err.println("\tParse Error [Locale=" + 216 locale + ", " + formats[j] + 217 "/\"" + valids[k][0] + 218 "\"] Unexpected Exception occurred: " + e); 219 continue; 220 } 221 222 /* Since TimeZone.getTimeZone() don't treat 223 * "+00234" or "-00234" as a valid ID, skips. 224 */ 225 if (((String)valids[k][0]).length() == 6) { 226 continue; 227 } 228 229 /* Since TimeZone.getTimeZone() don't recognize 230 * +hhmm/-hhmm format, add "GMT" as prefix. 231 */ 232 sdf.setTimeZone(TimeZone.getTimeZone( 233 (((((String)valids[k][0]).charAt(0) != 'G') ? 234 "GMT" : "") + valids[k][0]))); 235 StringBuffer s = new StringBuffer(); 236 sdf.format(date, s, new FieldPosition(0)); 237 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 238 239 String got = s.toString(); 240 String expected = (String)valids[k][2+j]; 241 if (!got.equals(expected) && 242 // special case to allow the difference between 243 // DateFormatSymbols.getZoneStrings() and 244 // TimeZone.getDisplayName() for "GMT+-00:00" 245 !(got.equals("GMT-00:00") && 246 expected.equals("GMT+00:00"))) { 247 err = true; 248 System.err.println("\tFormat Error [Locale=" + 249 locale + ", " + 250 formats[j] + "/\"" + valids[k][0] + 251 "\"] expected:" + valids[k][2+j] + 252 ", got:" + s + ", " + date); 253 } else { 254 /* 255 logln("\tFormat Okay [Locale=" + 256 locale + ", " + 257 formats[j] + "/\"" + valids[k][0] + 258 "\"] expected:" + valids[k][2+j] + 259 ", got:" + s + ", " + date); 260 */ 261 } 262 } 263 } 264 265 /* Error case 1 266 * using SimpleDateFormat.parse(String, ParsePosition) 267 */ 268 for (int k=0; k < invalids.length; k++) { 269 ParsePosition pos = new ParsePosition(0); 270 try { 271 date = sdf.parse((String)invalids[k][0], pos); 272 if (date != null) { 273 err = true; 274 System.err.println("\tParse Error [Locale=" + 275 locale + ", " + formats[j] + 276 "/\"" + invalids[k][0] + 277 "\"] expected:null , got:" + date); 278 } 279 int offset = pos.getErrorIndex(); 280 if (offset != ((Integer)invalids[k][1]).intValue()) { 281 err = true; 282 System.err.println("\tParse Error [Locale=" + 283 locale + ", " + formats[j] + 284 "/\"" + invalids[k][0] + 285 "\"] incorrect offset. expected:" + 286 invalids[k][1] + ", got: " + offset); 287 } else { 288 /* 289 logln("\tParse Okay [Locale=" + 290 locale + ", " + formats[j] + 291 "/\"" + invalids[k][0] + 292 "\"] correct offset: " + offset); 293 */ 294 } 295 } 296 catch (Exception e) { 297 err = true; 298 System.err.println("\tParse Error [Locale=" + 299 locale + ", " + formats[j] + 300 "/\"" + invalids[k][0] + 301 "\"] Unexpected Exception occurred: " + e); 302 } 303 } 304 305 /* Error case 2 306 * using DateFormat.parse(String) 307 */ 308 boolean correctParseException = false; 309 for (int k=0; k < invalids.length; k++) { 310 try { 311 date = sdf.parse((String)invalids[k][0]); 312 } 313 catch (ParseException e) { 314 correctParseException = true; 315 int offset = e.getErrorOffset(); 316 if (offset != ((Integer)invalids[k][1]).intValue()) { 317 err = true; 318 System.err.println("\tParse Error [Locale=" + 319 locale + ", " + formats[j] + 320 "/\"" + invalids[k][0] + 321 "\"] Expected exception occurred with an incorrect offset. expected:" + 322 invalids[k][1] + ", got: " + offset); 323 } else { 324 /* 325 logln("\tParse Okay [Locale=" + 326 locale + ", " + formats[j] + 327 "/\"" + invalids[k][0] + 328 "\"] Expected exception occurred with an correct offset: " 329 + offset); 330 */ 331 } 332 } 333 catch (Exception e) { 334 err = true; 335 System.err.println("\tParse Error [Locale=" + 336 locale + ", " + formats[j] + 337 "/\"" + invalids[k][0] + 338 "\"] Invalid exception occurred: " + e); 339 } 340 finally { 341 if (!correctParseException) { 342 err = true; 343 System.err.println("\tParse Error: [Locale=" + 344 locale + ", " + formats[j] + 345 "/\"" + invalids[k][0] + 346 "\"] Expected exception didn't occur."); 347 } 348 } 349 } 350 } 351 } 352 } 353 finally { 354 Locale.setDefault(savedLocale); 355 TimeZone.setDefault(savedTimeZone); 356 if (err) { 357 errln("SimpleDateFormat.parse()/format() test failed"); 358 } 359 } 360 } 361 362 public static void main(String[] args) throws Exception { 363 new Bug4322313().run(args); 364 } 365 }