1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
3/*
4 *******************************************************************************
5 * Copyright (C) 2007-2010, International Business Machines Corporation and    *
6 * others. All Rights Reserved.                                                *
7 *******************************************************************************
8 */
9package com.ibm.icu.util;
10
11import java.io.Serializable;
12
13/**
14 * <code>DateTimeRule</code> is a class representing a time in a year by
15 * a rule specified by month, day of month, day of week and
16 * time in the day.
17 *
18 * @stable ICU 3.8
19 */
20public class DateTimeRule implements Serializable {
21
22    private static final long serialVersionUID = 2183055795738051443L;
23
24    /**
25     * Date rule type defined by exact day of month.
26     * For example, March 14.
27     *
28     * @stable ICU 3.8
29     */
30    public static final int DOM = 0;
31
32    /**
33     * Date rule type defined by day of week in month.
34     * For example, 2nd Sunday in March.
35     *
36     * @stable ICU 3.8
37     */
38    public static final int DOW = 1;
39
40    /**
41     * Date rule type defined by first day of week on or
42     * after exact day of month.
43     * For example, 1st Monday on or after March 15.
44     *
45     * @stable ICU 3.8
46     */
47    public static final int DOW_GEQ_DOM = 2;
48
49    /**
50     * Date rule type defined by last day of week on or
51     * before exact day of month.
52     * For example, last Saturday on or before March 15.
53     *
54     * @stable ICU 3.8
55     */
56    public static final int DOW_LEQ_DOM = 3;
57
58    /**
59     * Time rule type for local wall time.
60     *
61     * @stable ICU 3.8
62     */
63    public static final int WALL_TIME = 0;
64
65    /**
66     * Time rule type for local standard time.
67     *
68     * @stable ICU 3.8
69     */
70    public static final int STANDARD_TIME = 1;
71
72    /**
73     * Time rule type for coordinated universal time.
74     *
75     * @stable ICU 3.8
76     */
77    public static final int UTC_TIME = 2;
78
79    // private stuff
80    private final int dateRuleType;
81    private final int month;
82    private final int dayOfMonth;
83    private final int dayOfWeek;
84    private final int weekInMonth;
85
86    private final int timeRuleType;
87    private final int millisInDay;
88
89    /**
90     * Constructs a <code>DateTimeRule</code> by the day of month and
91     * the time rule.  The date rule type for an instance created by
92     * this constructor is <code>DOM</code>.
93     *
94     * @param month         The rule month, for example, <code>Calendar.JANUARY</code>
95     * @param dayOfMonth    The day of month, 1-based.
96     * @param millisInDay   The milliseconds in the rule date.
97     * @param timeType      The time type, <code>WALL_TIME</code> or <code>STANDARD_TIME</code>
98     *                      or <code>UTC_TIME</code>.
99     *
100     * @stable ICU 3.8
101     */
102    public DateTimeRule(int month, int dayOfMonth,
103            int millisInDay, int timeType) {
104        dateRuleType = DOM;
105        this.month = month;
106        this.dayOfMonth = dayOfMonth;
107
108        this.millisInDay = millisInDay;
109        this.timeRuleType = timeType;
110
111        // not used by this rule type
112        this.dayOfWeek = 0;
113        this.weekInMonth = 0;
114    }
115
116    /**
117     * Constructs a <code>DateTimeRule</code> by the day of week and its oridinal
118     * number and the time rule.  The date rule type for an instance created
119     * by this constructor is <code>DOW</code>.
120     *
121     * @param month         The rule month, for example, <code>Calendar.JANUARY</code>.
122     * @param weekInMonth   The ordinal number of the day of week.  Negative number
123     *                      may be used for specifying a rule date counted from the
124     *                      end of the rule month.
125     * @param dayOfWeek     The day of week, for example, <code>Calendar.SUNDAY</code>.
126     * @param millisInDay   The milliseconds in the rule date.
127     * @param timeType      The time type, <code>WALL_TIME</code> or <code>STANDARD_TIME</code>
128     *                      or <code>UTC_TIME</code>.
129     *
130     * @stable ICU 3.8
131     */
132    public DateTimeRule(int month, int weekInMonth, int dayOfWeek,
133            int millisInDay, int timeType) {
134        dateRuleType = DOW;
135        this.month = month;
136        this.weekInMonth = weekInMonth;
137        this.dayOfWeek = dayOfWeek;
138
139        this.millisInDay = millisInDay;
140        this.timeRuleType = timeType;
141
142        // not used by this rule type
143        this.dayOfMonth = 0;
144    }
145
146    /**
147     * Constructs a <code>DateTimeRule</code> by the first/last day of week
148     * on or after/before the day of month and the time rule.  The date rule
149     * type for an instance created by this constructor is either
150     * <code>DOM_GEQ_DOM</code> or <code>DOM_LEQ_DOM</code>.
151     *
152     * @param month         The rule month, for example, <code>Calendar.JANUARY</code>
153     * @param dayOfMonth    The day of month, 1-based.
154     * @param dayOfWeek     The day of week, for example, <code>Calendar.SUNDAY</code>.
155     * @param after         true if the rule date is on or after the day of month.
156     * @param millisInDay   The milliseconds in the rule date.
157     * @param timeType      The time type, <code>WALL_TIME</code> or <code>STANDARD_TIME</code>
158     *                      or <code>UTC_TIME</code>.
159     *
160     * @stable ICU 3.8
161     */
162    public DateTimeRule(int month, int dayOfMonth, int dayOfWeek, boolean after,
163            int millisInDay, int timeType) {
164        this.dateRuleType = after ? DOW_GEQ_DOM : DOW_LEQ_DOM;
165        this.month = month;
166        this.dayOfMonth = dayOfMonth;
167        this.dayOfWeek = dayOfWeek;
168
169        this.millisInDay = millisInDay;
170        this.timeRuleType = timeType;
171
172        // not used by this rule type
173        this.weekInMonth = 0;
174    }
175
176    /**
177     * Gets the date rule type, such as <code>DOM</code>
178     *
179     * @return The date rule type.
180     *
181     * @stable ICU 3.8
182     */
183    public int getDateRuleType() {
184        return dateRuleType;
185    }
186
187    /**
188     * Gets the rule month.
189     *
190     * @return The rule month.
191     *
192     * @stable ICU 3.8
193     */
194    public int getRuleMonth() {
195        return month;
196    }
197
198    /**
199     * Gets the rule day of month.  When the date rule type
200     * is <code>DOW</code>, the value is always 0.
201     *
202     * @return The rule day of month
203     *
204     * @stable ICU 3.8
205     */
206    public int getRuleDayOfMonth() {
207        return dayOfMonth;
208    }
209
210    /**
211     * Gets the rule day of week.  When the date rule type
212     * is <code>DOM</code>, the value is always 0.
213     *
214     * @return The rule day of week.
215     *
216     * @stable ICU 3.8
217     */
218    public int getRuleDayOfWeek() {
219        return dayOfWeek;
220    }
221
222    /**
223     * Gets the rule day of week ordinal number in the month.
224     * When the date rule type is not <code>DOW</code>, the value is
225     * always 0.
226     *
227     * @return The rule day of week ordinal number in the month.
228     *
229     * @stable ICU 3.8
230     */
231    public int getRuleWeekInMonth() {
232        return weekInMonth;
233    }
234
235    /**
236     * Gets the time rule type
237     *
238     * @return The time rule type, either <code>WALL_TIME</code> or <code>STANDARD_TIME</code>
239     *         or <code>UTC_TIME</code>.
240     *
241     * @stable ICU 3.8
242     */
243    public int getTimeRuleType() {
244        return timeRuleType;
245    }
246
247    /**
248     * Gets the rule time in the rule day.
249     *
250     * @return The time in the rule day in milliseconds.
251     *
252     * @stable ICU 3.8
253     */
254    public int getRuleMillisInDay() {
255        return millisInDay;
256    }
257
258    private static final String[] DOWSTR = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
259    private static final String[] MONSTR = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
260
261    /**
262     * Returns a <code>String</code> representation of this <code>DateTimeRule</code> object.
263     * This method is used for debugging purpose only.  The string representation can be changed
264     * in future version of ICU without any notice.
265     *
266     * @stable ICU 3.8
267     */
268    @Override
269    public String toString() {
270        String sDate = null;
271        String sTimeRuleType = null;
272
273        switch (dateRuleType) {
274        case DOM:
275            sDate = Integer.toString(dayOfMonth);
276            break;
277        case DOW:
278            sDate = Integer.toString(weekInMonth) + DOWSTR[dayOfWeek];
279            break;
280        case DOW_GEQ_DOM:
281            sDate = DOWSTR[dayOfWeek] + ">=" + Integer.toString(dayOfMonth);
282            break;
283        case DOW_LEQ_DOM:
284            sDate = DOWSTR[dayOfWeek] + "<=" + Integer.toString(dayOfMonth);
285            break;
286        }
287
288        switch (timeRuleType) {
289        case WALL_TIME:
290            sTimeRuleType = "WALL";
291            break;
292        case STANDARD_TIME:
293            sTimeRuleType = "STD";
294            break;
295        case UTC_TIME:
296            sTimeRuleType = "UTC";
297            break;
298        }
299
300        int time = millisInDay;
301        int millis = time % 1000;
302        time /= 1000;
303        int secs = time % 60;
304        time /= 60;
305        int mins = time % 60;
306        int hours = time / 60;
307
308        StringBuilder buf = new StringBuilder();
309        buf.append("month=");
310        buf.append(MONSTR[month]);
311        buf.append(", date=");
312        buf.append(sDate);
313        buf.append(", time=");
314        buf.append(hours);
315        buf.append(":");
316        buf.append(mins/10);
317        buf.append(mins%10);
318        buf.append(":");
319        buf.append(secs/10);
320        buf.append(secs%10);
321        buf.append(".");
322        buf.append(millis/100);
323        buf.append((millis/10)%10);
324        buf.append(millis%10);
325        buf.append("(");
326        buf.append(sTimeRuleType);
327        buf.append(")");
328        return buf.toString();
329    }
330}
331