Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not resolve most zone IDs #676

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/main/java/org/joda/time/DateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -1198,8 +1198,19 @@ public long adjustOffset(long instant, boolean earlierOrLater) {
*
* @return the closest matching TimeZone object
*/
public java.util.TimeZone toTimeZone() {
return java.util.TimeZone.getTimeZone(iID);
public TimeZone toTimeZone() {
TimeZone converted = TimeZone.getTimeZone(iID);
// handle recent renames (since 2019) where the JDK may not have been updated yet
if (converted.getID().equals("GMT")) {
if (iID.equals("Europe/Kyiv")) {
converted = TimeZone.getTimeZone("Europe/Kiev");
} else if (iID.equals("Pacific/Kanton")) {
converted = TimeZone.getTimeZone("Pacific/Enderbury");
} else if (iID.equals("America/Nuuk")) {
converted = TimeZone.getTimeZone("America/Godthab");
}
}
return converted;
}

/**
Expand Down
148 changes: 144 additions & 4 deletions src/main/java/org/joda/time/tz/ZoneInfoCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -61,6 +62,143 @@
* @since 1.0
*/
public class ZoneInfoCompiler {

private static final List<String> ANCIENT_IDS = Arrays.asList(
// changed in 1993
"Australia/ACT",
"Australia/LHI",
"Australia/NSW",
"Australia/North",
"Australia/Queensland",
"Australia/South",
"Australia/Tasmania",
"Australia/Victoria",
"Australia/West",
"Australia/Yancowinna",
"Brazil/Acre",
"Brazil/DeNoronha",
"Brazil/East",
"Brazil/West",
"Canada/Atlantic",
"Canada/Central",
"Canada/Eastern",
"Canada/Mountain",
"Canada/Newfoundland",
"Canada/Pacific",
"Canada/Saskatchewan",
"Canada/Yukon",
"Chile/Continental",
"Chile/EasterIsland",
"Cuba",
"Egypt",
"Eire",
"Etc/GMT+0",
"Etc/GMT-0",
"Etc/GMT0",
"Etc/Greenwich",
"Etc/UCT",
"Etc/Universal",
"Etc/Zulu",
"GB",
"GB-Eire",
"GMT+0",
"GMT-0",
"GMT0",
"GMT",
"Greenwich",
"Hongkong",
"Iceland",
"Iran",
"Israel",
"Jamaica",
"Japan",
"Kwajalein",
"Libya",
"Mexico/BajaNorte",
"Mexico/BajaSur",
"Mexico/General",
"NZ",
"NZ-CHAT",
"Navajo",
"PRC",
"Poland",
"Portugal",
"ROC",
"ROK",
"Singapore",
"Turkey",
"UCT",
"US/Alaska",
"US/Aleutian",
"US/Arizona",
"US/Central",
"US/East-Indiana",
"US/Eastern",
"US/Hawaii",
"US/Indiana-Starke",
"US/Michigan",
"US/Mountain",
"US/Pacific",
"US/Samoa",
"UCT",
"UTC",
"Universal",
"W-SU",
"Zulu",
// removed
"US/Pacific-New");

// allowing these to be "good links"
// all these follow the modern naming convention that avoids country names
// Australia/Canberra
// America/Buenos_Aires
// America/Catamarca
// America/Cordoba
// America/Indianapolis
// America/Jujuy
// America/Knox_IN
// America/Louisville
// America/Mendoza
// America/Virgin
// Pacific/Samoa
// Africa/Asmera
// Africa/Timbuktu
// America/Argentina/ComodRivadavia
// America/Atka
// America/Coral_Harbour
// America/Ensenada
// America/Fort_Wayne
// America/Godthab
// America/Montreal
// America/Porto_Acre
// America/Rosario
// America/Santa_Isabel
// America/Shiprock
// Antarctica/South_Pole
// Asia/Ashkhabad
// Asia/Calcutta
// Asia/Chongqing
// Asia/Chungking
// Asia/Dacca
// Asia/Harbin
// Asia/Kashgar
// Asia/Katmandu
// Asia/Macao
// Asia/Rangoon
// Asia/Saigon
// Asia/Tel_Aviv
// Asia/Thimbu
// Asia/Ujung_Pandang
// Asia/Ulan_Bator
// Atlantic/Faeroe
// Atlantic/Jan_Mayen
// Europe/Belfast
// Europe/Tiraspol
// Pacific/Johnston
// Pacific/Ponape
// Pacific/Truk
// Pacific/Yap

static DateTimeOfYear cStartOfYear;

static Chronology cLenientISO;
Expand Down Expand Up @@ -353,15 +491,17 @@ static boolean test(String id, DateTimeZone tz) {
public ZoneInfoCompiler() {
iRuleSets = new HashMap<String, RuleSet>();
iZones = new ArrayList<Zone>();
iGoodLinks = new ArrayList<String>();
iBackLinks = new ArrayList<String>();
iGoodLinks = new ArrayList<String>(); // list of pairs, (good, bad)*
iBackLinks = new ArrayList<String>(); // list of pairs, (good, bad)*
}

/**
* Returns a map of ids to DateTimeZones.
*
* @param outputDir optional directory to write compiled data files to
* @param sources optional list of source files to parse
* @return the map of ID to zone
* @throws IOException if an IO error occurs
*/
public Map<String, DateTimeZone> compile(File outputDir, File[] sources) throws IOException {
if (sources != null) {
Expand Down Expand Up @@ -430,7 +570,7 @@ public Map<String, DateTimeZone> compile(File outputDir, File[] sources) throws
}
}

// store "back" links as aliases (where name is permanently mapped
// store "back" links as aliases (where name is permanently mapped)
for (int pass = 0; pass < 2; pass++) {
for (int i = 0; i < iBackLinks.size(); i += 2) {
String id = iBackLinks.get(i);
Expand Down Expand Up @@ -551,7 +691,7 @@ public void parseDataFile(BufferedReader in, boolean backward) throws IOExceptio
// links in "backward" are deprecated names
// links in other files should be kept
// special case a few to try to repair terrible damage to tzdb
if (backward || alias.equals("US/Pacific-New") || alias.startsWith("Etc/") || alias.equals("GMT")) {
if (alias.startsWith("Etc/") || ANCIENT_IDS.contains(alias)) {
iBackLinks.add(real);
iBackLinks.add(alias);
} else {
Expand Down
25 changes: 13 additions & 12 deletions src/test/java/org/joda/time/TestDateTimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -1052,9 +1052,19 @@ public void testIsLocalDateTimeGap_NewYork() {

//-----------------------------------------------------------------------
public void testToTimeZone() {
DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
TimeZone tz = zone.toTimeZone();
assertEquals("Europe/Paris", tz.getID());
assertEquals("Europe/Paris", DateTimeZone.forID("Europe/Paris").toTimeZone().getID());

String kanton = DateTimeZone.forID("Pacific/Kanton").toTimeZone().getID();
assertTrue(kanton.equals("Pacific/Kanton") || kanton.equals("Pacific/Enderbury"));
System.out.println(kanton);

String gothab = DateTimeZone.forID("America/Nuuk").toTimeZone().getID();
assertTrue(gothab.equals("America/Nuuk") || gothab.equals("America/Godthab"));
System.out.println(gothab);

String kyiv = DateTimeZone.forID("Europe/Kyiv").toTimeZone().getID();
assertTrue(kyiv.equals("Europe/Kyiv") || kyiv.equals("Europe/Kiev"));
System.out.println(kyiv);
}

//-----------------------------------------------------------------------
Expand Down Expand Up @@ -1323,13 +1333,4 @@ public void testPatchedNameKeysGazaHistoric() throws Exception {
assertEquals(false, str1.equals(str2));
}

//-----------------------------------------------------------------------
public void testIdNotAutoMapped_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");
}

}
62 changes: 58 additions & 4 deletions src/test/java/org/joda/time/tz/TestCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@
package org.joda.time.tz;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringTokenizer;
import java.nio.charset.Charset;
import java.util.NoSuchElementException;

import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.StringTokenizer;

import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.DateTimeZone;
import org.joda.time.tz.ZoneInfoCompiler.DateTimeOfYear;

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

/**
* Test cases for ZoneInfoCompiler.
*
Expand Down Expand Up @@ -136,6 +139,57 @@ public void testCompile() throws Exception {
TestBuilder.testReverseTransitions(tz, TestBuilder.AMERICA_LOS_ANGELES_DATA);
}

public void testCompileAllTzdb() throws Exception {
String[] files = {
"src/main/java/org/joda/time/tz/src/africa",
"src/main/java/org/joda/time/tz/src/antarctica",
"src/main/java/org/joda/time/tz/src/asia",
"src/main/java/org/joda/time/tz/src/australasia",
"src/main/java/org/joda/time/tz/src/europe",
"src/main/java/org/joda/time/tz/src/northamerica",
"src/main/java/org/joda/time/tz/src/southamerica",
"src/main/java/org/joda/time/tz/src/etcetera",
"src/main/java/org/joda/time/tz/src/backward",
};
StringBuilder buf = new StringBuilder();
for (int i = 0; i < files.length; i++) {
byte[] bytes = readAllBytes(files[i]);
buf.append(new String(bytes, Charset.forName("UTF-8")));
}

Provider provider = compileAndLoad(buf.toString());

// check some links
assertEquals("Europe/Kiev", provider.getZone("Europe/Kiev").getID());
assertEquals("Europe/Kyiv", provider.getZone("Europe/Kyiv").getID());
assertEquals("Asia/Rangoon", provider.getZone("Asia/Rangoon").getID());
assertEquals("Asia/Yangon", provider.getZone("Asia/Yangon").getID());
assertEquals("Europe/Lisbon", provider.getZone("Portugal").getID());
assertEquals("Africa/Tripoli", provider.getZone("Libya").getID());
assertEquals("Etc/GMT", provider.getZone("GMT").getID());
assertEquals("Etc/GMT", provider.getZone("Etc/GMT").getID());
assertEquals("Etc/GMT", provider.getZone("Etc/GMT0").getID());
assertEquals("Etc/GMT+1", provider.getZone("Etc/GMT+1").getID());
assertEquals("UTC", provider.getZone("UTC").getID());
assertEquals("Etc/UTC", provider.getZone("Etc/UTC").getID());
assertEquals("Australia/Currie", provider.getZone("Australia/Currie").getID());
}

private static byte[] readAllBytes(String fileName) throws IOException {
InputStream in = new FileInputStream(fileName);
try {
byte[] b = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int c;
while ((c = in.read(b)) != -1) {
out.write(b, 0, c);
}
return out.toByteArray();
} finally {
in.close();
}
}

public void testCompileOnBrokenTimeZoneFile() throws Exception {
try {
Provider provider = compileAndLoad(BROKEN_TIMEZONE_FILE);
Expand Down