1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dbforms.util;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.apache.regexp.RE;
30 import org.apache.regexp.RESyntaxException;
31
32 /***
33 * Helper classes for dealing with time values
34 *
35 */
36 import java.text.SimpleDateFormat;
37
38 import java.util.Calendar;
39 import java.util.Date;
40 import java.util.GregorianCalendar;
41 import java.util.TimeZone;
42
43
44
45 /***
46 * DOCUMENT ME!
47 *
48 * @version $Revision: 1.24 $
49 * @author $author$
50 */
51 public class TimeUtil {
52 private static Log logCat = LogFactory.getLog(TimeUtil.class.getName());
53 static final int SECSPERDAY = 24 * 60 * 60;
54 private static String reISO8601 = "(//d//d//d//d)(-(//d//d)(-(//d//d))?)?"
55 + "([T| ]?"
56 + "(//d//d):(//d//d)(:((//d//d)(//.(//d+))?)?)?"
57 + "(Z|([+-]//d//d://d//d)|([A-Z]{3}))?)?";
58
59 /***
60 * Reformats seconds to time string with format: dd:hh:mm:ss
61 *
62 * @param seconds string to format
63 *
64 * @return String
65 */
66 public static final String seconds2String(String seconds) {
67 if (Util.isNull(seconds)) {
68 return "";
69 } else {
70 return seconds2String(Integer.valueOf(seconds));
71 }
72 }
73
74
75 /***
76 * Reformats seconds to time string with format: dd:hh:mm:ss
77 *
78 * @param seconds Integer to format
79 *
80 * @return String
81 */
82 public static final String seconds2String(Integer seconds) {
83 return seconds2String(seconds.intValue());
84 }
85
86
87 /***
88 * Reformats seconds to time string with format: dd:hh:mm:ss
89 *
90 * @param seconds string to format
91 *
92 * @return String
93 */
94 public static final String seconds2String(Long seconds) {
95 return seconds2String(seconds.longValue());
96 }
97
98
99 /***
100 * Reformats seconds to time string with format: dd:hh:mm:ss
101 *
102 * @param seconds string to format
103 *
104 * @return String
105 */
106 public static final String seconds2String(long seconds) {
107 long d;
108 long h;
109 long m;
110 String zeit;
111 d = (seconds / SECSPERDAY);
112 seconds = seconds - (d * SECSPERDAY);
113 h = seconds / (60 * 60);
114 seconds = seconds - (h * 60 * 60);
115 m = seconds / 60;
116 seconds = seconds - (m * 60);
117
118 if (d > 0) {
119 Object[] o = {
120 new Long(d),
121 new Long(h),
122 new Long(m),
123 new Long(seconds)
124 };
125 zeit = Util.sprintf("%i:%02i:%02i:%02i", o);
126 } else {
127 Object[] o = {
128 new Long(h),
129 new Long(m),
130 new Long(seconds)
131 };
132 zeit = Util.sprintf("%i:%02i:%02i", o);
133 }
134
135 return zeit;
136 }
137
138 /***
139 * Reformats minutes to time string with format: dd:hh:mm
140 *
141 * @param seconds string to format
142 *
143 * @return String
144 */
145 public static final String minutes2String(long minutes) {
146 long d;
147 long h;
148 long m;
149 String zeit;
150 d = (minutes / SECSPERDAY * 60);
151 minutes = minutes - (d * SECSPERDAY * 60);
152 h = minutes / (60);
153 minutes = minutes - (h * 60);
154
155 if (d > 0) {
156 Object[] o = {
157 new Long(d),
158 new Long(h),
159 new Long(minutes)
160 };
161 zeit = Util.sprintf("%i:%02i:%02i", o);
162 } else {
163 Object[] o = {
164 new Long(h),
165 new Long(minutes),
166 };
167 zeit = Util.sprintf("%i:%02i", o);
168 }
169
170 return zeit;
171 }
172
173
174 /***
175 * finds the end of the given day
176 *
177 * @param d date of which end should be find
178 *
179 * @return end of the day
180 */
181 public static Date findEndOfDay(Date d) {
182 Calendar cal = Calendar.getInstance();
183 cal.setTime(d);
184 cal.set(Calendar.HOUR_OF_DAY, 0);
185 cal.set(Calendar.MINUTE, 0);
186 cal.set(Calendar.SECOND, 0);
187 cal.add(Calendar.DAY_OF_MONTH, 1);
188
189 return cal.getTime();
190 }
191
192
193 /***
194 * Tries to parse a String into a Calendar objectvalue. String mustn't a full date,
195 * parts are enough. Parsing will set missing parts to default values
196 *
197 * @param loc locale to use
198 * @param format java format string for date/time
199 * @param s string to be parsed
200 *
201 * @return the parsed date
202 */
203 public static Calendar parseDate(final SimpleDateFormat format,
204 String s) {
205 StringBuffer sDate = new StringBuffer();
206 StringBuffer sTime = new StringBuffer();
207 StringBuffer fDate = new StringBuffer();
208 StringBuffer fTime = new StringBuffer();
209
210 splitDate(s, sDate, sTime);
211 splitDate(format.toPattern(), fDate, fTime);
212
213 SimpleDateFormat f = (SimpleDateFormat) format.clone();
214 Calendar dDate = saveParseDate(f, fDate.toString(),
215 sDate.toString());
216 long date = dDate.getTime()
217 .getTime();
218 f.setTimeZone(dDate.getTimeZone());
219
220 long time = saveParseTime(f, fTime.toString(), sTime.toString());
221 long offset = dDate.getTimeZone()
222 .getRawOffset();
223
224 if (!Util.isNull(sTime.toString())) {
225 time = time + offset;
226 }
227
228 date = date + time;
229
230 Calendar c = format.getCalendar();
231
232
233 Date dateAsDate = new Date(date);
234 c.setTime(dateAsDate);
235
236 logCat.info("parsed " + s + " to " + format.format(c.getTime()));
237
238 return c;
239 }
240
241
242 /***
243 * Parses an ISO8601 date format string
244 *
245 * @param s string to be parsed
246 *
247 * @return the parsed date
248 */
249 public static Date parseISO8601Date(String s) {
250 ISO8601 iso = parseISO8601(s);
251
252 if (iso != null) {
253 TimeZone tz = null;
254
255
256 if ((iso.tz != null) && !(iso.tz.length() == 0)) {
257 if (iso.tz.equals("Z")) {
258 tz = TimeZone.getTimeZone("GMT");
259 } else if (iso.tz.length() == 3) {
260 tz = TimeZone.getTimeZone(iso.tz);
261 } else {
262 tz = TimeZone.getTimeZone("GMT" + iso.tz);
263 }
264 }
265
266 Calendar cal = new GregorianCalendar(iso.year, iso.month - 1, iso.day,
267 iso.hour, iso.min, iso.sec);
268
269 if (tz != null) {
270 cal.setTimeZone(tz);
271 }
272
273 return cal.getTime();
274 }
275
276
277 return null;
278 }
279
280
281 private static ISO8601 parseISO8601(String s) {
282
283
284
285 try {
286 RE re = new RE(reISO8601);
287
288 if (re.match(s)) {
289 ISO8601 iso = new ISO8601();
290 iso.year = toInt(re.getParen(1));
291 iso.month = toInt(re.getParen(3));
292 iso.day = toInt(re.getParen(5));
293 iso.hour = toInt(re.getParen(7));
294 iso.min = toInt(re.getParen(8));
295 iso.sec = toInt(re.getParen(11));
296 iso.frac = toInt(re.getParen(13));
297 iso.tz = re.getParen(14);
298
299 return iso;
300 }
301 }
302
303 catch (RESyntaxException ree) {
304 ree.printStackTrace();
305 }
306
307 return null;
308 }
309
310
311 private static Calendar saveParseDate(final SimpleDateFormat format,
312 String formatString,
313 String s)
314 throws NumberFormatException {
315 Date d = null;
316 Calendar cal;
317 Calendar now = Calendar.getInstance();
318
319 if (!Util.isNull(s)) {
320 if (!Util.isNull(formatString)) {
321 format.applyPattern(formatString);
322 }
323
324 try {
325 d = format.parse(s);
326 } catch (Exception e) {
327 logCat.error(e);
328
329
330 SimpleDateFormat f = (SimpleDateFormat) format.clone();
331 f.applyPattern("yyyy-MM-dd");
332
333 try {
334 d = f.parse(s);
335 } catch (Exception ex) {
336 logCat.error(ex);
337 }
338 }
339
340 cal = format.getCalendar();
341
342 if (d != null) {
343 cal.setTime(d);
344 } else {
345 synchronized (cal) {
346 try {
347
348
349 cal.wait(5);
350 } catch (Exception ex) {
351 logCat.error(ex);
352 }
353 }
354 }
355
356 if (!cal.isSet(Calendar.DAY_OF_MONTH)
357 && !cal.isSet(Calendar.MONTH)
358 && !cal.isSet(Calendar.YEAR)) {
359 throw new NumberFormatException("wrong date format");
360 }
361
362 if (!cal.isSet(Calendar.DAY_OF_MONTH)) {
363 cal.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH));
364 }
365
366 if (!cal.isSet(Calendar.MONTH)) {
367 cal.set(Calendar.MONTH, now.get(Calendar.MONTH));
368 }
369
370 if (!cal.isSet(Calendar.YEAR)) {
371 cal.set(Calendar.YEAR, now.get(Calendar.YEAR));
372 }
373
374 if (cal.get(Calendar.YEAR) < 30) {
375 cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 2000);
376 } else if (cal.get(Calendar.YEAR) < 100) {
377 cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1900);
378 }
379 } else {
380 cal = now;
381 }
382
383 cal.set(Calendar.HOUR_OF_DAY, 0);
384 cal.set(Calendar.MINUTE, 0);
385 cal.set(Calendar.SECOND, 0);
386
387 return cal;
388 }
389
390
391 private static synchronized long saveParseTime(final SimpleDateFormat format,
392 String formatString,
393 String s) {
394 Date d = null;
395
396 if (!Util.isNull(s)) {
397 if (!Util.isNull(formatString)) {
398 format.applyPattern(formatString);
399 }
400
401 try {
402 d = format.parse(s);
403 } catch (Exception e) {
404 logCat.error(e);
405
406
407 SimpleDateFormat f = (SimpleDateFormat) format.clone();
408 f.applyPattern("HH:mm:ss");
409
410 try {
411 d = f.parse(s);
412 } catch (Exception ex) {
413 logCat.error(ex);
414 }
415 }
416
417 Calendar cal = format.getCalendar();
418
419 if (d != null) {
420 cal.setTime(d);
421 } else {
422 synchronized (cal) {
423 try {
424
425
426 cal.wait(5);
427 } catch (Exception ex) {
428 logCat.error(ex);
429 }
430 }
431 }
432
433 if (!cal.isSet(Calendar.HOUR_OF_DAY)
434 && !cal.isSet(Calendar.MINUTE)
435 && !cal.isSet(Calendar.SECOND)) {
436 throw new NumberFormatException("wrong time format");
437 }
438
439 if (!cal.isSet(Calendar.HOUR_OF_DAY)) {
440 cal.set(Calendar.HOUR_OF_DAY, 0);
441 }
442
443 if (!cal.isSet(Calendar.MINUTE)) {
444 cal.set(Calendar.MINUTE, 0);
445 }
446
447 if (!cal.isSet(Calendar.SECOND)) {
448 cal.set(Calendar.SECOND, 0);
449 }
450
451 return cal.getTime()
452 .getTime();
453 }
454
455 return 0;
456 }
457
458
459 public static void splitDate(final String format,
460 StringBuffer sDate,
461 StringBuffer sTime) {
462 sDate.setLength(0);
463 sTime.setLength(0);
464
465 int i = format.lastIndexOf(':');
466
467 if (i > -1) {
468 i = format.lastIndexOf(' ', i);
469
470 if (i > -1) {
471 sDate.append(format.substring(0, i));
472 sTime.append(format.substring(i + 1));
473 } else {
474 sTime.append(format);
475 }
476 } else {
477 sDate.append(format);
478 }
479 }
480
481
482 private static int toInt(String x) {
483 if (x == null) {
484 return 0;
485 }
486
487 try {
488 return Integer.parseInt(x);
489 } catch (NumberFormatException e) {
490 return 0;
491 }
492 }
493
494 /***
495 * Parses an ISO8601 date format string
496 *
497 */
498 private static class ISO8601 {
499 public String tz;
500 public int day;
501 public int frac;
502 public int hour;
503 public int min;
504 public int month;
505 public int sec;
506 public int year;
507 }
508 }