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