001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.util.time;
018:
019: import java.text.ParseException;
020: import java.text.SimpleDateFormat;
021: import java.util.Calendar;
022: import java.util.Date;
023:
024: /**
025: * An immutable Time class that represents a specific point in time. The
026: * underlying representation is a long value which holds a number of
027: * milliseconds since January 1, 1970, 0:00 GMT. To represent a time duration,
028: * such as "6 seconds", use the Duration class. To represent a time period with
029: * a start and end time, use the TimeFrame class. To represent a time of day,
030: * use the TimeOfDay class.
031: *
032: * @author Jonathan Locke
033: */
034: public final class Time extends AbstractTime {
035: private static final long serialVersionUID = 1L;
036:
037: /** The beginning of UNIX time: January 1, 1970, 0:00 GMT. */
038: public static final Time START_OF_UNIX_TIME = milliseconds(0);
039:
040: /** Parser in 'yyyy.MM.dd' format. */
041: private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
042: "yyyy.MM.dd");
043:
044: /** Parser in 'yyyy.MM.dd-h.mma' format. */
045: private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
046: "yyyy.MM.dd-h.mma");
047:
048: /**
049: * Gets a Time instance based on the given miliseconds.
050: *
051: * @param time
052: * The time in milliseconds since START_OF_UNIX_TIME
053: * @return The given time
054: */
055: public static Time milliseconds(final long time) {
056: return new Time(time);
057: }
058:
059: /**
060: * Gets a Time instance based on the current time.
061: *
062: * @return The current time
063: */
064: public static Time now() {
065: return new Time(System.currentTimeMillis());
066: }
067:
068: /**
069: * Gets time by parsing 'yyyy.MM.dd' format.
070: *
071: * @param calendar
072: * The calendar to use when parsing date string
073: * @param string
074: * The string
075: * @return The time
076: * @throws ParseException
077: */
078: public static Time parseDate(final Calendar calendar,
079: final String string) throws ParseException {
080: synchronized (dateFormat) {
081: synchronized (calendar) {
082: dateFormat.setCalendar(calendar);
083:
084: return valueOf(dateFormat.parse(string));
085: }
086: }
087: }
088:
089: /**
090: * Gets time by parsing 'yyyy.MM.dd' format using a localtime calendar.
091: *
092: * @param string
093: * The string
094: * @return The time
095: * @throws ParseException
096: */
097: public static Time parseDate(final String string)
098: throws ParseException {
099: return parseDate(localtime, string);
100: }
101:
102: /**
103: * Gets time by parsing yyyy.MM.dd-h.mma format.
104: *
105: * @param calendar
106: * The calendar to use when parsing the string
107: * @param string
108: * The string
109: * @return An immutable UNIX time value
110: * @throws ParseException
111: */
112: public static Time valueOf(final Calendar calendar,
113: final String string) throws ParseException {
114: synchronized (dateTimeFormat) {
115: synchronized (calendar) {
116: dateTimeFormat.setCalendar(calendar);
117:
118: return valueOf(dateTimeFormat.parse(string));
119: }
120: }
121: }
122:
123: /**
124: * Gets a Time instance based on the given calendar and {@link TimeOfDay}
125: * objects.
126: *
127: * @param calendar
128: * The calendar to use
129: * @param timeOfDay
130: * The time of day
131: * @return A time value for the time of day today
132: */
133: public static Time valueOf(final Calendar calendar,
134: final TimeOfDay timeOfDay) {
135: synchronized (calendar) {
136: // Set time to midnight today
137: calendar.setTimeInMillis(System.currentTimeMillis());
138: calendar.set(Calendar.HOUR, 0);
139: calendar.set(Calendar.MINUTE, 0);
140: calendar.set(Calendar.SECOND, 0);
141:
142: // Add time of day milliseconds to midnight
143: return valueOf(calendar.getTimeInMillis()
144: + timeOfDay.getMilliseconds());
145: }
146: }
147:
148: /**
149: * Gets a Time instance based on the given date object.
150: *
151: * @param date
152: * A java.util.Date object
153: * @return A corresponding immutable Time object
154: */
155: public static Time valueOf(final Date date) {
156: return new Time(date.getTime());
157: }
158:
159: /**
160: * Gets a Time instance based on the given miliseconds.
161: *
162: * @param time
163: * The time in milliseconds since START_OF_UNIX_TIME
164: * @return A corresponding immutable Time object
165: */
166: public static Time valueOf(final long time) {
167: return new Time(time);
168: }
169:
170: /**
171: * Gets time by parsing yyyy.MM.dd-h.mma format.
172: *
173: * @param string
174: * The string
175: * @return The time
176: * @throws ParseException
177: */
178: public static Time valueOf(final String string)
179: throws ParseException {
180: return valueOf(localtime, string);
181: }
182:
183: /**
184: * Gets time by parsing 'pattern' format.
185: *
186: * @param string
187: * input
188: * @param pattern
189: * pattern to use
190: * @return Time instance that resulted from parsing the given string
191: * @throws ParseException
192: */
193: public static Time valueOf(final String string, final String pattern)
194: throws ParseException {
195: final SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
196: pattern);
197: dateTimeFormat.setCalendar(localtime);
198: return valueOf(dateTimeFormat.parse(string));
199: }
200:
201: /**
202: * Gets a Time instance based on the given {@link TimeOfDay}object.
203: *
204: * @param timeOfDay
205: * The time of day in localtime
206: * @return A time value for the time of day today
207: */
208: public static Time valueOf(final TimeOfDay timeOfDay) {
209: return valueOf(localtime, timeOfDay);
210: }
211:
212: /**
213: * Private constructor forces use of static factory methods.
214: *
215: * @param time
216: * The time in milliseconds since START_OF_UNIX_TIME
217: */
218: private Time(final long time) {
219: super (time);
220: }
221:
222: /**
223: * Adds the given duration to this time object, moving the time into the
224: * future.
225: *
226: * @param duration
227: * The duration to add
228: * @return This time + duration
229: */
230: public Time add(final Duration duration) {
231: return milliseconds(getMilliseconds()
232: + duration.getMilliseconds());
233: }
234:
235: /**
236: * @return Amount of time that has elapsed since this time
237: * @throws IllegalStateException Thrown if this time is in the future
238: */
239: public Duration elapsedSince() {
240: final Time now = now();
241: if (this .greaterThan(now)) {
242: throw new IllegalStateException(
243: "This time is in the future");
244: }
245: return now.subtract(this );
246: }
247:
248: /**
249: * Gets the duration from now to this time value. If this time value is in
250: * the past, then the Duration returned will be negative. Otherwise, it will
251: * be the number of milliseconds from now to this Time.
252: *
253: * @return The duration from now to this time value
254: */
255: public Duration fromNow() {
256: return subtract(now());
257: }
258:
259: /**
260: * Gets the value of a field from the given calendar.
261: *
262: * @param calendar
263: * The calendar to use
264: * @param field
265: * The calendar field to get
266: * @return The field's value for this point in time on the given calendar
267: */
268: public int get(final Calendar calendar, final int field) {
269: synchronized (calendar) {
270: calendar.setTimeInMillis(getMilliseconds());
271:
272: return calendar.get(field);
273: }
274: }
275:
276: /**
277: * Gets the value of a field.
278: *
279: * @param field
280: * The calendar field to get
281: * @return The field's value (in localtime)
282: */
283: public int get(final int field) {
284: return get(localtime, field);
285: }
286:
287: /**
288: * Gets the day of month field of the current calendar.
289: *
290: * @return the field value
291: */
292: public int getDayOfMonth() {
293: return getDayOfMonth(localtime);
294: }
295:
296: /**
297: * Gets the day of month field of the given calendar.
298: *
299: * @param calendar
300: * the calendar to get the field value from
301: * @return the field value
302: */
303: public int getDayOfMonth(final Calendar calendar) {
304: return get(calendar, Calendar.DAY_OF_MONTH);
305: }
306:
307: /**
308: * Gets the hour field of the current calendar.
309: *
310: * @return the field value
311: */
312: public int getHour() {
313: return getHour(localtime);
314: }
315:
316: /**
317: * Gets the hour field of the given calendar.
318: *
319: * @param calendar
320: * the calendar to get the field value from
321: * @return the field value
322: */
323: public int getHour(final Calendar calendar) {
324: return get(calendar, Calendar.HOUR);
325: }
326:
327: /**
328: * Gets the minute field of the current calendar.
329: *
330: * @return the field value
331: */
332: public int getMinute() {
333: return getMinute(localtime);
334: }
335:
336: /**
337: * Gets the minute field of the given calendar.
338: *
339: * @param calendar
340: * the calendar to get the field value from
341: * @return the field value
342: */
343: public int getMinute(final Calendar calendar) {
344: return get(calendar, Calendar.MINUTE);
345: }
346:
347: /**
348: * Gets the month field of the current calendar.
349: *
350: * @return the field value
351: */
352: public int getMonth() {
353: return getMonth(localtime);
354: }
355:
356: /**
357: * Gets the month field of the given calendar.
358: *
359: * @param calendar
360: * the calendar to get the field value from
361: * @return the field value
362: */
363: public int getMonth(final Calendar calendar) {
364: return get(calendar, Calendar.MONTH);
365: }
366:
367: /**
368: * Gets the second field of the current calendar.
369: *
370: * @return the field value
371: */
372: public int getSecond() {
373: return getSecond(localtime);
374: }
375:
376: /**
377: * Gets the second field of the given calendar.
378: *
379: * @param calendar
380: * the calendar to get the field value from
381: * @return the field value
382: */
383: public int getSecond(final Calendar calendar) {
384: return get(calendar, Calendar.SECOND);
385: }
386:
387: /**
388: * Gets the year field of the current calendar.
389: *
390: * @return the field value
391: */
392: public int getYear() {
393: return getYear(localtime);
394: }
395:
396: /**
397: * Gets the year field of the given calendar.
398: *
399: * @param calendar
400: * the calendar to get the field value from
401: * @return the field value
402: */
403: public int getYear(final Calendar calendar) {
404: return get(calendar, Calendar.YEAR);
405: }
406:
407: /**
408: * Adds the given duration to this time object, moving the time into the
409: * future.
410: *
411: * @param duration
412: * The duration to add
413: * @return This time - duration
414: */
415: public Time subtract(final Duration duration) {
416: return milliseconds(getMilliseconds()
417: - duration.getMilliseconds());
418: }
419:
420: /**
421: * Subtract time from this and returns the difference as a duration object.
422: *
423: * @param that
424: * The time to subtract
425: * @return The duration between this and that time
426: */
427: public Duration subtract(final Time that) {
428: return Duration.milliseconds(this .getMilliseconds()
429: - that.getMilliseconds());
430: }
431:
432: /**
433: * Gets a Date object for this time object. A new Date object is always
434: * returned rather than attempting to cache a date since Date is mutable.
435: *
436: * @return This immutable time object as a mutable java.util.Date object
437: */
438: public Date toDate() {
439: return new Date(getMilliseconds());
440: }
441:
442: /**
443: * Converts this time to a date string using the date formatter
444: * 'yyyy.MM.dd'.
445: *
446: * @return The date string
447: */
448: public String toDateString() {
449: return toDateString(localtime);
450: }
451:
452: /**
453: * Converts this time to a date string using the formatter 'yyyy.MM.dd'.
454: *
455: * @param calendar
456: * The calendar to use in the conversion
457: * @return The date string
458: */
459: public String toDateString(final Calendar calendar) {
460: synchronized (dateFormat) {
461: synchronized (calendar) {
462: dateFormat.setCalendar(calendar);
463:
464: return dateFormat.format(new Date(getMilliseconds()))
465: .toLowerCase();
466: }
467: }
468: }
469:
470: /**
471: * Converts this time to a string suitable for use in a filesystem name.
472: *
473: * @return This time as a formatted string
474: */
475: public String toString() {
476: return toDateString() + "-" + toTimeString();
477: }
478:
479: /**
480: * Converts this time to a string using the given calendar and format.
481: *
482: * @param calendar
483: * the calendar to use
484: * @param format
485: * the format to use
486: * @return This time as a formatted string
487: */
488: public String toString(final Calendar calendar, final String format) {
489: final SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
490: format);
491: dateTimeFormat.setCalendar(calendar == null ? localtime
492: : calendar);
493: return dateTimeFormat.format(new Date(getMilliseconds()));
494: }
495:
496: /**
497: * Converts this time to a string using the given format.
498: *
499: * @param format
500: * the format to use
501: * @return This time as a formatted string
502: */
503: public String toString(final String format) {
504: return toString(null, format);
505: }
506: }
|