1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package net.fortuna.ical4j.util;
35
36 import java.util.StringTokenizer;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41 /***
42 * Defines the format used for all iCalendar durations.
43 *
44 * @author benfortuna
45 */
46 public final class DurationFormat {
47
48 private static final long MILLIS_PER_SECOND = 1000;
49
50 private static final long MILLIS_PER_MINUTE = 60000;
51
52 private static final long MILLIS_PER_HOUR = 3600000;
53
54 private static final long MILLIS_PER_DAY = 86400000;
55
56 private static final long MILLIS_PER_WEEK = 604800000;
57
58 private static Log log = LogFactory.getLog(DurationFormat.class);
59
60 private static DurationFormat instance = new DurationFormat();
61
62 /***
63 * Constructor made private to enforce singleton.
64 */
65 private DurationFormat() {
66 }
67
68 /***
69 * @return Returns the instance.
70 */
71 public static DurationFormat getInstance() {
72 return instance;
73 }
74
75 /***
76 * Parse an iCalendar duration (dur-val) string.
77 *
78 * @param aString
79 * a string representation of a duration
80 * @return a duration in milliseconds
81 */
82 public long parse(final String aString) {
83
84 long duration = 0;
85
86 boolean negative = false;
87
88 String token = null;
89 String prevToken = null;
90
91 for (StringTokenizer t = new StringTokenizer(aString, "+-PWDTHMS", true);
92 t.hasMoreTokens();) {
93
94 prevToken = token;
95
96 token = t.nextToken();
97
98 if ("+".equals(token)) {
99 negative = false;
100 }
101 else if ("-".equals(token)) {
102 negative = true;
103 }
104 else if ("P".equals(token)) {
105
106 log.debug("Redundant [P] token ignored.");
107 }
108 else if ("W".equals(token)) {
109
110 int weeks = Integer.parseInt(prevToken);
111
112 duration += weeks * MILLIS_PER_WEEK;
113 }
114 else if ("D".equals(token)) {
115
116 int days = Integer.parseInt(prevToken);
117
118 duration += days * MILLIS_PER_DAY;
119 }
120 else if ("T".equals(token)) {
121
122 log.debug("Redundant [T] token ignored.");
123 }
124 else if ("H".equals(token)) {
125
126 int hours = Integer.parseInt(prevToken);
127
128 duration += hours * MILLIS_PER_HOUR;
129 }
130 else if ("M".equals(token)) {
131
132 int minutes = Integer.parseInt(prevToken);
133
134 duration += minutes * MILLIS_PER_MINUTE;
135 }
136 else if ("S".equals(token)) {
137
138 int seconds = Integer.parseInt(prevToken);
139
140 duration += seconds * MILLIS_PER_SECOND;
141 }
142 }
143
144 if (negative) { return -duration; }
145
146 return duration;
147 }
148
149 /***
150 * Returns a string representation of a duration.
151 *
152 * @param duration
153 * a duration in milliseconds
154 * @return a string
155 */
156 public String format(final long duration) {
157
158 StringBuffer b = new StringBuffer();
159
160 long remainder = Math.abs(duration);
161
162 if (duration < 0) {
163 b.append('-');
164 }
165
166 b.append('P');
167
168 if (remainder >= MILLIS_PER_WEEK) {
169 b.append(remainder / MILLIS_PER_WEEK);
170 b.append('W');
171 }
172 else {
173
174 if (remainder >= MILLIS_PER_DAY) {
175 b.append(remainder / MILLIS_PER_DAY);
176 b.append('D');
177
178 remainder = remainder % MILLIS_PER_DAY;
179 }
180
181 if (remainder > 0) {
182 b.append('T');
183 }
184
185 if (remainder >= MILLIS_PER_HOUR) {
186 b.append(remainder / MILLIS_PER_HOUR);
187 b.append('H');
188
189 remainder = remainder % MILLIS_PER_HOUR;
190 }
191
192 if (remainder >= MILLIS_PER_MINUTE) {
193 b.append(remainder / MILLIS_PER_MINUTE);
194 b.append('M');
195
196 remainder = remainder % MILLIS_PER_MINUTE;
197 }
198
199 if (remainder >= MILLIS_PER_SECOND) {
200 b.append(remainder / MILLIS_PER_SECOND);
201 b.append('S');
202 }
203 }
204
205 return b.toString();
206 }
207 }