1 /* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import java.io.BufferedReader; 27 import java.io.FileReader; 28 import java.io.FileNotFoundException; 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.StringTokenizer; 37 38 /** 39 * ZoneRec hold information of time zone corresponding to each text 40 * line of the "Zone" part. 41 * 42 * @since 1.4 43 */ 44 class ZoneRec { 45 private int gmtOffset; 46 private String ruleName; 47 private int directSave; 48 private Rule ruleRef; 49 private String format; 50 private boolean hasUntil; 51 private int untilYear; 52 private Month untilMonth; 53 private RuleDay untilDay; 54 private Time untilTime; 55 private long untilInMillis; 56 private String line; 57 58 /** 59 * @return the "UNTIL" value in milliseconds 60 */ 61 Time getUntilTime() { 62 return untilTime; 63 } 64 65 /** 66 * @return the GMT offset value in milliseconds 67 */ 68 int getGmtOffset() { 69 return gmtOffset; 70 } 71 72 /** 73 * @return the rule name to which this zone record refers 74 */ 75 String getRuleName() { 76 return ruleName; 77 } 78 79 /** 80 * @return the amount of saving time directly defined in the 81 * "RULES/SAVE" field. 82 */ 83 int getDirectSave() { 84 return directSave; 85 } 86 87 /** 88 * @return true if this zone record has a reference to a rule 89 */ 90 boolean hasRuleReference() { 91 return ruleRef != null; 92 } 93 94 /** 95 * Returns the "FORMAT" field string of this zone record. This 96 * @return the "FORMAT" field 97 */ 98 String getFormat() { 99 return format; 100 } 101 102 /** 103 * @return the year in the "UNTIL" field 104 */ 105 int getUntilYear() { 106 return untilYear; 107 } 108 109 /** 110 * Returns the "UNTIL" field value in milliseconds from Janurary 111 * 1, 1970 0:00 GMT. 112 * @param currentSave the amount of daylight saving in 113 * milliseconds that is used to adjust wall-clock time. 114 * @return the milliseconds value of the "UNTIL" field 115 */ 116 long getUntilTime(int currentSave) { 117 if (untilTime.isWall()) { 118 return untilInMillis - currentSave; 119 } 120 return untilInMillis; 121 } 122 123 /** 124 * Returns the "UNTIL" time in milliseconds without adjusting GMT 125 * offsets or daylight saving. 126 * @return local "UNTIL" time in milliseconds 127 */ 128 long getLocalUntilTime() { 129 return Time.getLocalTime(untilYear, 130 untilMonth, 131 untilDay, 132 untilTime.getTime()); 133 } 134 135 /** 136 * Returns the "UNTIL" time in milliseconds with adjusting GMT offsets and daylight saving. 137 * @return the "UNTIL" time after the adjustment 138 */ 139 long getLocalUntilTime(int save, int gmtOffset) { 140 return Time.getLocalTime(untilYear, 141 untilMonth, 142 untilDay, 143 save, 144 gmtOffset, 145 untilTime); 146 } 147 148 /** 149 * @return the text line of this zone record 150 */ 151 String getLine() { 152 return line; 153 } 154 155 /** 156 * Sets the specified text line to this zone record 157 */ 158 void setLine(String line) { 159 this.line = line; 160 } 161 162 /** 163 * @return true if this zone record has the "UNTIL" field 164 */ 165 boolean hasUntil() { 166 return this.hasUntil; 167 } 168 169 /** 170 * Adjusts the "UNTIL" time to GMT offset if this zone record has 171 * it. <code>untilTime</code> is not adjusted to daylight saving 172 * in this method. 173 */ 174 void adjustTime() { 175 if (!hasUntil()) { 176 return; 177 } 178 if (untilTime.isSTD() || untilTime.isWall()) { 179 // adjust to gmt offset only here. adjust to real 180 // wall-clock time when tracking rules 181 untilInMillis -= gmtOffset; 182 } 183 } 184 185 /** 186 * @return the reference to the Rule object 187 */ 188 Rule getRuleRef() { 189 return ruleRef; 190 } 191 192 /** 193 * Resolves the reference to a Rule and adjusts its "UNTIL" time 194 * to GMT offset. 195 */ 196 void resolve(Zoneinfo zi) { 197 if (ruleName != null && (!"-".equals(ruleName))) { 198 ruleRef = zi.getRule(ruleName); 199 } 200 adjustTime(); 201 } 202 203 /** 204 * Parses a Zone text line that is described by a StringTokenizer. 205 * @param tokens represents tokens of a Zone text line 206 * @return the zone record produced by parsing the text 207 */ 208 static ZoneRec parse(StringTokenizer tokens) { 209 ZoneRec rec = new ZoneRec(); 210 try { 211 rec.gmtOffset = (int) Time.parse(tokens.nextToken()).getTime(); 212 String token = tokens.nextToken(); 213 char c = token.charAt(0); 214 if (c >= '0' && c <= '9') { 215 rec.directSave = (int) Time.parse(token).getTime(); 216 } else { 217 rec.ruleName = token; 218 } 219 rec.format = tokens.nextToken(); 220 if (tokens.hasMoreTokens()) { 221 rec.hasUntil = true; 222 rec.untilYear = Integer.parseInt(tokens.nextToken()); 223 if (tokens.hasMoreTokens()) { 224 rec.untilMonth = Month.parse(tokens.nextToken()); 225 } else { 226 rec.untilMonth = Month.JANUARY; 227 } 228 if (tokens.hasMoreTokens()) { 229 rec.untilDay = RuleDay.parse(tokens.nextToken()); 230 } else { 231 rec.untilDay = new RuleDay(1); 232 } 233 if (tokens.hasMoreTokens()) { 234 rec.untilTime = Time.parse(tokens.nextToken()); 235 } else { 236 rec.untilTime = Time.parse("0:00"); 237 } 238 rec.untilInMillis = rec.getLocalUntilTime(); 239 } 240 } catch (Exception e) { 241 // TODO: error reporting 242 e.printStackTrace(); 243 } 244 return rec; 245 } 246 247 private static void panic(String msg) { 248 Main.panic(msg); 249 } 250 }