Skip to content

Commit

Permalink
#524 DateTimeZone.forID() remains the same in mapping time zone ids. …
Browse files Browse the repository at this point in the history
…DateTimeZone.forIDNoMapping() will return an object with an id exactly as provided
  • Loading branch information
Thomas Wolkenstein committed Oct 13, 2021
1 parent d2f1bb0 commit 2bd707b
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 5 deletions.
32 changes: 31 additions & 1 deletion src/main/java/org/joda/time/DateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,36 @@ public static DateTimeZone forID(String id) {
throw new IllegalArgumentException("The datetime zone id '" + id + "' is not recognised");
}

/**
* Same as {@link #forID(String) forID} but does not mapping of deprecated time zones.
*
* @param id the ID of the datetime zone, null means default
* @return the DateTimeZone object for the ID
* @throws IllegalArgumentException if the ID is not recognised
*/
public static DateTimeZone forIDNoMapping(String id) {
if (id == null) {
return getDefault();
}
if (id.equals("UTC")) {
return DateTimeZone.UTC;
}
DateTimeZone zone = getProvider().getZoneNoMapping(id);
if (zone != null) {
return zone;
}
if (id.startsWith("+") || id.startsWith("-")) {
int offset = parseOffset(id);
if (offset == 0L) {
return DateTimeZone.UTC;
} else {
id = printOffset(offset);
return fixedOffsetZone(id, offset);
}
}
throw new IllegalArgumentException("The datetime zone id '" + id + "' is not recognised");
}

/**
* Gets a time zone instance for the specified offset to UTC in hours.
* This method assumes standard length hours.
Expand Down Expand Up @@ -1261,7 +1291,7 @@ private void readObject(ObjectInputStream in) throws IOException {
}

private Object readResolve() throws ObjectStreamException {
return forID(iID);
return forIDNoMapping(iID);
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/joda/time/tz/Provider.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ public interface Provider {
*/
DateTimeZone getZone(String id);

/**
* Same as {@link #getZone(String) getZone} but does no mapping of deprecated time zones
*
* @param id String id
* @return null if not found
*/
DateTimeZone getZoneNoMapping(String id);

/**
* Returns an unmodifiable set of ids. All providers must at least
* support id "UTC".
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/joda/time/tz/UTCProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ public DateTimeZone getZone(String id) {
return null;
}

/**
* Returns {@link DateTimeZone#UTC UTC} for <code>"UTC"</code>, null
* otherwise.
*/
public DateTimeZone getZoneNoMapping(String id) {
if ("UTC".equalsIgnoreCase(id)) {
return DateTimeZone.UTC;
}
return null;
}

/**
* Returns a singleton collection containing only <code>"UTC"</code>.
*/
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/org/joda/time/tz/ZoneInfoProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,45 @@ public DateTimeZone getZone(String id) {
return null;
}

if (obj instanceof Entry) {
// If this point is reached, mapping must link to another.
@SuppressWarnings("unchecked")
Entry<String, SoftReference<DateTimeZone>> entry = (Entry<String, SoftReference<DateTimeZone>>) obj;
return getZone(entry.getKey());
} else if (obj instanceof SoftReference<?>) {
@SuppressWarnings("unchecked")
SoftReference<DateTimeZone> ref = (SoftReference<DateTimeZone>) obj;
DateTimeZone tz = ref.get();
if (tz != null) {
return tz;
}
// Reference cleared; load data again.
return loadZoneData(id, id);
} else if (id.equals(obj)) {
// Load zone data for the first time.
return loadZoneData(id, id);
}

// If this point is reached, mapping must link to another.
return getZone((String) obj);
}

