test/java/time/tck/java/time/TCKZoneId.java

Print this page




  47  *
  48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  59  */
  60 package tck.java.time;
  61 
  62 import static org.testng.Assert.assertEquals;
  63 import static org.testng.Assert.fail;
  64 
  65 import java.io.ByteArrayInputStream;
  66 import java.io.ByteArrayOutputStream;
  67 import java.io.DataInputStream;
  68 import java.io.DataOutputStream;
  69 import java.io.IOException;
  70 import java.io.ObjectInputStream;
  71 import java.io.ObjectStreamConstants;
  72 import java.lang.reflect.Field;
  73 import java.time.DateTimeException;

  74 import java.time.LocalTime;
  75 import java.time.ZoneId;
  76 import java.time.ZoneOffset;
  77 import java.time.temporal.Queries;
  78 import java.time.temporal.TemporalAccessor;
  79 import java.time.temporal.TemporalField;
  80 import java.time.temporal.TemporalQuery;
  81 import java.time.zone.ZoneRulesException;
  82 import java.util.HashMap;

  83 import java.util.Map;

  84 
  85 import org.testng.annotations.DataProvider;
  86 import org.testng.annotations.Test;
  87 
  88 /**
  89  * Test ZoneId.
  90  */
  91 @Test
  92 public class TCKZoneId extends AbstractTCKTest {
  93 
  94     //-----------------------------------------------------------------------
  95     @Test
  96     public void test_serialization() throws Exception {
  97         assertSerializable(ZoneId.of("Europe/London"));
  98         assertSerializable(ZoneId.of("America/Chicago"));
  99     }
 100 
 101     @Test
 102     public void test_serialization_format() throws Exception {
 103         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 104         try (DataOutputStream dos = new DataOutputStream(baos) ) {
 105             dos.writeByte(7);
 106             dos.writeUTF("Europe/London");
 107         }
 108         byte[] bytes = baos.toByteArray();
 109         assertSerializedBySer(ZoneId.of("Europe/London"), bytes);
 110     }
 111 
 112     @Test
 113     public void test_deserialization_lenient_characters() throws Exception {
 114         // an ID can be loaded without validation during deserialization
 115         String id = "QWERTYUIOPASDFGHJKLZXCVBNM~/._+-";
 116         ZoneId deser = deserialize(id);
 117         // getting the ID and string are OK
 118         assertEquals(deser.getId(), id);
 119         assertEquals(deser.toString(), id);



 120         // getting the rules is not
 121         try {
 122             deser.getRules();
 123             fail();
 124         } catch (ZoneRulesException ex) {
 125             // expected
 126         }
 127     }
 128 
 129     @Test(expectedExceptions=DateTimeException.class)
 130     public void test_deserialization_lenient_badCharacters() throws Exception {
 131         // an ID can be loaded without validation during deserialization
 132         // but there is a check to ensure the ID format is valid
 133         deserialize("|!?");
 134     }
 135 
 136     @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class)
 137     public void test_deserialization_lenient_offsetNotAllowed_noPrefix(String input, String resolvedId) throws Exception {
 138         // an ID can be loaded without validation during deserialization
 139         // but there is a check to ensure the ID format is valid
 140         deserialize(input);
 141     }
 142 
 143     @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class)
 144     public void test_deserialization_lenient_offsetNotAllowed_prefixUTC(String input, String resolvedId) throws Exception {
 145         // an ID can be loaded without validation during deserialization
 146         // but there is a check to ensure the ID format is valid
 147         deserialize("UTC" + input);
 148     }
 149 
 150     @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class)
 151     public void test_deserialization_lenient_offsetNotAllowed_prefixGMT(String input, String resolvedId) throws Exception {
 152         // an ID can be loaded without validation during deserialization
 153         // but there is a check to ensure the ID format is valid
 154         deserialize("GMT" + input);
 155     }
 156 
 157     @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class)
 158     public void test_deserialization_lenient_offsetNotAllowed_prefixUT(String input, String resolvedId) throws Exception {
 159         // an ID can be loaded without validation during deserialization
 160         // but there is a check to ensure the ID format is valid
 161         deserialize("UT" + input);
 162     }
 163 
 164     private ZoneId deserialize(String id) throws Exception {
 165         String serClass = ZoneId.class.getPackage().getName() + ".Ser";
 166         Class<?> serCls = Class.forName(serClass);
 167         Field field = serCls.getDeclaredField("serialVersionUID");
 168         field.setAccessible(true);
 169         long serVer = (Long) field.get(null);
 170         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 171         try (DataOutputStream dos = new DataOutputStream(baos)) {
 172             dos.writeShort(ObjectStreamConstants.STREAM_MAGIC);
 173             dos.writeShort(ObjectStreamConstants.STREAM_VERSION);
 174             dos.writeByte(ObjectStreamConstants.TC_OBJECT);
 175             dos.writeByte(ObjectStreamConstants.TC_CLASSDESC);
 176             dos.writeUTF(serClass);
 177             dos.writeLong(serVer);
 178             dos.writeByte(ObjectStreamConstants.SC_EXTERNALIZABLE | ObjectStreamConstants.SC_BLOCK_DATA);
 179             dos.writeShort(0);  // number of fields
 180             dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);  // end of classdesc
 181             dos.writeByte(ObjectStreamConstants.TC_NULL);  // no superclasses
 182             dos.writeByte(ObjectStreamConstants.TC_BLOCKDATA);
 183             dos.writeByte(1 + 2 + id.length());  // length of data (1 byte + 2 bytes UTF length + 32 bytes UTF)
 184             dos.writeByte(7);  // ZoneId
 185             dos.writeUTF(id);
 186             dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);  // end of blockdata
 187         }
 188         ZoneId deser = null;
 189         try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
 190             deser = (ZoneId) ois.readObject();
 191         }
 192         return deser;
 193     }
 194 
 195     //-----------------------------------------------------------------------
 196     // OLD_IDS_PRE_2005
 197     //-----------------------------------------------------------------------
 198     public void test_constant_OLD_IDS_PRE_2005() {
 199         Map<String, String> ids = ZoneId.OLD_IDS_PRE_2005;
 200         assertEquals(ids.get("EST"), "America/New_York");
 201         assertEquals(ids.get("MST"), "America/Denver");
 202         assertEquals(ids.get("HST"), "Pacific/Honolulu");
 203         assertEquals(ids.get("ACT"), "Australia/Darwin");
 204         assertEquals(ids.get("AET"), "Australia/Sydney");
 205         assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires");
 206         assertEquals(ids.get("ART"), "Africa/Cairo");
 207         assertEquals(ids.get("AST"), "America/Anchorage");
 208         assertEquals(ids.get("BET"), "America/Sao_Paulo");
 209         assertEquals(ids.get("BST"), "Asia/Dhaka");
 210         assertEquals(ids.get("CAT"), "Africa/Harare");
 211         assertEquals(ids.get("CNT"), "America/St_Johns");
 212         assertEquals(ids.get("CST"), "America/Chicago");
 213         assertEquals(ids.get("CTT"), "Asia/Shanghai");
 214         assertEquals(ids.get("EAT"), "Africa/Addis_Ababa");
 215         assertEquals(ids.get("ECT"), "Europe/Paris");
 216         assertEquals(ids.get("IET"), "America/Indiana/Indianapolis");
 217         assertEquals(ids.get("IST"), "Asia/Kolkata");
 218         assertEquals(ids.get("JST"), "Asia/Tokyo");
 219         assertEquals(ids.get("MIT"), "Pacific/Apia");
 220         assertEquals(ids.get("NET"), "Asia/Yerevan");
 221         assertEquals(ids.get("NST"), "Pacific/Auckland");
 222         assertEquals(ids.get("PLT"), "Asia/Karachi");
 223         assertEquals(ids.get("PNT"), "America/Phoenix");
 224         assertEquals(ids.get("PRT"), "America/Puerto_Rico");
 225         assertEquals(ids.get("PST"), "America/Los_Angeles");
 226         assertEquals(ids.get("SST"), "Pacific/Guadalcanal");
 227         assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh");
 228     }
 229 
 230     @Test(expectedExceptions=UnsupportedOperationException.class)
 231     public void test_constant_OLD_IDS_PRE_2005_immutable() {
 232         Map<String, String> ids = ZoneId.OLD_IDS_PRE_2005;
 233         ids.clear();
 234     }
 235 
 236     //-----------------------------------------------------------------------
 237     // OLD_IDS_POST_2005
 238     //-----------------------------------------------------------------------
 239     public void test_constant_OLD_IDS_POST_2005() {
 240         Map<String, String> ids = ZoneId.OLD_IDS_POST_2005;
 241         assertEquals(ids.get("EST"), "-05:00");
 242         assertEquals(ids.get("MST"), "-07:00");
 243         assertEquals(ids.get("HST"), "-10:00");
 244         assertEquals(ids.get("ACT"), "Australia/Darwin");
 245         assertEquals(ids.get("AET"), "Australia/Sydney");
 246         assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires");
 247         assertEquals(ids.get("ART"), "Africa/Cairo");
 248         assertEquals(ids.get("AST"), "America/Anchorage");
 249         assertEquals(ids.get("BET"), "America/Sao_Paulo");
 250         assertEquals(ids.get("BST"), "Asia/Dhaka");
 251         assertEquals(ids.get("CAT"), "Africa/Harare");
 252         assertEquals(ids.get("CNT"), "America/St_Johns");
 253         assertEquals(ids.get("CST"), "America/Chicago");
 254         assertEquals(ids.get("CTT"), "Asia/Shanghai");
 255         assertEquals(ids.get("EAT"), "Africa/Addis_Ababa");
 256         assertEquals(ids.get("ECT"), "Europe/Paris");
 257         assertEquals(ids.get("IET"), "America/Indiana/Indianapolis");
 258         assertEquals(ids.get("IST"), "Asia/Kolkata");
 259         assertEquals(ids.get("JST"), "Asia/Tokyo");
 260         assertEquals(ids.get("MIT"), "Pacific/Apia");
 261         assertEquals(ids.get("NET"), "Asia/Yerevan");
 262         assertEquals(ids.get("NST"), "Pacific/Auckland");
 263         assertEquals(ids.get("PLT"), "Asia/Karachi");
 264         assertEquals(ids.get("PNT"), "America/Phoenix");
 265         assertEquals(ids.get("PRT"), "America/Puerto_Rico");
 266         assertEquals(ids.get("PST"), "America/Los_Angeles");
 267         assertEquals(ids.get("SST"), "Pacific/Guadalcanal");
 268         assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh");
 269     }
 270 
 271     @Test(expectedExceptions=UnsupportedOperationException.class)
 272     public void test_constant_OLD_IDS_POST_2005_immutable() {
 273         Map<String, String> ids = ZoneId.OLD_IDS_POST_2005;
 274         ids.clear();
 275     }
 276 
 277     //-----------------------------------------------------------------------













 278     // mapped factory
 279     //-----------------------------------------------------------------------
 280     @Test
 281     public void test_of_string_Map() {
 282         Map<String, String> map = new HashMap<>();
 283         map.put("LONDON", "Europe/London");
 284         map.put("PARIS", "Europe/Paris");
 285         ZoneId test = ZoneId.of("LONDON", map);
 286         assertEquals(test.getId(), "Europe/London");
 287     }
 288 
 289     @Test
 290     public void test_of_string_Map_lookThrough() {
 291         Map<String, String> map = new HashMap<>();
 292         map.put("LONDON", "Europe/London");
 293         map.put("PARIS", "Europe/Paris");
 294         ZoneId test = ZoneId.of("Europe/Madrid", map);
 295         assertEquals(test.getId(), "Europe/Madrid");
 296     }
 297 
 298     @Test
 299     public void test_of_string_Map_emptyMap() {
 300         Map<String, String> map = new HashMap<>();
 301         ZoneId test = ZoneId.of("Europe/Madrid", map);
 302         assertEquals(test.getId(), "Europe/Madrid");
 303     }
 304 
 305     @Test(expectedExceptions=DateTimeException.class)
 306     public void test_of_string_Map_badFormat() {
 307         Map<String, String> map = new HashMap<>();
 308         ZoneId.of("Not known", map);
 309     }
 310 
 311     @Test(expectedExceptions=ZoneRulesException.class)
 312     public void test_of_string_Map_unknown() {
 313         Map<String, String> map = new HashMap<>();
 314         ZoneId.of("Unknown", map);
 315     }
 316 
 317     //-----------------------------------------------------------------------
 318     // regular factory
 319     //-----------------------------------------------------------------------
 320     @DataProvider(name="offsetBasedZero")
 321     Object[][] data_offsetBasedZero() {
 322         return new Object[][] {
 323                 {""}, {"0"},
 324                 {"+00"},{"+0000"},{"+00:00"},{"+000000"},{"+00:00:00"},
 325                 {"-00"},{"-0000"},{"-00:00"},{"-000000"},{"-00:00:00"},
 326         };
 327     }
 328 
 329     @Test(dataProvider="offsetBasedZero")
 330     public void factory_of_String_offsetBasedZero_noPrefix(String id) {
 331         if (id.length() > 0 && id.equals("0") == false) {
 332             ZoneId test = ZoneId.of(id);
 333             assertEquals(test, ZoneOffset.UTC);
 334         }
 335     }
 336 
 337     @Test(dataProvider="offsetBasedZero")
 338     public void factory_of_String_offsetBasedZero_prefixUTC(String id) {
 339         ZoneId test = ZoneId.of("UTC" + id);
 340         assertEquals(test, ZoneOffset.UTC);
 341     }
 342 
 343     @Test(dataProvider="offsetBasedZero")
 344     public void factory_of_String_offsetBasedZero_prefixGMT(String id) {
 345         ZoneId test = ZoneId.of("GMT" + id);
 346         assertEquals(test, ZoneOffset.UTC);
 347     }
 348 
 349     @Test(dataProvider="offsetBasedZero")
 350     public void factory_of_String_offsetBasedZero_prefixUT(String id) {
 351         ZoneId test = ZoneId.of("UT" + id);
 352         assertEquals(test, ZoneOffset.UTC);
 353     }
 354 
 355     @Test
 356     public void factory_of_String_offsetBasedZero_z() {
 357         ZoneId test = ZoneId.of("Z");
 358         assertEquals(test, ZoneOffset.UTC);
 359     }
 360 
 361     //-----------------------------------------------------------------------
 362     @DataProvider(name="offsetBasedValid")
 363     Object[][] data_offsetBasedValid() {
 364         return new Object[][] {

 365                 {"+0", "Z"},











 366                 {"+5", "+05:00"},
 367                 {"+01", "+01:00"},
 368                 {"+0100", "+01:00"},{"+01:00", "+01:00"},
 369                 {"+010000", "+01:00"},{"+01:00:00", "+01:00"},


 370                 {"+12", "+12:00"},
 371                 {"+1234", "+12:34"},{"+12:34", "+12:34"},
 372                 {"+123456", "+12:34:56"},{"+12:34:56", "+12:34:56"},


 373                 {"-02", "-02:00"},
 374                 {"-5", "-05:00"},
 375                 {"-0200", "-02:00"},{"-02:00", "-02:00"},
 376                 {"-020000", "-02:00"},{"-02:00:00", "-02:00"},


 377         };
 378     }
 379 
 380     @Test(dataProvider="offsetBasedValid")
 381     public void factory_of_String_offsetBasedValid_noPrefix(String input, String id) {
 382         ZoneId test = ZoneId.of(input);
 383         assertEquals(test.getId(), id);
 384         assertEquals(test, ZoneOffset.of(id));




 385     }
 386 
 387     @Test(dataProvider="offsetBasedValid")
 388     public void factory_of_String_offsetBasedValid_prefixUTC(String input, String id) {





































 389         ZoneId test = ZoneId.of("UTC" + input);
 390         assertEquals(test.getId(), id);
 391         assertEquals(test, ZoneOffset.of(id));




 392     }
 393 
 394     @Test(dataProvider="offsetBasedValid")
 395     public void factory_of_String_offsetBasedValid_prefixGMT(String input, String id) {
 396         ZoneId test = ZoneId.of("GMT" + input);
 397         assertEquals(test.getId(), id);
 398         assertEquals(test, ZoneOffset.of(id));




 399     }
 400 
 401     @Test(dataProvider="offsetBasedValid")
 402     public void factory_of_String_offsetBasedValid_prefixUT(String input, String id) {
 403         ZoneId test = ZoneId.of("UT" + input);
 404         assertEquals(test.getId(), id);
 405         assertEquals(test, ZoneOffset.of(id));


















































 406     }
 407 
 408     //-----------------------------------------------------------------------
 409     @DataProvider(name="offsetBasedInvalid")
 410     Object[][] data_offsetBasedInvalid() {
 411         return new Object[][] {
 412                 {"A"}, {"B"}, {"C"}, {"D"}, {"E"}, {"F"}, {"G"}, {"H"}, {"I"}, {"J"}, {"K"}, {"L"}, {"M"},
 413                 {"N"}, {"O"}, {"P"}, {"Q"}, {"R"}, {"S"}, {"T"}, {"U"}, {"V"}, {"W"}, {"X"}, {"Y"}, {"Z"},
 414                 {"+0:00"}, {"+00:0"}, {"+0:0"},
 415                 {"+000"}, {"+00000"},
 416                 {"+0:00:00"}, {"+00:0:00"}, {"+00:00:0"}, {"+0:0:0"}, {"+0:0:00"}, {"+00:0:0"}, {"+0:00:0"},
 417                 {"+01_00"}, {"+01;00"}, {"+01@00"}, {"+01:AA"},
 418                 {"+19"}, {"+19:00"}, {"+18:01"}, {"+18:00:01"}, {"+1801"}, {"+180001"},
 419                 {"-0:00"}, {"-00:0"}, {"-0:0"},
 420                 {"-000"}, {"-00000"},
 421                 {"-0:00:00"}, {"-00:0:00"}, {"-00:00:0"}, {"-0:0:0"}, {"-0:0:00"}, {"-00:0:0"}, {"-0:00:0"},
 422                 {"-19"}, {"-19:00"}, {"-18:01"}, {"-18:00:01"}, {"-1801"}, {"-180001"},
 423                 {"-01_00"}, {"-01;00"}, {"-01@00"}, {"-01:AA"},
 424                 {"@01:00"},






 425         };
 426     }
 427 
 428     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 429     public void factory_of_String_offsetBasedInvalid_noPrefix(String id) {
 430         if (id.equals("Z")) {
 431             throw new DateTimeException("Fake exception: Z alone is valid, not invalid");
 432         }
 433         ZoneId.of(id);
 434     }
 435 
 436     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 437     public void factory_of_String_offsetBasedInvalid_prefixUTC(String id) {
 438         ZoneId.of("UTC" + id);
 439     }
 440 
 441     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 442     public void factory_of_String_offsetBasedInvalid_prefixGMT(String id) {



 443         ZoneId.of("GMT" + id);
 444     }
 445 
 446     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 447     public void factory_of_String_offsetBasedInvalid_prefixUT(String id) {
 448         if (id.equals("C")) {
 449             throw new DateTimeException("Fake exception: UT + C = UTC, thus it is valid, not invalid");
 450         }
 451         ZoneId.of("UT" + id);
 452     }
 453 
 454     //-----------------------------------------------------------------------
 455     @DataProvider(name="regionBasedInvalid")
 456     Object[][] data_regionBasedInvalid() {
 457         // \u00ef is a random unicode character
 458         return new Object[][] {
 459                 {""}, {":"}, {"#"},
 460                 {"\u00ef"}, {"`"}, {"!"}, {"\""}, {"\u00ef"}, {"$"}, {"^"}, {"&"}, {"*"}, {"("}, {")"}, {"="},
 461                 {"\\"}, {"|"}, {","}, {"<"}, {">"}, {"?"}, {";"}, {"'"}, {"["}, {"]"}, {"{"}, {"}"},
 462                 {"\u00ef:A"}, {"`:A"}, {"!:A"}, {"\":A"}, {"\u00ef:A"}, {"$:A"}, {"^:A"}, {"&:A"}, {"*:A"}, {"(:A"}, {"):A"}, {"=:A"}, {"+:A"},
 463                 {"\\:A"}, {"|:A"}, {",:A"}, {"<:A"}, {">:A"}, {"?:A"}, {";:A"}, {"::A"}, {"':A"}, {"@:A"}, {"~:A"}, {"[:A"}, {"]:A"}, {"{:A"}, {"}:A"},
 464                 {"A:B#\u00ef"}, {"A:B#`"}, {"A:B#!"}, {"A:B#\""}, {"A:B#\u00ef"}, {"A:B#$"}, {"A:B#^"}, {"A:B#&"}, {"A:B#*"},
 465                 {"A:B#("}, {"A:B#)"}, {"A:B#="}, {"A:B#+"},
 466                 {"A:B#\\"}, {"A:B#|"}, {"A:B#,"}, {"A:B#<"}, {"A:B#>"}, {"A:B#?"}, {"A:B#;"}, {"A:B#:"},
 467                 {"A:B#'"}, {"A:B#@"}, {"A:B#~"}, {"A:B#["}, {"A:B#]"}, {"A:B#{"}, {"A:B#}"},
 468         };
 469     }
 470 
 471     @Test(dataProvider="regionBasedInvalid", expectedExceptions=DateTimeException.class)
 472     public void factory_of_String_regionBasedInvalid(String id) {
 473         ZoneId.of(id);
 474     }
 475 
 476     //-----------------------------------------------------------------------
 477     @Test
 478     public void factory_of_String_region_EuropeLondon() {
 479         ZoneId test = ZoneId.of("Europe/London");
 480         assertEquals(test.getId(), "Europe/London");
 481         assertEquals(test.getRules().isFixedOffset(), false);

 482     }
 483 
 484     //-----------------------------------------------------------------------
 485     @Test(expectedExceptions=NullPointerException.class)
 486     public void factory_of_String_null() {
 487         ZoneId.of(null);
 488     }
 489 
 490     @Test(expectedExceptions=DateTimeException.class)
 491     public void factory_of_String_badFormat() {
 492         ZoneId.of("Unknown rule");
 493     }
 494 
 495     @Test(expectedExceptions=ZoneRulesException.class)
 496     public void factory_of_String_unknown() {
 497         ZoneId.of("Unknown");
 498     }
 499 
 500     //-----------------------------------------------------------------------
 501     // from(TemporalAccessor)
 502     //-----------------------------------------------------------------------
 503     @Test
 504     public void factory_from_TemporalAccessor_zoneId() {
 505         TemporalAccessor mock = new TemporalAccessor() {
 506             @Override
 507             public boolean isSupported(TemporalField field) {
 508                 return false;
 509             }
 510             @Override
 511             public long getLong(TemporalField field) {
 512                 throw new DateTimeException("Mock");
 513             }
 514             @SuppressWarnings("unchecked")
 515             @Override
 516             public <R> R query(TemporalQuery<R> query) {
 517                 if (query == Queries.zoneId()) {
 518                     return (R) ZoneId.of("Europe/Paris");
 519                 }
 520                 return TemporalAccessor.super.query(query);
 521             }
 522         };
 523         assertEquals(ZoneId.from(mock),  ZoneId.of("Europe/Paris"));
 524     }
 525 
 526     @Test
 527     public void factory_from_TemporalAccessor_offset() {
 528         ZoneOffset offset = ZoneOffset.ofHours(1);
 529         assertEquals(ZoneId.from(offset), offset);
 530     }
 531 
 532     @Test(expectedExceptions=DateTimeException.class)
 533     public void factory_from_TemporalAccessor_invalid_noDerive() {
 534         ZoneId.from(LocalTime.of(12, 30));
 535     }
 536 
 537     @Test(expectedExceptions=NullPointerException.class)


 561 
 562     @Test
 563     public void test_equals_null() {
 564         assertEquals(ZoneId.of("Europe/London").equals(null), false);
 565     }
 566 
 567     @Test
 568     public void test_equals_notEqualWrongType() {
 569         assertEquals(ZoneId.of("Europe/London").equals("Europe/London"), false);
 570     }
 571 
 572     //-----------------------------------------------------------------------
 573     // toString()
 574     //-----------------------------------------------------------------------
 575     @DataProvider(name="toString")
 576     Object[][] data_toString() {
 577         return new Object[][] {
 578                 {"Europe/London", "Europe/London"},
 579                 {"Europe/Paris", "Europe/Paris"},
 580                 {"Europe/Berlin", "Europe/Berlin"},
 581                 {"UTC", "Z"},
 582                 {"UTC+01:00", "+01:00"},


 583         };
 584     }
 585 
 586     @Test(dataProvider="toString")
 587     public void test_toString(String id, String expected) {
 588         ZoneId test = ZoneId.of(id);
 589         assertEquals(test.toString(), expected);
 590     }
 591 
 592 }


  47  *
  48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  59  */
  60 package tck.java.time;
  61 
  62 import static org.testng.Assert.assertEquals;
  63 import static org.testng.Assert.fail;
  64 
  65 import java.io.ByteArrayInputStream;
  66 import java.io.ByteArrayOutputStream;

  67 import java.io.DataOutputStream;

  68 import java.io.ObjectInputStream;
  69 import java.io.ObjectStreamConstants;
  70 import java.lang.reflect.Field;
  71 import java.time.DateTimeException;
  72 import java.time.Instant;
  73 import java.time.LocalTime;
  74 import java.time.ZoneId;
  75 import java.time.ZoneOffset;
  76 import java.time.format.TextStyle;
  77 import java.time.temporal.TemporalAccessor;
  78 import java.time.temporal.TemporalField;
  79 import java.time.temporal.TemporalQuery;
  80 import java.time.zone.ZoneRulesException;
  81 import java.util.HashMap;
  82 import java.util.Locale;
  83 import java.util.Map;
  84 import java.util.Set;
  85 
  86 import org.testng.annotations.DataProvider;
  87 import org.testng.annotations.Test;
  88 
  89 /**
  90  * Test ZoneId.
  91  */
  92 @Test
  93 public class TCKZoneId extends AbstractTCKTest {
  94 
  95     //-----------------------------------------------------------------------
  96     @Test
  97     public void test_serialization() throws Exception {
  98         assertSerializable(ZoneId.of("Europe/London"));
  99         assertSerializable(ZoneId.of("America/Chicago"));
 100     }
 101 
 102     @Test
 103     public void test_serialization_format() throws Exception {
 104         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 105         try (DataOutputStream dos = new DataOutputStream(baos) ) {
 106             dos.writeByte(7);
 107             dos.writeUTF("Europe/London");
 108         }
 109         byte[] bytes = baos.toByteArray();
 110         assertSerializedBySer(ZoneId.of("Europe/London"), bytes);
 111     }
 112 
 113     @Test
 114     public void test_deserialization_lenient_characters() throws Exception {
 115         // an ID can be loaded without validation during deserialization
 116         String id = "QWERTYUIOPASDFGHJKLZXCVBNM~/._+-";
 117         ZoneId deser = deserialize(id);
 118         // getId, equals, hashCode, toString and normalized are OK
 119         assertEquals(deser.getId(), id);
 120         assertEquals(deser.toString(), id);
 121         assertEquals(deser, deser);
 122         assertEquals(deser.hashCode(), deser.hashCode());
 123         assertEquals(deser.normalized(), deser);
 124         // getting the rules is not
 125         try {
 126             deser.getRules();
 127             fail();
 128         } catch (ZoneRulesException ex) {
 129             // expected
 130         }
 131     }
 132 
 133     @Test(expectedExceptions=DateTimeException.class)
 134     public void test_deserialization_lenient_badCharacters() throws Exception {
 135         // an ID can be loaded without validation during deserialization
 136         // but there is a check to ensure the ID format is valid
 137         deserialize("|!?");
 138     }
 139 
 140     @Test(dataProvider="offsetBasedValid")
 141     public void test_deserialization_lenient_offsetNotAllowed_noPrefix(String input, String resolvedId) throws Exception {
 142         ZoneId deserialized = deserialize(input);
 143         assertEquals(deserialized, ZoneId.of(input));
 144         assertEquals(deserialized, ZoneId.of(resolvedId));
 145     }
 146 
 147     @Test(dataProvider="offsetBasedValidPrefix")
 148     public void test_deserialization_lenient_offsetNotAllowed_prefixUTC(String input, String resolvedId, String offsetId) throws Exception {
 149         ZoneId deserialized = deserialize("UTC" + input);
 150         assertEquals(deserialized, ZoneId.of("UTC" + input));
 151         assertEquals(deserialized, ZoneId.of("UTC" + resolvedId));
 152     }
 153 
 154     @Test(dataProvider="offsetBasedValidPrefix")
 155     public void test_deserialization_lenient_offsetNotAllowed_prefixGMT(String input, String resolvedId, String offsetId) throws Exception {
 156         ZoneId deserialized = deserialize("GMT" + input);
 157         assertEquals(deserialized, ZoneId.of("GMT" + input));
 158         assertEquals(deserialized, ZoneId.of("GMT" + resolvedId));
 159     }
 160 
 161     @Test(dataProvider="offsetBasedValidPrefix")
 162     public void test_deserialization_lenient_offsetNotAllowed_prefixUT(String input, String resolvedId, String offsetId) throws Exception {
 163         ZoneId deserialized = deserialize("UT" + input);
 164         assertEquals(deserialized, ZoneId.of("UT" + input));
 165         assertEquals(deserialized, ZoneId.of("UT" + resolvedId));
 166     }
 167 
 168     private ZoneId deserialize(String id) throws Exception {
 169         String serClass = ZoneId.class.getPackage().getName() + ".Ser";
 170         Class<?> serCls = Class.forName(serClass);
 171         Field field = serCls.getDeclaredField("serialVersionUID");
 172         field.setAccessible(true);
 173         long serVer = (Long) field.get(null);
 174         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 175         try (DataOutputStream dos = new DataOutputStream(baos)) {
 176             dos.writeShort(ObjectStreamConstants.STREAM_MAGIC);
 177             dos.writeShort(ObjectStreamConstants.STREAM_VERSION);
 178             dos.writeByte(ObjectStreamConstants.TC_OBJECT);
 179             dos.writeByte(ObjectStreamConstants.TC_CLASSDESC);
 180             dos.writeUTF(serClass);
 181             dos.writeLong(serVer);
 182             dos.writeByte(ObjectStreamConstants.SC_EXTERNALIZABLE | ObjectStreamConstants.SC_BLOCK_DATA);
 183             dos.writeShort(0);  // number of fields
 184             dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);  // end of classdesc
 185             dos.writeByte(ObjectStreamConstants.TC_NULL);  // no superclasses
 186             dos.writeByte(ObjectStreamConstants.TC_BLOCKDATA);
 187             dos.writeByte(1 + 2 + id.length());  // length of data (1 byte + 2 bytes UTF length + 32 bytes UTF)
 188             dos.writeByte(7);  // ZoneId
 189             dos.writeUTF(id);
 190             dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);  // end of blockdata
 191         }
 192         ZoneId deser = null;
 193         try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
 194             deser = (ZoneId) ois.readObject();
 195         }
 196         return deser;
 197     }
 198 
 199     //-----------------------------------------------------------------------
 200     // OLD_SHORT_IDS
 201     //-----------------------------------------------------------------------
 202     public void test_constant_OLD_IDS_PRE_2005() {
 203         Map<String, String> ids = ZoneId.OLD_SHORT_IDS;
 204         assertEquals(ids.get("EST"), "America/New_York");
 205         assertEquals(ids.get("MST"), "America/Denver");
 206         assertEquals(ids.get("HST"), "Pacific/Honolulu");
 207         assertEquals(ids.get("ACT"), "Australia/Darwin");
 208         assertEquals(ids.get("AET"), "Australia/Sydney");
 209         assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires");
 210         assertEquals(ids.get("ART"), "Africa/Cairo");
 211         assertEquals(ids.get("AST"), "America/Anchorage");
 212         assertEquals(ids.get("BET"), "America/Sao_Paulo");
 213         assertEquals(ids.get("BST"), "Asia/Dhaka");
 214         assertEquals(ids.get("CAT"), "Africa/Harare");
 215         assertEquals(ids.get("CNT"), "America/St_Johns");
 216         assertEquals(ids.get("CST"), "America/Chicago");
 217         assertEquals(ids.get("CTT"), "Asia/Shanghai");
 218         assertEquals(ids.get("EAT"), "Africa/Addis_Ababa");
 219         assertEquals(ids.get("ECT"), "Europe/Paris");
 220         assertEquals(ids.get("IET"), "America/Indiana/Indianapolis");
 221         assertEquals(ids.get("IST"), "Asia/Kolkata");
 222         assertEquals(ids.get("JST"), "Asia/Tokyo");
 223         assertEquals(ids.get("MIT"), "Pacific/Apia");
 224         assertEquals(ids.get("NET"), "Asia/Yerevan");
 225         assertEquals(ids.get("NST"), "Pacific/Auckland");
 226         assertEquals(ids.get("PLT"), "Asia/Karachi");
 227         assertEquals(ids.get("PNT"), "America/Phoenix");
 228         assertEquals(ids.get("PRT"), "America/Puerto_Rico");
 229         assertEquals(ids.get("PST"), "America/Los_Angeles");
 230         assertEquals(ids.get("SST"), "Pacific/Guadalcanal");
 231         assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh");
 232     }
 233 
 234     @Test(expectedExceptions=UnsupportedOperationException.class)
 235     public void test_constant_OLD_IDS_PRE_2005_immutable() {
 236         Map<String, String> ids = ZoneId.OLD_SHORT_IDS;
 237         ids.clear();
 238     }
 239 
 240     //-----------------------------------------------------------------------
 241     // SHORT_IDS
 242     //-----------------------------------------------------------------------
 243     public void test_constant_OLD_IDS_POST_2005() {
 244         Map<String, String> ids = ZoneId.SHORT_IDS;
 245         assertEquals(ids.get("EST"), "-05:00");
 246         assertEquals(ids.get("MST"), "-07:00");
 247         assertEquals(ids.get("HST"), "-10:00");
 248         assertEquals(ids.get("ACT"), "Australia/Darwin");
 249         assertEquals(ids.get("AET"), "Australia/Sydney");
 250         assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires");
 251         assertEquals(ids.get("ART"), "Africa/Cairo");
 252         assertEquals(ids.get("AST"), "America/Anchorage");
 253         assertEquals(ids.get("BET"), "America/Sao_Paulo");
 254         assertEquals(ids.get("BST"), "Asia/Dhaka");
 255         assertEquals(ids.get("CAT"), "Africa/Harare");
 256         assertEquals(ids.get("CNT"), "America/St_Johns");
 257         assertEquals(ids.get("CST"), "America/Chicago");
 258         assertEquals(ids.get("CTT"), "Asia/Shanghai");
 259         assertEquals(ids.get("EAT"), "Africa/Addis_Ababa");
 260         assertEquals(ids.get("ECT"), "Europe/Paris");
 261         assertEquals(ids.get("IET"), "America/Indiana/Indianapolis");
 262         assertEquals(ids.get("IST"), "Asia/Kolkata");
 263         assertEquals(ids.get("JST"), "Asia/Tokyo");
 264         assertEquals(ids.get("MIT"), "Pacific/Apia");
 265         assertEquals(ids.get("NET"), "Asia/Yerevan");
 266         assertEquals(ids.get("NST"), "Pacific/Auckland");
 267         assertEquals(ids.get("PLT"), "Asia/Karachi");
 268         assertEquals(ids.get("PNT"), "America/Phoenix");
 269         assertEquals(ids.get("PRT"), "America/Puerto_Rico");
 270         assertEquals(ids.get("PST"), "America/Los_Angeles");
 271         assertEquals(ids.get("SST"), "Pacific/Guadalcanal");
 272         assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh");
 273     }
 274 
 275     @Test(expectedExceptions=UnsupportedOperationException.class)
 276     public void test_constant_OLD_IDS_POST_2005_immutable() {
 277         Map<String, String> ids = ZoneId.SHORT_IDS;
 278         ids.clear();
 279     }
 280 
 281     //-----------------------------------------------------------------------
 282     // getAvailableZoneIds()
 283     //-----------------------------------------------------------------------
 284     @Test
 285     public void test_getAvailableGroupIds() {
 286         Set<String> zoneIds = ZoneId.getAvailableZoneIds();
 287         assertEquals(zoneIds.contains("Europe/London"), true);
 288         zoneIds.clear();
 289         assertEquals(zoneIds.size(), 0);
 290         Set<String> zoneIds2 = ZoneId.getAvailableZoneIds();
 291         assertEquals(zoneIds2.contains("Europe/London"), true);
 292     }
 293 
 294     //-----------------------------------------------------------------------
 295     // mapped factory
 296     //-----------------------------------------------------------------------
 297     @Test
 298     public void test_of_string_Map() {
 299         Map<String, String> map = new HashMap<>();
 300         map.put("LONDON", "Europe/London");
 301         map.put("PARIS", "Europe/Paris");
 302         ZoneId test = ZoneId.of("LONDON", map);
 303         assertEquals(test.getId(), "Europe/London");
 304     }
 305 
 306     @Test
 307     public void test_of_string_Map_lookThrough() {
 308         Map<String, String> map = new HashMap<>();
 309         map.put("LONDON", "Europe/London");
 310         map.put("PARIS", "Europe/Paris");
 311         ZoneId test = ZoneId.of("Europe/Madrid", map);
 312         assertEquals(test.getId(), "Europe/Madrid");
 313     }
 314 
 315     @Test
 316     public void test_of_string_Map_emptyMap() {
 317         Map<String, String> map = new HashMap<>();
 318         ZoneId test = ZoneId.of("Europe/Madrid", map);
 319         assertEquals(test.getId(), "Europe/Madrid");
 320     }
 321 
 322     @Test(expectedExceptions=DateTimeException.class)
 323     public void test_of_string_Map_badFormat() {
 324         Map<String, String> map = new HashMap<>();
 325         ZoneId.of("Not known", map);
 326     }
 327 
 328     @Test(expectedExceptions=ZoneRulesException.class)
 329     public void test_of_string_Map_unknown() {
 330         Map<String, String> map = new HashMap<>();
 331         ZoneId.of("Unknown", map);
 332     }
 333 
 334     //-----------------------------------------------------------------------
 335     // regular factory and .normalized()










































 336     //-----------------------------------------------------------------------
 337     @DataProvider(name="offsetBasedValid")
 338     Object[][] data_offsetBasedValid() {
 339         return new Object[][] {
 340                 {"Z", "Z"},
 341                 {"+0", "Z"},
 342                 {"-0", "Z"},
 343                 {"+00", "Z"},
 344                 {"+0000", "Z"},
 345                 {"+00:00", "Z"},
 346                 {"+000000", "Z"},
 347                 {"+00:00:00", "Z"},
 348                 {"-00", "Z"},
 349                 {"-0000", "Z"},
 350                 {"-00:00", "Z"},
 351                 {"-000000", "Z"},
 352                 {"-00:00:00", "Z"},
 353                 {"+5", "+05:00"},
 354                 {"+01", "+01:00"},
 355                 {"+0100", "+01:00"},
 356                 {"+01:00", "+01:00"},
 357                 {"+010000", "+01:00"},
 358                 {"+01:00:00", "+01:00"},
 359                 {"+12", "+12:00"},
 360                 {"+1234", "+12:34"},
 361                 {"+12:34", "+12:34"},
 362                 {"+123456", "+12:34:56"},
 363                 {"+12:34:56", "+12:34:56"},
 364                 {"-02", "-02:00"},
 365                 {"-5", "-05:00"},
 366                 {"-0200", "-02:00"},
 367                 {"-02:00", "-02:00"},
 368                 {"-020000", "-02:00"},
 369                 {"-02:00:00", "-02:00"},
 370         };
 371     }
 372 
 373     @Test(dataProvider="offsetBasedValid")
 374     public void factory_of_String_offsetBasedValid_noPrefix(String input, String id) {
 375         ZoneId test = ZoneId.of(input);
 376         assertEquals(test.getId(), id);
 377         assertEquals(test, ZoneOffset.of(id));
 378         assertEquals(test.normalized(), ZoneOffset.of(id));
 379         assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), id);
 380         assertEquals(test.getRules().isFixedOffset(), true);
 381         assertEquals(test.getRules().getOffset(Instant.EPOCH), ZoneOffset.of(id));
 382     }
 383 
 384     //-----------------------------------------------------------------------
 385     @DataProvider(name="offsetBasedValidPrefix")
 386     Object[][] data_offsetBasedValidPrefix() {
 387         return new Object[][] {
 388                 {"", "", "Z"},
 389                 {"+0", "", "Z"},
 390                 {"-0", "", "Z"},
 391                 {"+00", "", "Z"},
 392                 {"+0000", "", "Z"},
 393                 {"+00:00", "", "Z"},
 394                 {"+000000", "", "Z"},
 395                 {"+00:00:00", "", "Z"},
 396                 {"-00", "", "Z"},
 397                 {"-0000", "", "Z"},
 398                 {"-00:00", "", "Z"},
 399                 {"-000000", "", "Z"},
 400                 {"-00:00:00", "", "Z"},
 401                 {"+5", "+05:00", "+05:00"},
 402                 {"+01", "+01:00", "+01:00"},
 403                 {"+0100", "+01:00", "+01:00"},
 404                 {"+01:00", "+01:00", "+01:00"},
 405                 {"+010000", "+01:00", "+01:00"},
 406                 {"+01:00:00", "+01:00", "+01:00"},
 407                 {"+12", "+12:00", "+12:00"},
 408                 {"+1234", "+12:34", "+12:34"},
 409                 {"+12:34", "+12:34", "+12:34"},
 410                 {"+123456", "+12:34:56", "+12:34:56"},
 411                 {"+12:34:56", "+12:34:56", "+12:34:56"},
 412                 {"-02", "-02:00", "-02:00"},
 413                 {"-5", "-05:00", "-05:00"},
 414                 {"-0200", "-02:00", "-02:00"},
 415                 {"-02:00", "-02:00", "-02:00"},
 416                 {"-020000", "-02:00", "-02:00"},
 417                 {"-02:00:00", "-02:00", "-02:00"},
 418         };
 419     }
 420 
 421     @Test(dataProvider="offsetBasedValidPrefix")
 422     public void factory_of_String_offsetBasedValid_prefixUTC(String input, String id, String offsetId) {
 423         ZoneId test = ZoneId.of("UTC" + input);
 424         assertEquals(test.getId(), "UTC" + id);
 425         assertEquals(test.getRules(), ZoneOffset.of(offsetId).getRules());
 426         assertEquals(test.normalized(), ZoneOffset.of(offsetId));
 427         assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), displayName("UTC" + id));
 428         assertEquals(test.getRules().isFixedOffset(), true);
 429         assertEquals(test.getRules().getOffset(Instant.EPOCH), ZoneOffset.of(offsetId));
 430     }
 431 
 432     @Test(dataProvider="offsetBasedValidPrefix")
 433     public void factory_of_String_offsetBasedValid_prefixGMT(String input, String id, String offsetId) {
 434         ZoneId test = ZoneId.of("GMT" + input);
 435         assertEquals(test.getId(), "GMT" + id);
 436         assertEquals(test.getRules(), ZoneOffset.of(offsetId).getRules());
 437         assertEquals(test.normalized(), ZoneOffset.of(offsetId));
 438         assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), displayName("GMT" + id));
 439         assertEquals(test.getRules().isFixedOffset(), true);
 440         assertEquals(test.getRules().getOffset(Instant.EPOCH), ZoneOffset.of(offsetId));
 441     }
 442 
 443     @Test(dataProvider="offsetBasedValidPrefix")
 444     public void factory_of_String_offsetBasedValid_prefixUT(String input, String id, String offsetId) {
 445         ZoneId test = ZoneId.of("UT" + input);
 446         assertEquals(test.getId(), "UT" + id);
 447         assertEquals(test.getRules(), ZoneOffset.of(offsetId).getRules());
 448         assertEquals(test.normalized(), ZoneOffset.of(offsetId));
 449         assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), displayName("UT" + id));
 450         assertEquals(test.getRules().isFixedOffset(), true);
 451         assertEquals(test.getRules().getOffset(Instant.EPOCH), ZoneOffset.of(offsetId));
 452     }
 453 
 454     private String displayName(String id) {
 455         if (id.equals("GMT")) {
 456             return "Greenwich Mean Time";
 457         }
 458         if (id.equals("GMT0")) {
 459             return "Greenwich Mean Time";
 460         }
 461         if (id.equals("UTC")) {
 462             return "Coordinated Universal Time";
 463         }
 464         return id;
 465     }
 466 
 467     //-----------------------------------------------------------------------
 468     @DataProvider(name="offsetBasedValidOther")
 469     Object[][] data_offsetBasedValidOther() {
 470         return new Object[][] {
 471                 {"GMT", "Z"},
 472                 {"GMT0", "Z"},
 473                 {"UCT", "Z"},
 474                 {"Greenwich", "Z"},
 475                 {"Universal", "Z"},
 476                 {"Zulu", "Z"},
 477                 {"Etc/GMT", "Z"},
 478                 {"Etc/GMT+0", "Z"},
 479                 {"Etc/GMT+1", "-01:00"},
 480                 {"Etc/GMT-1", "+01:00"},
 481                 {"Etc/GMT+9", "-09:00"},
 482                 {"Etc/GMT-9", "+09:00"},
 483                 {"Etc/GMT0", "Z"},
 484                 {"Etc/UCT", "Z"},
 485                 {"Etc/UTC", "Z"},
 486                 {"Etc/Greenwich", "Z"},
 487                 {"Etc/Universal", "Z"},
 488                 {"Etc/Zulu", "Z"},
 489         };
 490     }
 491 
 492     @Test(dataProvider="offsetBasedValidOther")
 493     public void factory_of_String_offsetBasedValidOther(String input, String offsetId) {
 494         ZoneId test = ZoneId.of(input);
 495         assertEquals(test.getId(), input);
 496         assertEquals(test.getRules(), ZoneOffset.of(offsetId).getRules());
 497         assertEquals(test.normalized(), ZoneOffset.of(offsetId));
 498     }
 499 
 500     //-----------------------------------------------------------------------
 501     @DataProvider(name="offsetBasedInvalid")
 502     Object[][] data_offsetBasedInvalid() {
 503         return new Object[][] {
 504                 {"A"}, {"B"}, {"C"}, {"D"}, {"E"}, {"F"}, {"G"}, {"H"}, {"I"}, {"J"}, {"K"}, {"L"}, {"M"},
 505                 {"N"}, {"O"}, {"P"}, {"Q"}, {"R"}, {"S"}, {"T"}, {"U"}, {"V"}, {"W"}, {"X"}, {"Y"}, {"Z"},
 506                 {"+0:00"}, {"+00:0"}, {"+0:0"},
 507                 {"+000"}, {"+00000"},
 508                 {"+0:00:00"}, {"+00:0:00"}, {"+00:00:0"}, {"+0:0:0"}, {"+0:0:00"}, {"+00:0:0"}, {"+0:00:0"},
 509                 {"+01_00"}, {"+01;00"}, {"+01@00"}, {"+01:AA"},
 510                 {"+19"}, {"+19:00"}, {"+18:01"}, {"+18:00:01"}, {"+1801"}, {"+180001"},
 511                 {"-0:00"}, {"-00:0"}, {"-0:0"},
 512                 {"-000"}, {"-00000"},
 513                 {"-0:00:00"}, {"-00:0:00"}, {"-00:00:0"}, {"-0:0:0"}, {"-0:0:00"}, {"-00:0:0"}, {"-0:00:0"},
 514                 {"-19"}, {"-19:00"}, {"-18:01"}, {"-18:00:01"}, {"-1801"}, {"-180001"},
 515                 {"-01_00"}, {"-01;00"}, {"-01@00"}, {"-01:AA"},
 516                 {"@01:00"},
 517                 {"0"},
 518                 {"UT0"},
 519                 {"UTZ"},
 520                 {"UTC0"},
 521                 {"UTCZ"},
 522                 {"GMTZ"},  // GMT0 is valid in ZoneRulesProvider
 523         };
 524     }
 525 
 526     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 527     public void factory_of_String_offsetBasedInvalid_noPrefix(String id) {
 528         if (id.equals("Z")) {
 529             throw new DateTimeException("Fake exception: Z alone is valid, not invalid");
 530         }
 531         ZoneId.of(id);
 532     }
 533 
 534     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 535     public void factory_of_String_offsetBasedInvalid_prefixUTC(String id) {
 536         ZoneId.of("UTC" + id);
 537     }
 538 
 539     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 540     public void factory_of_String_offsetBasedInvalid_prefixGMT(String id) {
 541         if (id.equals("0")) {
 542             throw new DateTimeException("Fake exception: GMT0 is valid, not invalid");
 543         }
 544         ZoneId.of("GMT" + id);
 545     }
 546 
 547     @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class)
 548     public void factory_of_String_offsetBasedInvalid_prefixUT(String id) {
 549         if (id.equals("C")) {
 550             throw new DateTimeException("Fake exception: UT + C = UTC, thus it is valid, not invalid");
 551         }
 552         ZoneId.of("UT" + id);
 553     }
 554 
 555     //-----------------------------------------------------------------------
 556     @DataProvider(name="regionBasedInvalid")
 557     Object[][] data_regionBasedInvalid() {
 558         // \u00ef is a random unicode character
 559         return new Object[][] {
 560                 {""}, {":"}, {"#"},
 561                 {"\u00ef"}, {"`"}, {"!"}, {"\""}, {"\u00ef"}, {"$"}, {"^"}, {"&"}, {"*"}, {"("}, {")"}, {"="},
 562                 {"\\"}, {"|"}, {","}, {"<"}, {">"}, {"?"}, {";"}, {"'"}, {"["}, {"]"}, {"{"}, {"}"},
 563                 {"\u00ef:A"}, {"`:A"}, {"!:A"}, {"\":A"}, {"\u00ef:A"}, {"$:A"}, {"^:A"}, {"&:A"}, {"*:A"}, {"(:A"}, {"):A"}, {"=:A"}, {"+:A"},
 564                 {"\\:A"}, {"|:A"}, {",:A"}, {"<:A"}, {">:A"}, {"?:A"}, {";:A"}, {"::A"}, {"':A"}, {"@:A"}, {"~:A"}, {"[:A"}, {"]:A"}, {"{:A"}, {"}:A"},
 565                 {"A:B#\u00ef"}, {"A:B#`"}, {"A:B#!"}, {"A:B#\""}, {"A:B#\u00ef"}, {"A:B#$"}, {"A:B#^"}, {"A:B#&"}, {"A:B#*"},
 566                 {"A:B#("}, {"A:B#)"}, {"A:B#="}, {"A:B#+"},
 567                 {"A:B#\\"}, {"A:B#|"}, {"A:B#,"}, {"A:B#<"}, {"A:B#>"}, {"A:B#?"}, {"A:B#;"}, {"A:B#:"},
 568                 {"A:B#'"}, {"A:B#@"}, {"A:B#~"}, {"A:B#["}, {"A:B#]"}, {"A:B#{"}, {"A:B#}"},
 569         };
 570     }
 571 
 572     @Test(dataProvider="regionBasedInvalid", expectedExceptions=DateTimeException.class)
 573     public void factory_of_String_regionBasedInvalid(String id) {
 574         ZoneId.of(id);
 575     }
 576 
 577     //-----------------------------------------------------------------------
 578     @Test
 579     public void factory_of_String_region_EuropeLondon() {
 580         ZoneId test = ZoneId.of("Europe/London");
 581         assertEquals(test.getId(), "Europe/London");
 582         assertEquals(test.getRules().isFixedOffset(), false);
 583         assertEquals(test.normalized(), test);
 584     }
 585 
 586     //-----------------------------------------------------------------------
 587     @Test(expectedExceptions=NullPointerException.class)
 588     public void factory_of_String_null() {
 589         ZoneId.of(null);
 590     }
 591 
 592     @Test(expectedExceptions=DateTimeException.class)
 593     public void factory_of_String_badFormat() {
 594         ZoneId.of("Unknown rule");
 595     }
 596 
 597     @Test(expectedExceptions=ZoneRulesException.class)
 598     public void factory_of_String_unknown() {
 599         ZoneId.of("Unknown");
 600     }
 601 
 602     //-----------------------------------------------------------------------
 603     // from(TemporalAccessor)
 604     //-----------------------------------------------------------------------
 605     @Test
 606     public void factory_from_TemporalAccessor_zoneId() {
 607         TemporalAccessor mock = new TemporalAccessor() {
 608             @Override
 609             public boolean isSupported(TemporalField field) {
 610                 return false;
 611             }
 612             @Override
 613             public long getLong(TemporalField field) {
 614                 throw new DateTimeException("Mock");
 615             }
 616             @SuppressWarnings("unchecked")
 617             @Override
 618             public <R> R query(TemporalQuery<R> query) {
 619                 if (query == TemporalQuery.zoneId()) {
 620                     return (R) ZoneId.of("Europe/Paris");
 621                 }
 622                 return TemporalAccessor.super.query(query);
 623             }
 624         };
 625         assertEquals(ZoneId.from(mock),  ZoneId.of("Europe/Paris"));
 626     }
 627 
 628     @Test
 629     public void factory_from_TemporalAccessor_offset() {
 630         ZoneOffset offset = ZoneOffset.ofHours(1);
 631         assertEquals(ZoneId.from(offset), offset);
 632     }
 633 
 634     @Test(expectedExceptions=DateTimeException.class)
 635     public void factory_from_TemporalAccessor_invalid_noDerive() {
 636         ZoneId.from(LocalTime.of(12, 30));
 637     }
 638 
 639     @Test(expectedExceptions=NullPointerException.class)


 663 
 664     @Test
 665     public void test_equals_null() {
 666         assertEquals(ZoneId.of("Europe/London").equals(null), false);
 667     }
 668 
 669     @Test
 670     public void test_equals_notEqualWrongType() {
 671         assertEquals(ZoneId.of("Europe/London").equals("Europe/London"), false);
 672     }
 673 
 674     //-----------------------------------------------------------------------
 675     // toString()
 676     //-----------------------------------------------------------------------
 677     @DataProvider(name="toString")
 678     Object[][] data_toString() {
 679         return new Object[][] {
 680                 {"Europe/London", "Europe/London"},
 681                 {"Europe/Paris", "Europe/Paris"},
 682                 {"Europe/Berlin", "Europe/Berlin"},
 683                 {"Z", "Z"},
 684                 {"+01:00", "+01:00"},
 685                 {"UTC", "UTC"},
 686                 {"UTC+01:00", "UTC+01:00"},
 687         };
 688     }
 689 
 690     @Test(dataProvider="toString")
 691     public void test_toString(String id, String expected) {
 692         ZoneId test = ZoneId.of(id);
 693         assertEquals(test.toString(), expected);
 694     }
 695 
 696 }