All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.expr.number.NamedTimeZone Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy