1 16 package org.joda.time.tz; 17 18 import org.joda.time.DateTimeZone; 19 20 30 public class CachedDateTimeZone extends DateTimeZone { 31 32 private static final long serialVersionUID = 5472298452022250685L; 33 34 private static final int cInfoCacheMask; 35 36 static { 37 Integer i; 38 try { 39 i = Integer.getInteger("org.joda.time.tz.CachedDateTimeZone.size"); 40 } catch (SecurityException e) { 41 i = null; 42 } 43 44 int cacheSize; 45 if (i == null) { 46 cacheSize = 512; } else { 50 cacheSize = i.intValue(); 51 cacheSize--; 53 int shift = 0; 54 while (cacheSize > 0) { 55 shift++; 56 cacheSize >>= 1; 57 } 58 cacheSize = 1 << shift; 59 } 60 61 cInfoCacheMask = cacheSize - 1; 62 } 63 64 67 public static CachedDateTimeZone forZone(DateTimeZone zone) { 68 if (zone instanceof CachedDateTimeZone) { 69 return (CachedDateTimeZone)zone; 70 } 71 return new CachedDateTimeZone(zone); 72 } 73 74 81 82 private final DateTimeZone iZone; 83 84 private transient Info[] iInfoCache; 85 86 private CachedDateTimeZone(DateTimeZone zone) { 87 super(zone.getID()); 88 iZone = zone; 89 iInfoCache = new Info[cInfoCacheMask + 1]; 90 } 91 92 private void readObject(java.io.ObjectInputStream in) 93 throws java.io.IOException , ClassNotFoundException 94 { 95 in.defaultReadObject(); 96 iInfoCache = new Info[cInfoCacheMask + 1]; 97 } 98 99 102 public DateTimeZone getUncachedZone() { 103 return iZone; 104 } 105 106 public String getNameKey(long instant) { 107 return getInfo(instant).getNameKey(instant); 108 } 109 110 public int getOffset(long instant) { 111 return getInfo(instant).getOffset(instant); 112 } 113 114 public int getStandardOffset(long instant) { 115 return getInfo(instant).getStandardOffset(instant); 116 } 117 118 public boolean isFixed() { 119 return iZone.isFixed(); 120 } 121 122 public long nextTransition(long instant) { 123 return iZone.nextTransition(instant); 124 } 125 126 public long previousTransition(long instant) { 127 return iZone.previousTransition(instant); 128 } 129 130 public int hashCode() { 131 return iZone.hashCode(); 132 } 133 134 public boolean equals(Object obj) { 135 if (this == obj) { 136 return true; 137 } 138 if (obj instanceof CachedDateTimeZone) { 139 return iZone.equals(((CachedDateTimeZone)obj).iZone); 140 } 141 return false; 142 } 143 144 147 private Info getInfo(long millis) { 148 int period = (int)(millis >> 32); 149 Info[] cache = iInfoCache; 150 int index = period & cInfoCacheMask; 151 Info info = cache[index]; 152 if (info == null || (int)((info.iPeriodStart >> 32)) != period) { 153 info = createInfo(millis); 154 cache[index] = info; 155 } 156 return info; 157 } 158 159 private Info createInfo(long millis) { 160 long periodStart = millis & (0xffffffffL << 32); 161 Info info = new Info(iZone, periodStart); 162 163 long end = periodStart | 0xffffffffL; 164 Info chain = info; 165 while (true) { 166 long next = iZone.nextTransition(periodStart); 167 if (next == periodStart || next > end) { 168 break; 169 } 170 periodStart = next; 171 chain = (chain.iNextInfo = new Info(iZone, periodStart)); 172 } 173 174 return info; 175 } 176 177 private final static class Info { 178 public final long iPeriodStart; 180 public final DateTimeZone iZoneRef; 181 182 Info iNextInfo; 183 184 private String iNameKey; 185 private int iOffset = Integer.MIN_VALUE; 186 private int iStandardOffset = Integer.MIN_VALUE; 187 188 Info(DateTimeZone zone, long periodStart) { 189 iPeriodStart = periodStart; 190 iZoneRef = zone; 191 } 192 193 public String getNameKey(long millis) { 194 if (iNextInfo == null || millis < iNextInfo.iPeriodStart) { 195 if (iNameKey == null) { 196 iNameKey = iZoneRef.getNameKey(iPeriodStart); 197 } 198 return iNameKey; 199 } 200 return iNextInfo.getNameKey(millis); 201 } 202 203 public int getOffset(long millis) { 204 if (iNextInfo == null || millis < iNextInfo.iPeriodStart) { 205 if (iOffset == Integer.MIN_VALUE) { 206 iOffset = iZoneRef.getOffset(iPeriodStart); 207 } 208 return iOffset; 209 } 210 return iNextInfo.getOffset(millis); 211 } 212 213 public int getStandardOffset(long millis) { 214 if (iNextInfo == null || millis < iNextInfo.iPeriodStart) { 215 if (iStandardOffset == Integer.MIN_VALUE) { 216 iStandardOffset = iZoneRef.getStandardOffset(iPeriodStart); 217 } 218 return iStandardOffset; 219 } 220 return iNextInfo.getStandardOffset(millis); 221 } 222 } 223 } 224 | Popular Tags |