net.sf.saxon.expr.number.NamedTimeZone Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of saxon-he Show documentation
Show all versions of saxon-he Show documentation
An OSGi bundle for Saxon-HE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Saxonica Limited.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package net.sf.saxon.expr.number;
import net.sf.saxon.tree.util.FastStringBuffer;
import net.sf.saxon.value.DateTimeValue;
import java.util.*;
/**
* This class attempts to identify a timezone name, given the date (including the time zone offset)
* and the country. The process is heuristic: sometimes there is more than one timezone that matches
* this information, sometimes there is none, but the class simply does its best. This is in support
* of the XSLT format-date() function.
*/
public class NamedTimeZone {
static HashMap> idForCountry = new HashMap>(50);
/**
* Register a timezone in use in a particular country. Note that some countries use multiple
* time zones
* @param country the two-character code for the country
* @param zoneId the Olsen timezone name for the timezone
*/
static void tz(String country, String zoneId) {
List list = idForCountry.get(country);
if (list == null) {
list = new ArrayList(4);
}
list.add(zoneId);
idForCountry.put(country, list);
}
static {
// The table starts with countries that use multiple timezones, then proceeds in alphabetical order
tz("us", "America/New_York");
tz("us", "America/Chicago");
tz("us", "America/Denver");
tz("us", "America/Los_Angeles");
tz("us", "America/Anchorage");
tz("us", "America/Halifax");
tz("ca", "Canada/Pacific");
tz("ca", "Canada/Mountain");
tz("ca", "Canada/Central");
tz("ca", "Canada/Eastern");
tz("ca", "Canada/Atlantic");
tz("au", "Australia/Sydney");
tz("au", "Australia/Darwin");
tz("au", "Australia/Perth");
tz("ru", "Europe/Moscow");
tz("ru", "Europe/Samara");
tz("ru", "Asia/Yekaterinburg");
tz("ru", "Asia/Novosibirsk");
tz("ru", "Asia/Krasnoyarsk");
tz("ru", "Asia/Irkutsk");
tz("ru", "Asia/Chita");
tz("ru", "Asia/Vladivostok");
tz("an", "Europe/Andorra");
tz("ae", "Asia/Abu_Dhabi");
tz("af", "Asia/Kabul");
tz("al", "Europe/Tirana");
tz("am", "Asia/Yerevan");
tz("ao", "Africa/Luanda");
tz("ar", "America/Buenos_Aires");
tz("as", "Pacific/Samoa");
tz("at", "Europe/Vienna");
tz("aw", "America/Aruba");
tz("az", "Asia/Baku");
tz("ba", "Europe/Sarajevo");
tz("bb", "America/Barbados");
tz("bd", "Asia/Dhaka");
tz("be", "Europe/Brussels");
tz("bf", "Africa/Ouagadougou");
tz("bg", "Europe/Sofia");
tz("bh", "Asia/Bahrain");
tz("bi", "Africa/Bujumbura");
tz("bm", "Atlantic/Bermuda");
tz("bn", "Asia/Brunei");
tz("bo", "America/La_Paz");
tz("br", "America/Sao_Paulo");
tz("bs", "America/Nassau");
tz("bw", "Gaborone");
tz("by", "Europe/Minsk");
tz("bz", "America/Belize");
tz("cd", "Africa/Kinshasa");
tz("ch", "Europe/Zurich");
tz("ci", "Africa/Abidjan");
tz("cl", "America/Santiago");
tz("cn", "Asia/Shanghai");
tz("co", "America/Bogota");
tz("cr", "America/Costa_Rica");
tz("cu", "America/Cuba");
tz("cv", "Atlantic/Cape_Verde");
tz("cy", "Asia/Nicosia");
tz("cz", "Europe/Prague");
tz("de", "Europe/Berlin");
tz("dj", "Africa/Djibouti");
tz("dk", "Europe/Copenhagen");
tz("do", "America/Santo_Domingo");
tz("dz", "Africa/Algiers");
tz("ec", "America/Quito");
tz("ee", "Europe/Tallinn");
tz("eg", "Africa/Cairo");
tz("er", "Africa/Asmara");
tz("es", "Europe/Madrid");
tz("fi", "Europe/Helsinki");
tz("fj", "Pacific/Fiji");
tz("fk", "America/Stanley");
tz("fr", "Europe/Paris");
tz("ga", "Africa/Libreville");
tz("gb", "Europe/London");
tz("gd", "America/Grenada");
tz("ge", "Asia/Tbilisi");
tz("gh", "Africa/Accra");
tz("gm", "Africa/Banjul");
tz("gn", "Africa/Conakry");
tz("gr", "Europe/Athens");
tz("gy", "America/Guyana");
tz("hk", "Asia/Hong_Kong");
tz("hn", "America/Tegucigalpa");
tz("hr", "Europe/Zagreb");
tz("ht", "America/Port-au-Prince");
tz("hu", "Europe/Budapest");
tz("id", "Asia/Jakarta");
tz("ie", "Europe/Dublin");
tz("il", "Asia/Tel_Aviv");
tz("in", "Asia/Calcutta");
tz("iq", "Asia/Baghdad");
tz("ir", "Asia/Tehran");
tz("is", "Atlantic/Reykjavik");
tz("it", "Europe/Rome");
tz("jm", "America/Jamaica");
tz("jo", "Asia/Amman");
tz("jp", "Asia/Tokyo");
tz("ke", "Africa/Nairobi");
tz("kg", "Asia/Bishkek");
tz("kh", "Asia/Phnom_Penh");
tz("kp", "Asia/Pyongyang");
tz("kr", "Asia/Seoul");
tz("kw", "Asia/Kuwait");
tz("lb", "Asia/Beirut");
tz("li", "Europe/Liechtenstein");
tz("lk", "Asia/Colombo");
tz("lr", "Africa/Monrovia");
tz("ls", "Africa/Maseru");
tz("lt", "Europe/Vilnius");
tz("lu", "Europe/Luxembourg");
tz("lv", "Europe/Riga");
tz("ly", "Africa/Tripoli");
tz("ma", "Africa/Rabat");
tz("mc", "Europe/Monaco");
tz("md", "Europe/Chisinau");
tz("mg", "Indian/Antananarivo");
tz("mk", "Europe/Skopje");
tz("ml", "Africa/Bamako");
tz("mm", "Asia/Rangoon");
tz("mn", "Asia/Ulaanbaatar");
tz("mo", "Asia/Macao");
tz("mq", "America/Martinique");
tz("mt", "Europe/Malta");
tz("mu", "Indian/Mauritius");
tz("mv", "Indian/Maldives");
tz("mw", "Africa/Lilongwe");
tz("mx", "America/Mexico_City");
tz("my", "Asia/Kuala_Lumpur");
tz("na", "Africa/Windhoek");
tz("ne", "Africa/Niamey");
tz("ng", "Africa/Lagos");
tz("ni", "America/Managua");
tz("nl", "Europe/Amsterdam");
tz("no", "Europe/Oslo");
tz("np", "Asia/Kathmandu");
tz("nz", "Pacific/Aukland");
tz("om", "Asia/Muscat");
tz("pa", "America/Panama");
tz("pe", "America/Lima");
tz("pg", "Pacific/Port_Moresby");
tz("ph", "Asia/Manila");
tz("pk", "Asia/Karachi");
tz("pl", "Europe/Warsaw");
tz("pr", "America/Puerto_Rico");
tz("pt", "Europe/Lisbon");
tz("py", "America/Asuncion");
tz("qa", "Asia/Qatar");
tz("ro", "Europe/Bucharest");
tz("rs", "Europe/Belgrade");
tz("rw", "Africa/Kigali");
tz("sa", "Asia/Riyadh");
tz("sd", "Africa/Khartoum");
tz("se", "Europe/Stockholm");
tz("sg", "Asia/Singapore");
tz("si", "Europe/Ljubljana");
tz("sk", "Europe/Bratislava");
tz("sl", "Africa/Freetown");
tz("so", "Africa/Mogadishu");
tz("sr", "America/Paramaribo");
tz("sv", "America/El_Salvador");
tz("sy", "Asia/Damascus");
tz("sz", "Africa/Mbabane");
tz("td", "Africa/Ndjamena");
tz("tg", "Africa/Lome");
tz("th", "Asia/Bangkok");
tz("tj", "Asia/Dushanbe");
tz("tm", "Asia/Ashgabat");
tz("tn", "Africa/Tunis");
tz("to", "Pacific/Tongatapu");
tz("tr", "Asia/Istanbul");
tz("tw", "Asia/Taipei");
tz("tz", "Africa/Dar_es_Salaam");
tz("ua", "Europe/Kiev");
tz("ug", "Africa/Kampala");
tz("uk", "Europe/London");
tz("uy", "America/Montevideo");
tz("uz", "Asia/Tashkent");
tz("ve", "America/Caracas");
tz("vn", "Asia/Hanoi");
tz("za", "Africa/Johannesburg");
tz("zm", "Africa/Lusaka");
tz("zw", "Africa/Harare");
}
/**
* Try to identify a timezone name corresponding to a given date (including time zone)
* and a given country. Note that this takes account of Java's calendar of daylight savings time
* changes in different countries. The returned value is the convenional short timezone name, for example
* PDT for Pacific Daylight Time
* @param date the dateTimeValue, including timezone
* @param country the two-letter ISO country code
* @return the short timezone name if a timezone with the given time displacement is in use in the country
* in question (on the appropriate date, if known). Otherwise, the formatted (numeric) timezone offset. If
* the dateTimeValue supplied has no timezone, return a zero-length string.
*/
public static String getTimeZoneNameForDate(DateTimeValue date, /*@Nullable*/ String country) {
if (!date.hasTimezone()) {
return "";
}
if (country == null) {
return formatTimeZoneOffset(date);
}
List possibleIds = idForCountry.get(country.toLowerCase());
String exampleId;
if (possibleIds == null) {
return formatTimeZoneOffset(date);
} else {
exampleId = possibleIds.get(0);
}
TimeZone exampleZone = TimeZone.getTimeZone(exampleId);
Date javaDate;
try {
javaDate = date.getCalendar().getTime();
} catch (IllegalArgumentException e) {
// this happens with timezones that are allowed in XPath but not in Java, especially on JDK 1.4
return formatTimeZoneOffset(date);
}
boolean inSummerTime = exampleZone.inDaylightTime(javaDate);
int tzMinutes = date.getTimezoneInMinutes();
for (int i=0; i possibleIds = idForCountry.get(country.toLowerCase());
String exampleId;
if (possibleIds == null) {
return formatTimeZoneOffset(date);
} else {
exampleId = possibleIds.get(0);
}
TimeZone exampleZone = TimeZone.getTimeZone(exampleId);
Date javaDate = date.getCalendar().getTime();
boolean inSummerTime = exampleZone.inDaylightTime(javaDate);
int tzMinutes = date.getTimezoneInMinutes();
for (int i=0; i possibleIds = idForCountry.get(region.toLowerCase());
if (possibleIds == null) {
return null;
} else {
olsenName = possibleIds.get(0);
}
} else {
olsenName = region;
}
TimeZone zone = TimeZone.getTimeZone(olsenName);
return Boolean.valueOf(zone.inDaylightTime(date.getCalendar().getTime()));
}
/**
* Get the civil time offset to be made to a given date/time in a given
* civil timezone. For example, if the timezone is America/New_York, the civil time
* offset will be -5 hours (= 5 x 3600000 ms) during the winter and -4 hours
* (=4 x 3600000 ms) during the summer
* @param date the date/time in question. If this has no timezone, it is assumed
* to be in GMT.
* @param olsenName the Olsen name of the timezone, for example Europe/Lisbon
* @return the civil time offset, in milliseconds, to be applied to the given
* date/time
*/
public static int civilTimeOffset(DateTimeValue date, String olsenName) {
TimeZone zone = TimeZone.getTimeZone(olsenName);
return zone.getOffset(date.getCalendar().getTime().getTime());
}
/**
* Main method for testing
* @param args first argument: a dateTime value
* second argument: a country code
*/
// public static void main(String[] args) {
// System.err.println(NamedTimeZone.getTimeZoneNameForDate((DateTimeValue)DateTimeValue.makeDateTimeValue(args[0]), args[1]));
// }
/**
* Main method to generate the list of timezone names known to Java
* @param args not used
*/
// public static void main(String[] args) {
// String[] ids = TimeZone.getAvailableIDs(/* -5*60*60*1000 */);
// for (int i=0; i