1bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert/*
2bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** Copyright 2006, The Android Open Source Project
3bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert**
4bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** Licensed under the Apache License, Version 2.0 (the "License");
5bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** you may not use this file except in compliance with the License.
6bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** You may obtain a copy of the License at
7bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert**
8bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert**     http://www.apache.org/licenses/LICENSE-2.0
9bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert**
10bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** Unless required by applicable law or agreed to in writing, software
11bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** distributed under the License is distributed on an "AS IS" BASIS,
12bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** See the License for the specific language governing permissions and
14bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert** limitations under the License.
15bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert*/
16bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
1706b3293d5af3454a39681cfd659271551354b8a0Michael Chanpackage com.android.calendarcommon2;
18bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
19bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albertimport java.util.Calendar;
20bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
21bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert/**
22bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert * According to RFC2445, durations are like this:
23bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert *       WEEKS
24bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert *     | DAYS [ HOURS [ MINUTES [ SECONDS ] ] ]
25bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert *     | HOURS [ MINUTES [ SECONDS ] ]
26bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert * it doesn't specifically, say, but this sort of implies that you can't have
27bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert * 70 seconds.
28bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert */
29bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albertpublic class Duration
30bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert{
31bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int sign; // 1 or -1
32bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int weeks;
33bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int days;
34bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int hours;
35bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int minutes;
36bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public int seconds;
37bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
38bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public Duration()
39bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    {
40bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        sign = 1;
41bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    }
42bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
43bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    /**
44bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert     * Parse according to RFC2445 ss4.3.6.  (It's actually a little loose with
45bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert     * its parsing, for better or for worse)
46bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert     */
47bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public void parse(String str) throws DateException
48bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    {
49bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        sign = 1;
50bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        weeks = 0;
51bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        days = 0;
52bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        hours = 0;
53bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        minutes = 0;
54bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        seconds = 0;
55bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
56bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        int len = str.length();
57bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        int index = 0;
58bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        char c;
59bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
60bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        if (len < 1) {
61bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            return ;
62bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
63bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
64bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        c = str.charAt(0);
65bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        if (c == '-') {
66bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            sign = -1;
67bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            index++;
68bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
69bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        else if (c == '+') {
70bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            index++;
71bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
72bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
73bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        if (len < index) {
74bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            return ;
75bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
76bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
77bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        c = str.charAt(index);
78bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        if (c != 'P') {
79bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            throw new DateException (
80bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                    "Duration.parse(str='" + str + "') expected 'P' at index="
81bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                    + index);
82bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
83bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        index++;
84bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        c = str.charAt(index);
85bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        if (c == 'T') {
86bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            index++;
87bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
88bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
89bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        int n = 0;
90bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        for (; index < len; index++) {
91bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            c = str.charAt(index);
92bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            if (c >= '0' && c <= '9') {
93bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n *= 10;
94bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n += ((int)(c-'0'));
95bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
96bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'W') {
97bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                weeks = n;
98bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n = 0;
99bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
100bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'H') {
101bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                hours = n;
102bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n = 0;
103bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
104bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'M') {
105bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                minutes = n;
106bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n = 0;
107bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
108bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'S') {
109bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                seconds = n;
110bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n = 0;
111bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
112bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'D') {
113bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                days = n;
114bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                n = 0;
115bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
116bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else if (c == 'T') {
117bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
118bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            else {
119bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                throw new DateException (
120bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                        "Duration.parse(str='" + str + "') unexpected char '"
121bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                        + c + "' at index=" + index);
122bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert            }
123bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        }
124bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    }
125bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
126bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    /**
127bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert     * Add this to the calendar provided, in place, in the calendar.
128bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert     */
129bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public void addTo(Calendar cal)
130bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    {
131bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        cal.add(Calendar.DAY_OF_MONTH, sign*weeks*7);
132bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        cal.add(Calendar.DAY_OF_MONTH, sign*days);
133bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        cal.add(Calendar.HOUR, sign*hours);
134bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        cal.add(Calendar.MINUTE, sign*minutes);
135bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        cal.add(Calendar.SECOND, sign*seconds);
136bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    }
137bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
138bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public long addTo(long dt) {
139bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        return dt + getMillis();
140bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    }
141bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert
142bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    public long getMillis() {
143bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        long factor = 1000 * sign;
144bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert        return factor * ((7*24*60*60*weeks)
145bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                + (24*60*60*days)
146bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                + (60*60*hours)
147bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                + (60*minutes)
148bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert                + seconds);
149bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert    }
150bd003db9ed354cfd87df64d1ffd500e9a4bb8930Alon Albert}
151