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