/**
* Returns a DateTimeZone object for the the id, that includes the exact id as provided, no mapping of deprecated zone ids is done as in {@code getZone}.
*
* @param id the id to load
* @return the loaded zone
*/
public DateTimeZone getZoneNoMapping(String id) {
if (id == null) {
return null;
}

Object obj = iZoneInfoMap.get(id);
if (obj == null) {
return null;
}

if (obj instanceof Entry) {
// If this point is reached, mapping must link to another.
@SuppressWarnings("unchecked")
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/org/joda/time/TestDateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,9 @@ public Set getAvailableIDs() {
public DateTimeZone getZone(String id) {
return null;
}
public DateTimeZone getZoneNoMapping(String id) {
return null;
}
}
static class MockEmptyIDSProvider implements Provider {
public Set getAvailableIDs() {
Expand All @@ -610,6 +613,9 @@ public Set getAvailableIDs() {
public DateTimeZone getZone(String id) {
return null;
}
public DateTimeZone getZoneNoMapping(String id) {
return null;
}
}
static class MockNoUTCProvider implements Provider {
public Set getAvailableIDs() {
Expand All @@ -620,6 +626,9 @@ public Set getAvailableIDs() {
public DateTimeZone getZone(String id) {
return null;
}
public DateTimeZone getZoneNoMapping(String id) {
return null;
}
}
static class MockBadUTCProvider implements Provider {
public Set getAvailableIDs() {
Expand All @@ -631,6 +640,9 @@ public Set getAvailableIDs() {
public DateTimeZone getZone(String id) {
return null;
}
public DateTimeZone getZoneNoMapping(String id) {
return null;
}
}
static class MockOKProvider implements Provider {
public Set getAvailableIDs() {
Expand All @@ -642,6 +654,9 @@ public Set getAvailableIDs() {
public DateTimeZone getZone(String id) {
return DateTimeZone.UTC;
}
public DateTimeZone getZoneNoMapping(String id) {
return DateTimeZone.UTC;
}
}

//-----------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ public void test_printParseZoneGMT() {
DateTimeFormatter f = bld.toFormatter();

DateTime dt = new DateTime(2007, 3, 4, 12, 30, 0, DateTimeZone.forID("GMT"));
assertEquals("2007-03-04 12:30 GMT", f.print(dt));
assertEquals("2007-03-04 12:30 Etc/GMT", f.print(dt));
assertEquals(dt, f.parseDateTime("2007-03-04 12:30 GMT"));
}

Expand All @@ -501,7 +501,7 @@ public void test_printParseZoneGMT_suffix() {
DateTimeFormatter f = bld.toFormatter();

DateTime dt = new DateTime(2007, 3, 4, 12, 30, 0, DateTimeZone.forID("GMT"));
assertEquals("2007-03-04 12:30 GMT]", f.print(dt));
assertEquals("2007-03-04 12:30 Etc/GMT]", f.print(dt));
assertEquals(dt, f.parseDateTime("2007-03-04 12:30 GMT]"));
}

Expand Down
60 changes: 58 additions & 2 deletions src/test/java/org/joda/time/tz/TestCachedDateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@
*/
package org.joda.time.tz;

import org.joda.time.DateTimeZone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.time.ZoneId;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;

import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.joda.time.DateTimeZone;

/**
* Test cases for FixedDateTimeZone.
*
Expand Down Expand Up @@ -55,6 +61,56 @@ protected void tearDown() throws Exception {
DateTimeZone.setDefault(originalDateTimeZone);
}

public void testRangoonDateTimeZone_MappingToNewId_Asia_Yangon() throws Exception {
DateTimeZone zoneOld = DateTimeZone.forID("Asia/Rangoon");
assertEquals(zoneOld.getID(), "Asia/Yangon");

DateTimeZone zoneNew = DateTimeZone.forID("Asia/Yangon");
assertEquals(zoneNew.getID(), "Asia/Yangon");
}

public void testRangoonDateTimeZone_NoMapping() throws Exception {
DateTimeZone zoneOld = DateTimeZone.forIDNoMapping("Asia/Rangoon");
assertEquals(zoneOld.getID(), "Asia/Rangoon");

DateTimeZone zoneNew = DateTimeZone.forID("Asia/Yangon");
assertEquals(zoneNew.getID(), "Asia/Yangon");
}

public void testRangoonJavaUtilTimeZone() throws Exception {
TimeZone zone = TimeZone.getTimeZone("Asia/Rangoon");
assertEquals(zone.getID(), "Asia/Rangoon");

TimeZone zoneNew = TimeZone.getTimeZone("Asia/Yangon");
assertEquals(zoneNew.getID(), "Asia/Yangon");
}

public void testRangoonJavaTimeZoneId() throws Exception {
ZoneId zone = ZoneId.of("Asia/Rangoon");
assertEquals(zone.getId(), "Asia/Rangoon");

ZoneId zoneNew = ZoneId.of("Asia/Yangon");
assertEquals(zoneNew.getId(), "Asia/Yangon");
}

public void testRangoonCachingForMappingCode() throws Exception {
DateTimeZone zoneYangon = DateTimeZone.forID("Asia/Rangoon");
DateTimeZone zoneRangoon = DateTimeZone.forIDNoMapping("Asia/Rangoon");
Field field_iZoneInfoMap = ZoneInfoProvider.class.getDeclaredField("iZoneInfoMap");
field_iZoneInfoMap.setAccessible(true);
Map<String, Object> iZoneInfoMap = (Map<String, Object>) field_iZoneInfoMap.get(DateTimeZone.getProvider());
Entry<String, SoftReference<DateTimeZone>> entryRangoon = (Entry<String, SoftReference<DateTimeZone>>) iZoneInfoMap.get("Asia/Rangoon");
assertEquals("Asia/Yangon", entryRangoon.getKey());
SoftReference<DateTimeZone> entryYangon = (SoftReference<DateTimeZone>) iZoneInfoMap.get("Asia/Yangon");
entryRangoon.getValue().clear();
entryYangon.clear();

assertEquals(DateTimeZone.forID("Asia/Rangoon"), zoneYangon);
assertEquals(DateTimeZone.forIDNoMapping("Asia/Rangoon"), zoneRangoon);
assertEquals(DateTimeZone.forID("Asia/Rangoon").getID(), "Asia/Yangon");
assertEquals(DateTimeZone.forIDNoMapping("Asia/Rangoon").getID(), "Asia/Rangoon");
}

public void test_caching() throws Exception {
CachedDateTimeZone zone1 = CachedDateTimeZone.forZone(DateTimeZone.forID("Europe/Paris"));
CachedDateTimeZone zone2 = CachedDateTimeZone.forZone(DateTimeZone.forID("Europe/Paris"));
Expand Down

0 comments on commit 2bd707b

Please sign in to comment.