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.util.StringTokenizer; 27 28 /** 29 * RuleRec class represents one record of the Rule set. 30 * 31 * @since 1.4 32 */ 33 class RuleRec { 34 private int fromYear; 35 private int toYear; 36 private String type; 37 private Month inMonth; 38 private RuleDay onDay; 39 private Time atTime; 40 private int save; 41 private String letters; 42 private String line; 43 private boolean isLastRule; 44 45 int getFromYear() { 46 return fromYear; 47 } 48 49 int getToYear() { 50 return toYear; 51 } 52 53 Month getMonth() { 54 return inMonth; 55 } 56 57 int getMonthNum() { 58 return inMonth.value(); 59 } 60 61 RuleDay getDay() { 62 return onDay; 63 } 64 65 Time getTime() { 66 return atTime; 67 } 68 69 int getSave() { 70 return save; 71 } 72 73 String getLine() { 74 return line; 75 } 76 77 /** 78 * Sets the line from the text file. 79 * @param line the text of the line 80 */ 81 void setLine(String line) { 82 this.line = line; 83 } 84 85 /** 86 * @return true if the rule type is "odd". 87 */ 88 boolean isOdd() { 89 return "odd".equals(type); 90 } 91 92 /** 93 * @return true if the rule type is "even". 94 */ 95 boolean isEven() { 96 return "even".equals(type); 97 } 98 99 /** 100 * Determines if this rule record is the last DST schedule rule. 101 * 102 * @return true if this rule record has "max" as TO (year). 103 */ 104 boolean isLastRule() { 105 return isLastRule; 106 } 107 108 /** 109 * Determines if the unadjusted until time of the specified ZoneRec 110 * is the same as the transition time of this rule in the same 111 * year as the ZoneRec until year. 112 * 113 * @param zrec ZoneRec to compare to 114 * @param save the amount of daylight saving in milliseconds 115 * @param gmtOffset the GMT offset value in milliseconds 116 * @return true if the unadjusted until time is the same as rule's 117 * transition time. 118 */ 119 boolean isSameTransition(ZoneRec zrec, int save, int gmtOffset) { 120 long until, transition; 121 122 if (zrec.getUntilTime().getType() != atTime.getType()) { 123 until = zrec.getLocalUntilTime(save, gmtOffset); 124 transition = Time.getLocalTime(zrec.getUntilYear(), 125 getMonth(), 126 getDay(), 127 save, 128 gmtOffset, 129 atTime); 130 } else { 131 until = zrec.getLocalUntilTime(); 132 transition = Time.getLocalTime(zrec.getUntilYear(), 133 getMonth(), 134 getDay(), 135 atTime.getTime()); 136 } 137 138 return until == transition; 139 } 140 141 /** 142 * Parses a Rule line and returns a RuleRec object. 143 * 144 * @param tokens a StringTokenizer object that should contain a 145 * token for the "FROM" field and the rest. 146 * @return a RuleRec object. 147 */ 148 static RuleRec parse(StringTokenizer tokens) { 149 RuleRec rec = new RuleRec(); 150 try { 151 // FROM 152 String token = tokens.nextToken(); 153 try { 154 rec.fromYear = Integer.parseInt(token); 155 } catch (NumberFormatException e) { 156 // it's not integer 157 if ("min".equals(token) || "minimum".equals(token)) { 158 rec.fromYear = Zoneinfo.getMinYear(); 159 } else if ("max".equals(token) || "maximum".equals(token)) { 160 rec.fromYear = Zoneinfo.getMaxYear(); 161 } else { 162 Main.panic("invalid year value: "+token); 163 } 164 } 165 166 // TO 167 token = tokens.nextToken(); 168 rec.isLastRule = false; 169 try { 170 rec.toYear = Integer.parseInt(token); 171 } catch (NumberFormatException e) { 172 // it's not integer 173 if ("min".equals(token) || "minimum".equals(token)) { 174 rec.fromYear = Zoneinfo.getMinYear(); 175 } else if ("max".equals(token) || "maximum".equals(token)) { 176 rec.toYear = Integer.MAX_VALUE; 177 rec.isLastRule = true; 178 } else if ("only".equals(token)) { 179 rec.toYear = rec.fromYear; 180 } else { 181 Main.panic("invalid year value: "+token); 182 } 183 } 184 185 // TYPE 186 rec.type = tokens.nextToken(); 187 188 // IN 189 rec.inMonth = Month.parse(tokens.nextToken()); 190 191 // ON 192 rec.onDay = RuleDay.parse(tokens.nextToken()); 193 194 // AT 195 rec.atTime = Time.parse(tokens.nextToken()); 196 197 // SAVE 198 rec.save = (int) Time.parse(tokens.nextToken()).getTime(); 199 200 // LETTER/S 201 rec.letters = tokens.nextToken(); 202 } catch (Exception e) { 203 e.printStackTrace(); 204 } 205 return rec; 206 } 207 208 /** 209 * Calculates the transition time of the given year under this rule. 210 * @param year the year value 211 * @param gmtOffset the GMT offset value in milliseconds 212 * @param save the amount of daylight save time 213 * @return the transition time in milliseconds of the given year in UTC. 214 */ 215 long getTransitionTime(int year, int gmtOffset, int save) { 216 long time = Time.getLocalTime(year, getMonth(), 217 getDay(), atTime.getTime()); 218 if (atTime.isSTD()) { 219 time -= gmtOffset; 220 } else if (atTime.isWall()) { 221 time -= gmtOffset + save; 222 } 223 return time; 224 } 225 226 private static int getInt(StringTokenizer tokens) { 227 String token = tokens.nextToken(); 228 return Integer.parseInt(token); 229 } 230 }