1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2008-2014, International Business Machines Corporation and * 7 * others. All Rights Reserved. * 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.impl; 11 12 import java.io.IOException; 13 import java.io.ObjectInputStream; 14 import java.lang.reflect.InvocationTargetException; 15 import java.lang.reflect.Method; 16 import java.util.Date; 17 import java.util.TreeSet; 18 19 import ohos.global.icu.util.TimeZone; 20 21 /** 22 * JavaTimeZone inherits ohos.global.icu.util.TimeZone and wraps java.util.TimeZone. 23 * We used to have JDKTimeZone which wrapped Java TimeZone and used it as primary 24 * TimeZone implementation until ICU4J 3.4.1. This class works exactly like 25 * JDKTimeZone and allows ICU users who use ICU4J and JDK date/time/calendar 26 * services in mix to maintain only JDK timezone rules. 27 * 28 * This TimeZone subclass is returned by the TimeZone factory method getTimeZone(String) 29 * when the default timezone type in TimeZone class is TimeZone.TIMEZONE_JDK. 30 * @hide exposed on OHOS 31 */ 32 public class JavaTimeZone extends TimeZone { 33 34 private static final long serialVersionUID = 6977448185543929364L; 35 36 private static final TreeSet<String> AVAILABLESET; 37 38 private java.util.TimeZone javatz; 39 private transient java.util.Calendar javacal; 40 private static Method mObservesDaylightTime; 41 42 static { 43 AVAILABLESET = new TreeSet<>(); 44 String[] availableIds = java.util.TimeZone.getAvailableIDs(); 45 for (int i = 0; i < availableIds.length; i++) { 46 AVAILABLESET.add(availableIds[i]); 47 } 48 49 try { 50 mObservesDaylightTime = java.util.TimeZone.class.getMethod("observesDaylightTime", (Class[]) null); 51 } catch (NoSuchMethodException e) { 52 // Android API level 21..23 53 } catch (SecurityException e) { 54 // not visible 55 } 56 } 57 58 /** 59 * Constructs a JavaTimeZone with the default Java TimeZone 60 */ JavaTimeZone()61 public JavaTimeZone() { 62 this(java.util.TimeZone.getDefault(), null); 63 } 64 65 /** 66 * Constructs a JavaTimeZone with the specified Java TimeZone and ID. 67 * @param jtz the Java TimeZone 68 * @param id the ID of the zone. if null, the zone ID is initialized 69 * by the given Java TimeZone's ID. 70 */ JavaTimeZone(java.util.TimeZone jtz, String id)71 public JavaTimeZone(java.util.TimeZone jtz, String id) { 72 if (id == null) { 73 id = jtz.getID(); 74 } 75 javatz = jtz; 76 setID(id); 77 javacal = new java.util.GregorianCalendar(javatz); 78 } 79 80 /** 81 * Creates an instance of JavaTimeZone with the given timezone ID. 82 * @param id A timezone ID, either a system ID or a custom ID. 83 * @return An instance of JavaTimeZone for the given ID, or null 84 * when the ID cannot be understood. 85 */ createTimeZone(String id)86 public static JavaTimeZone createTimeZone(String id) { 87 java.util.TimeZone jtz = null; 88 89 if (AVAILABLESET.contains(id)) { 90 jtz = java.util.TimeZone.getTimeZone(id); 91 } 92 93 if (jtz == null) { 94 // Use ICU's canonical ID mapping 95 boolean[] isSystemID = new boolean[1]; 96 String canonicalID = TimeZone.getCanonicalID(id, isSystemID); 97 if (isSystemID[0] && AVAILABLESET.contains(canonicalID)) { 98 jtz = java.util.TimeZone.getTimeZone(canonicalID); 99 } 100 } 101 102 if (jtz == null) { 103 return null; 104 } 105 106 return new JavaTimeZone(jtz, id); 107 } 108 109 /* (non-Javadoc) 110 * @see ohos.global.icu.util.TimeZone#getOffset(int, int, int, int, int, int) 111 */ 112 @Override getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds)113 public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) { 114 return javatz.getOffset(era, year, month, day, dayOfWeek, milliseconds); 115 } 116 117 /* (non-Javadoc) 118 * @see ohos.global.icu.util.TimeZone#getOffset(long, boolean, int[]) 119 */ 120 @Override getOffset(long date, boolean local, int[] offsets)121 public void getOffset(long date, boolean local, int[] offsets) { 122 synchronized (javacal) { 123 if (local) { 124 int fields[] = new int[6]; 125 Grego.timeToFields(date, fields); 126 int hour, min, sec, mil; 127 int tmp = fields[5]; 128 mil = tmp % 1000; 129 tmp /= 1000; 130 sec = tmp % 60; 131 tmp /= 60; 132 min = tmp % 60; 133 hour = tmp / 60; 134 javacal.clear(); 135 javacal.set(fields[0], fields[1], fields[2], hour, min, sec); 136 javacal.set(java.util.Calendar.MILLISECOND, mil); 137 138 int doy1, hour1, min1, sec1, mil1; 139 doy1 = javacal.get(java.util.Calendar.DAY_OF_YEAR); 140 hour1 = javacal.get(java.util.Calendar.HOUR_OF_DAY); 141 min1 = javacal.get(java.util.Calendar.MINUTE); 142 sec1 = javacal.get(java.util.Calendar.SECOND); 143 mil1 = javacal.get(java.util.Calendar.MILLISECOND); 144 145 if (fields[4] != doy1 || hour != hour1 || min != min1 || sec != sec1 || mil != mil1) { 146 // Calendar field(s) were changed due to the adjustment for non-existing time 147 // Note: This code does not support non-existing local time at year boundary properly. 148 // But, it should work fine for real timezones. 149 int dayDelta = Math.abs(doy1 - fields[4]) > 1 ? 1 : doy1 - fields[4]; 150 int delta = ((((dayDelta * 24) + hour1 - hour) * 60 + min1 - min) * 60 + sec1 - sec) * 1000 + mil1 - mil; 151 152 // In this case, we use the offsets before the transition 153 javacal.setTimeInMillis(javacal.getTimeInMillis() - delta - 1); 154 } 155 } else { 156 javacal.setTimeInMillis(date); 157 } 158 offsets[0] = javacal.get(java.util.Calendar.ZONE_OFFSET); 159 offsets[1] = javacal.get(java.util.Calendar.DST_OFFSET); 160 } 161 } 162 163 /* (non-Javadoc) 164 * @see ohos.global.icu.util.TimeZone#getRawOffset() 165 */ 166 @Override getRawOffset()167 public int getRawOffset() { 168 return javatz.getRawOffset(); 169 } 170 171 /* (non-Javadoc) 172 * @see ohos.global.icu.util.TimeZone#inDaylightTime(java.util.Date) 173 */ 174 @Override inDaylightTime(Date date)175 public boolean inDaylightTime(Date date) { 176 return javatz.inDaylightTime(date); 177 } 178 179 /* (non-Javadoc) 180 * @see ohos.global.icu.util.TimeZone#setRawOffset(int) 181 */ 182 @Override setRawOffset(int offsetMillis)183 public void setRawOffset(int offsetMillis) { 184 if (isFrozen()) { 185 throw new UnsupportedOperationException("Attempt to modify a frozen JavaTimeZone instance."); 186 } 187 javatz.setRawOffset(offsetMillis); 188 } 189 190 /* (non-Javadoc) 191 * @see ohos.global.icu.util.TimeZone#useDaylightTime() 192 */ 193 @Override useDaylightTime()194 public boolean useDaylightTime() { 195 return javatz.useDaylightTime(); 196 } 197 198 /* (non-Javadoc) 199 * @see ohos.global.icu.util.TimeZone#observesDaylightTime() 200 */ 201 @Override observesDaylightTime()202 public boolean observesDaylightTime() { 203 if (mObservesDaylightTime != null) { 204 // Java 7+, Android API level 24+ 205 // https://developer.android.com/reference/java/util/TimeZone 206 try { 207 return (Boolean)mObservesDaylightTime.invoke(javatz, (Object[]) null); 208 } catch (IllegalAccessException e) { 209 } catch (IllegalArgumentException e) { 210 } catch (InvocationTargetException e) { 211 } 212 } 213 return super.observesDaylightTime(); 214 } 215 216 /* (non-Javadoc) 217 * @see ohos.global.icu.util.TimeZone#getDSTSavings() 218 */ 219 @Override getDSTSavings()220 public int getDSTSavings() { 221 return javatz.getDSTSavings(); 222 } 223 unwrap()224 public java.util.TimeZone unwrap() { 225 return javatz; 226 } 227 228 /* (non-Javadoc) 229 * @see ohos.global.icu.util.TimeZone#clone() 230 */ 231 @Override clone()232 public Object clone() { 233 if (isFrozen()) { 234 return this; 235 } 236 return cloneAsThawed(); 237 } 238 239 /* (non-Javadoc) 240 * @see ohos.global.icu.util.TimeZone#hashCode() 241 */ 242 @Override hashCode()243 public int hashCode() { 244 return super.hashCode() + javatz.hashCode(); 245 } 246 readObject(ObjectInputStream s)247 private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { 248 s.defaultReadObject(); 249 javacal = new java.util.GregorianCalendar(javatz); 250 } 251 252 // Freezable stuffs 253 private transient volatile boolean isFrozen = false; 254 255 /* (non-Javadoc) 256 * @see ohos.global.icu.util.TimeZone#isFrozen() 257 */ 258 @Override isFrozen()259 public boolean isFrozen() { 260 return isFrozen; 261 } 262 263 /* (non-Javadoc) 264 * @see ohos.global.icu.util.TimeZone#freeze() 265 */ 266 @Override freeze()267 public TimeZone freeze() { 268 isFrozen = true; 269 return this; 270 } 271 272 /* (non-Javadoc) 273 * @see ohos.global.icu.util.TimeZone#cloneAsThawed() 274 */ 275 @Override cloneAsThawed()276 public TimeZone cloneAsThawed() { 277 JavaTimeZone tz = (JavaTimeZone)super.cloneAsThawed(); 278 tz.javatz = (java.util.TimeZone)javatz.clone(); 279 tz.javacal = new java.util.GregorianCalendar(javatz); // easier than synchronized javacal.clone() 280 tz.isFrozen = false; 281 return tz; 282 } 283 284 } 285