com.ibm.icu.impl.JavaTimeZone Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of icu4j Show documentation
Show all versions of icu4j Show documentation
International Component for Unicode for Java (ICU4J) is a mature, widely used Java library
providing Unicode and Globalization support
/*
*******************************************************************************
* Copyright (C) 2008-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.TreeSet;
import com.ibm.icu.util.TimeZone;
/**
* JavaTimeZone inherits com.ibm.icu.util.TimeZone and wraps java.util.TimeZone.
* We used to have JDKTimeZone which wrapped Java TimeZone and used it as primary
* TimeZone implementation until ICU4J 3.4.1. This class works exactly like
* JDKTimeZone and allows ICU users who use ICU4J and JDK date/time/calendar
* services in mix to maintain only JDK timezone rules.
*
* This TimeZone subclass is returned by the TimeZone factory method getTimeZone(String)
* when the default timezone type in TimeZone class is TimeZone.TIMEZONE_JDK.
*/
public class JavaTimeZone extends TimeZone {
private static final long serialVersionUID = 6977448185543929364L;
private static final TreeSet AVAILABLESET;
private java.util.TimeZone javatz;
private transient java.util.Calendar javacal;
private static Method mObservesDaylightTime;
static {
AVAILABLESET = new TreeSet();
String[] availableIds = java.util.TimeZone.getAvailableIDs();
for (int i = 0; i < availableIds.length; i++) {
AVAILABLESET.add(availableIds[i]);
}
try {
mObservesDaylightTime = java.util.TimeZone.class.getMethod("observesDaylightTime", (Class[]) null);
} catch (NoSuchMethodException e) {
// Java 6 or older
} catch (SecurityException e) {
// not visible
}
}
/**
* Constructs a JavaTimeZone with the default Java TimeZone
*/
public JavaTimeZone() {
this(java.util.TimeZone.getDefault(), null);
}
/**
* Constructs a JavaTimeZone with the specified Java TimeZone and ID.
* @param jtz the Java TimeZone
* @param id the ID of the zone. if null, the zone ID is initialized
* by the given Java TimeZone's ID.
*/
public JavaTimeZone(java.util.TimeZone jtz, String id) {
if (id == null) {
id = jtz.getID();
}
javatz = jtz;
setID(id);
javacal = new java.util.GregorianCalendar(javatz);
}
/**
* Creates an instance of JavaTimeZone with the given timezone ID.
* @param id A timezone ID, either a system ID or a custom ID.
* @return An instance of JavaTimeZone for the given ID, or null
* when the ID cannot be understood.
*/
public static JavaTimeZone createTimeZone(String id) {
java.util.TimeZone jtz = null;
if (AVAILABLESET.contains(id)) {
jtz = java.util.TimeZone.getTimeZone(id);
}
if (jtz == null) {
// Use ICU's canonical ID mapping
boolean[] isSystemID = new boolean[1];
String canonicalID = TimeZone.getCanonicalID(id, isSystemID);
if (isSystemID[0] && AVAILABLESET.contains(canonicalID)) {
jtz = java.util.TimeZone.getTimeZone(canonicalID);
}
}
if (jtz == null) {
return null;
}
return new JavaTimeZone(jtz, id);
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#getOffset(int, int, int, int, int, int)
*/
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
return javatz.getOffset(era, year, month, day, dayOfWeek, milliseconds);
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#getOffset(long, boolean, int[])
*/
public void getOffset(long date, boolean local, int[] offsets) {
synchronized (javacal) {
if (local) {
int fields[] = new int[6];
Grego.timeToFields(date, fields);
int hour, min, sec, mil;
int tmp = fields[5];
mil = tmp % 1000;
tmp /= 1000;
sec = tmp % 60;
tmp /= 60;
min = tmp % 60;
hour = tmp / 60;
javacal.clear();
javacal.set(fields[0], fields[1], fields[2], hour, min, sec);
javacal.set(java.util.Calendar.MILLISECOND, mil);
int doy1, hour1, min1, sec1, mil1;
doy1 = javacal.get(java.util.Calendar.DAY_OF_YEAR);
hour1 = javacal.get(java.util.Calendar.HOUR_OF_DAY);
min1 = javacal.get(java.util.Calendar.MINUTE);
sec1 = javacal.get(java.util.Calendar.SECOND);
mil1 = javacal.get(java.util.Calendar.MILLISECOND);
if (fields[4] != doy1 || hour != hour1 || min != min1 || sec != sec1 || mil != mil1) {
// Calendar field(s) were changed due to the adjustment for non-existing time
// Note: This code does not support non-existing local time at year boundary properly.
// But, it should work fine for real timezones.
int dayDelta = Math.abs(doy1 - fields[4]) > 1 ? 1 : doy1 - fields[4];
int delta = ((((dayDelta * 24) + hour1 - hour) * 60 + min1 - min) * 60 + sec1 - sec) * 1000 + mil1 - mil;
// In this case, we use the offsets before the transition
javacal.setTimeInMillis(javacal.getTimeInMillis() - delta - 1);
}
} else {
javacal.setTimeInMillis(date);
}
offsets[0] = javacal.get(java.util.Calendar.ZONE_OFFSET);
offsets[1] = javacal.get(java.util.Calendar.DST_OFFSET);
}
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#getRawOffset()
*/
public int getRawOffset() {
return javatz.getRawOffset();
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#inDaylightTime(java.util.Date)
*/
public boolean inDaylightTime(Date date) {
return javatz.inDaylightTime(date);
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#setRawOffset(int)
*/
public void setRawOffset(int offsetMillis) {
if (isFrozen()) {
throw new UnsupportedOperationException("Attempt to modify a frozen JavaTimeZone instance.");
}
javatz.setRawOffset(offsetMillis);
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#useDaylightTime()
*/
public boolean useDaylightTime() {
return javatz.useDaylightTime();
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#observesDaylightTime()
*/
public boolean observesDaylightTime() {
if (mObservesDaylightTime != null) {
// Java 7+
try {
return (Boolean)mObservesDaylightTime.invoke(javatz, (Object[]) null);
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
}
return super.observesDaylightTime();
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#getDSTSavings()
*/
public int getDSTSavings() {
return javatz.getDSTSavings();
}
public java.util.TimeZone unwrap() {
return javatz;
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#clone()
*/
public Object clone() {
if (isFrozen()) {
return this;
}
return cloneAsThawed();
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#hashCode()
*/
public int hashCode() {
return super.hashCode() + javatz.hashCode();
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
javacal = new java.util.GregorianCalendar(javatz);
}
// Freezable stuffs
private transient boolean isFrozen = false;
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#isFrozen()
*/
public boolean isFrozen() {
return isFrozen;
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#freeze()
*/
public TimeZone freeze() {
isFrozen = true;
return this;
}
/* (non-Javadoc)
* @see com.ibm.icu.util.TimeZone#cloneAsThawed()
*/
public TimeZone cloneAsThawed() {
JavaTimeZone tz = (JavaTimeZone)super.cloneAsThawed();
tz.javatz = (java.util.TimeZone)javatz.clone();
tz.javacal = (java.util.GregorianCalendar)javacal.clone();
tz.isFrozen = false;
return tz;
}
}