RuleRec.java revision 9330:8b1f1c2a400f
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
26import java.util.StringTokenizer;
27
28/**
29 * RuleRec class represents one record of the Rule set.
30 *
31 * @since 1.4
32 */
33class 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}
231