001: package org.apache.velocity.tools.generic;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.lang.reflect.Field;
023: import java.text.DateFormat;
024: import java.text.SimpleDateFormat;
025: import java.util.Date;
026: import java.util.Calendar;
027: import java.util.Locale;
028: import java.util.Map;
029: import java.util.TimeZone;
030:
031: /**
032: * Tool for working with {@link Date} and {@link Calendar}
033: * in Velocity templates. It is useful for accessing and
034: * formatting the "current" date as well as for formatting
035: * arbitrary {@link Date} and {@link Calendar} objects. Also
036: * the tool can be used to retrieve {@link DateFormat} instances
037: * or make conversions to and from various date types.
038: * <p><pre>
039: * Example of formatting the "current" date:
040: * $date -> Oct 19, 2003 9:54:50 PM
041: * $date.long -> October 19, 2003 9:54:50 PM PDT
042: * $date.medium_time -> 9:54:50 PM
043: * $date.full_date -> Sunday, October 19, 2003
044: * $date.get('default','short') -> Oct 19, 2003 9:54 PM
045: * $date.get('yyyy-M-d H:m:s') -> 2003-10-19 21:54:50
046: *
047: * Example of formatting an arbitrary date:
048: * $myDate -> Tue Oct 07 03:14:50 PDT 2003
049: * $date.format('medium',$myDate) -> Oct 7, 2003 3:14:50 AM
050: *
051: * Example toolbox.xml config (if you want to use this with VelocityView):
052: * <tool>
053: * <key>date</key>
054: * <scope>application</scope>
055: * <class>org.apache.velocity.tools.generic.DateTool</class>
056: * <parameter name="format" value="yyyy-M-d"/>
057: * </tool>
058: * </pre></p>
059: *
060: * <p>The methods of this tool are highly interconnected, and overriding
061: * key methods provides an easy way to create subclasses that use
062: * a non-default format, calendar, locale, or timezone.</p>
063: *
064: * @author Nathan Bubna
065: * @since VelocityTools 1.0
066: * @version $Revision: 493081 $ $Date: 2007-01-05 08:48:09 -0800 (Fri, 05 Jan 2007) $
067: */
068: public class DateTool {
069:
070: /**
071: * The default format to be used when none is specified.
072: * @since VelocityTools 1.1
073: */
074: public static final String DEFAULT_FORMAT = "default";
075:
076: /**
077: * The key used for specifying a default format via toolbox params.
078: * @since VelocityTools 1.3
079: */
080: public static final String DEFAULT_FORMAT_KEY = "format";
081:
082: private String format = DEFAULT_FORMAT;
083:
084: /**
085: * Default constructor.
086: */
087: public DateTool() {
088: // do nothing
089: }
090:
091: /**
092: * Looks for a default format value in the given params.
093: * @since VelocityTools 1.3
094: */
095: public void configure(Map params) {
096: ValueParser parser = new ValueParser(params);
097: String format = parser.getString(DEFAULT_FORMAT_KEY);
098: if (format != null) {
099: setFormat(format);
100: }
101: }
102:
103: // ------------------------- system date access ------------------
104:
105: /**
106: * @return the system's current time as the number of milliseconds
107: * elapsed since January 1, 1970, 00:00:00 GMT.
108: */
109: public static final long getSystemTime() {
110: return getSystemCalendar().getTime().getTime();
111: }
112:
113: /**
114: * @return the system's current time as a {@link Date}
115: */
116: public static final Date getSystemDate() {
117: return getSystemCalendar().getTime();
118: }
119:
120: /**
121: * @return the system's current time as a {@link Calendar}
122: */
123: public static final Calendar getSystemCalendar() {
124: return Calendar.getInstance();
125: }
126:
127: // ------------------------- default parameter access ----------------
128:
129: /**
130: * This implementation returns the default locale. Subclasses
131: * may override this to return alternate locales. Please note that
132: * doing so will affect all formatting methods where no locale is
133: * specified in the parameters.
134: *
135: * @return the default {@link Locale}
136: */
137: public Locale getLocale() {
138: return Locale.getDefault();
139: }
140:
141: /**
142: * This implementation returns the default TimeZone. Subclasses
143: * may override this to return alternate timezones. Please note that
144: * doing so will affect all formatting methods where no timezone is
145: * specified in the parameters.
146: *
147: * @return the default {@link TimeZone}
148: */
149: public TimeZone getTimeZone() {
150: return TimeZone.getDefault();
151: }
152:
153: /**
154: * Returns a {@link Date} derived from the result of {@link #getCalendar}
155: *
156: * @return a {@link Date} derived from the result of {@link #getCalendar}
157: */
158: public Date getDate() {
159: return getCalendar().getTime();
160: }
161:
162: /**
163: * Returns a {@link Calendar} instance created using the timezone and
164: * locale returned by getTimeZone() and getLocale(). This allows subclasses
165: * to easily override the default locale and timezone used by this tool.
166: *
167: * <p>Sub-classes may override this method to return a Calendar instance
168: * not based on the system date.
169: * Doing so will also cause the getDate(), get(String), get(String,String),
170: * and toString() methods to return dates equivalent to the Calendar
171: * returned by this method, because those methods return values derived
172: * from the result of this method.</p>
173: *
174: * @return a {@link Calendar} instance created using the results of
175: * {@link #getTimeZone()} and {@link #getLocale()}.
176: * @see Calendar#getInstance(TimeZone zone, Locale aLocale)
177: */
178: public Calendar getCalendar() {
179: return Calendar.getInstance(getTimeZone(), getLocale());
180: }
181:
182: /**
183: * Return the pattern or style to be used for formatting dates when none
184: * is specified. This implementation gives a 'default' date-time format.
185: * Subclasses may override this to provide a different default format.
186: *
187: * <p>This can now be configured via the toolbox definition.
188: * Add a <code><parameter name="format" value="short"/><code>
189: * to your date tool configuration.</p>
190: *
191: * @since VelocityTools 1.1
192: */
193: public String getFormat() {
194: return format;
195: }
196:
197: /**
198: * Sets the default format for this instance. This is protected,
199: * because templates ought not to be using it; hat would not
200: * be threadsafe so far as templates are concerned.
201: *
202: * @since VelocityTools 1.3
203: */
204: protected void setFormat(String format) {
205: this .format = format;
206: }
207:
208: // ------------------------- date value access ---------------------------
209:
210: /**
211: * Returns the year value of the date returned by {@link #getCalendar()}.
212: *
213: * @since VelocityTools 1.2
214: */
215: public Integer getYear() {
216: return getYear(getCalendar());
217: }
218:
219: /**
220: * Returns the year value of the specified date.
221: *
222: * @since VelocityTools 1.2
223: */
224: public Integer getYear(Object date) {
225: return getValue(Calendar.YEAR, date);
226: }
227:
228: /**
229: * Returns the month value of the date returned by {@link #getCalendar()}.
230: *
231: * @since VelocityTools 1.2
232: */
233: public Integer getMonth() {
234: return getMonth(getCalendar());
235: }
236:
237: /**
238: * Returns the month value of the specified date.
239: *
240: * @since VelocityTools 1.2
241: */
242: public Integer getMonth(Object date) {
243: return getValue(Calendar.MONTH, date);
244: }
245:
246: /**
247: * Returns the day (of the month) value of the date
248: * returned by {@link #getCalendar()}.
249: * <br><br>
250: * NOTE: Unlike java.util.Date, this returns the day of the month.
251: * It is equivalent to Date.getDate() and
252: * Calendar.get(Calendar.DAY_OF_MONTH). We could not call this method
253: * getDate() because that already exists in this class with a different
254: * function.
255: *
256: * @since VelocityTools 1.2
257: */
258: public Integer getDay() {
259: return getDay(getCalendar());
260: }
261:
262: /**
263: * Returns the day (of the month) value for the specified date.
264: * <br><br>
265: * NOTE: Unlike java.util.Date, this returns the day of the month.
266: * It is equivalent to Date.getDate() and
267: * Calendar.get(Calendar.DAY_OF_MONTH). We could not call this method
268: * getDate() because that already exists in this class with a different
269: * function.
270: *
271: * @since VelocityTools 1.2
272: */
273: public Integer getDay(Object date) {
274: return getValue(Calendar.DAY_OF_MONTH, date);
275: }
276:
277: /**
278: * Return the specified value of the date returned by
279: * {@link #getCalendar()} or null if the field is invalid.
280: *
281: * @since VelocityTools 1.2
282: */
283: public Integer getValue(Object field) {
284: return getValue(field, getCalendar());
285: }
286:
287: /**
288: * Returns the specified value of the specified date,
289: * or null if the field or date is invalid. The field may be
290: * an Integer or it may be the name of the field as a String.
291: *
292: * @param field the corresponding Integer value or String name of the desired value
293: * @param date the date/calendar from which the field value will be taken
294: * @since VelocityTools 1.2
295: */
296: public Integer getValue(Object field, Object date) {
297: if (field == null) {
298: return null;
299: }
300:
301: int fieldValue;
302: if (field instanceof Integer) {
303: fieldValue = ((Integer) field).intValue();
304: }
305: // all the public static field names are upper case
306: String fstr = field.toString().toUpperCase();
307: try {
308: Field clsf = Calendar.class.getField(fstr);
309: fieldValue = clsf.getInt(Calendar.getInstance());
310: } catch (Exception e) {
311: return null;
312: }
313: return getValue(fieldValue, date);
314: }
315:
316: /**
317: * Returns the specified value of the specified date,
318: * or null if the field or date is invalid.
319: *
320: * @param field the int for the desired field (e.g. Calendar.MONTH)
321: * @param date the date/calendar from which the field value will be taken
322: * @since VelocityTools 1.2
323: */
324: public Integer getValue(int field, Object date) {
325: Calendar cal = toCalendar(date);
326: if (cal == null) {
327: return null;
328: }
329: return new Integer(cal.get(field));
330: }
331:
332: // ------------------------- formatting methods ---------------------------
333:
334: /**
335: * Returns a formatted string representing the date returned by
336: * {@link #getDate()}. In its default implementation, this method
337: * allows you to retrieve the current date in standard formats by
338: * simply doing things like <code>$date.medium</code> or
339: * <code>$date.full</code>. If you want only the date or time portion
340: * you can specify that along with the standard formats. (e.g.
341: * <code>$date.medium_date</code> or <code>$date.short_time</code>)
342: * More complex or custom formats can be retrieved
343: * by using the full method syntax. (e.g. $date.get('E, MMMM d'))
344: *
345: * @param format the formatting instructions
346: * @return a formatted representation of the date returned by
347: * {@link #getDate()}
348: * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
349: * @since VelocityTools 1.1
350: */
351: public String get(String format) {
352: return format(format, getDate());
353: }
354:
355: /**
356: * Returns a formatted string representing the date and/or time given by
357: * {@link #getDate()} in standard, localized patterns.
358: *
359: * @param dateStyle the style pattern for the date
360: * @param timeStyle the style pattern for the time
361: * @return a formatted representation of the date returned by
362: * {@link #getDate()}
363: * @see DateFormat
364: * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
365: * @since VelocityTools 1.1
366: */
367: public String get(String dateStyle, String timeStyle) {
368: return format(dateStyle, timeStyle, getDate(), getLocale());
369: }
370:
371: /**
372: * Converts the specified object to a date and formats it according to
373: * the pattern or style returned by {@link #getFormat()}.
374: *
375: * @param obj the date object to be formatted
376: * @return the specified date formatted as a string
377: * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
378: * @since VelocityTools 1.1
379: */
380: public String format(Object obj) {
381: return format(getFormat(), obj);
382: }
383:
384: /**
385: * Converts the specified object to a date and returns
386: * a formatted string representing that date in the locale
387: * returned by {@link #getLocale()}.
388: *
389: * @param format the formatting instructions
390: * @param obj the date object to be formatted
391: * @return a formatted string for this locale representing the specified
392: * date or <code>null</code> if the parameters are invalid
393: * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
394: */
395: public String format(String format, Object obj) {
396: return format(format, obj, getLocale());
397: }
398:
399: /**
400: * Converts the specified object to a date and returns
401: * a formatted string representing that date in the specified
402: * {@link Locale}.
403: *
404: * @param format the formatting instructions
405: * @param obj the date object to be formatted
406: * @param locale the locale to be used when formatting
407: * @return the given date as a formatted string
408: * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
409: */
410: public String format(String format, Object obj, Locale locale) {
411: return format(format, obj, locale, getTimeZone());
412: }
413:
414: /**
415: * Returns a formatted string representing the specified date,
416: * {@link Locale}, and {@link TimeZone}.
417: *
418: * <p>
419: * The specified format may be a standard style pattern ('full', 'long',
420: * 'medium', 'short', or 'default').
421: * </p>
422: * <p>
423: * You may also specify that you want only the date or time portion be
424: * appending '_date' or '_time' respectively to the standard style pattern.
425: * (e.g. 'full_date' or 'long_time')
426: * </p>
427: * <p>
428: * If the format fits neither of these patterns, then the output
429: * will be formatted according to the symbols defined by
430: * {@link SimpleDateFormat}:
431: * <pre>
432: * Symbol Meaning Presentation Example
433: * ------ ------- ------------ -------
434: * G era designator (Text) AD
435: * y year (Number) 1996
436: * M month in year (Text & Number) July & 07
437: * d day in month (Number) 10
438: * h hour in am/pm (1~12) (Number) 12
439: * H hour in day (0~23) (Number) 0
440: * m minute in hour (Number) 30
441: * s second in minute (Number) 55
442: * S millisecond (Number) 978
443: * E day in week (Text) Tuesday
444: * D day in year (Number) 189
445: * F day of week in month (Number) 2 (2nd Wed in July)
446: * w week in year (Number) 27
447: * W week in month (Number) 2
448: * a am/pm marker (Text) PM
449: * k hour in day (1~24) (Number) 24
450: * K hour in am/pm (0~11) (Number) 0
451: * z time zone (Text) Pacific Standard Time
452: * ' escape for text (Delimiter)
453: * '' single quote (Literal) '
454: *
455: * Examples: "E, MMMM d" will result in "Tue, July 24"
456: * "EEE, M-d (H:m)" will result in "Tuesday, 7-24 (14:12)"
457: * </pre>
458: * </p>
459: *
460: * @param format the custom or standard pattern to be used
461: * @param obj the date to format
462: * @param locale the {@link Locale} to format the date for
463: * @param timezone the {@link TimeZone} to be used when formatting
464: * @return a formatted string representing the specified date or
465: * <code>null</code> if the parameters are invalid
466: * @since VelocityTools 1.1
467: */
468: public String format(String format, Object obj, Locale locale,
469: TimeZone timezone) {
470: Date date = toDate(obj);
471: DateFormat df = getDateFormat(format, locale, timezone);
472: if (date == null || df == null) {
473: return null;
474: }
475: return df.format(date);
476: }
477:
478: /**
479: * Returns the specified date as a string formatted according to the
480: * specified date and/or time styles.
481: *
482: * @param dateStyle the style pattern for the date
483: * @param timeStyle the style pattern for the time
484: * @param obj the date to be formatted
485: * @return a formatted representation of the given date
486: * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
487: * @since VelocityTools 1.1
488: */
489: public String format(String dateStyle, String timeStyle, Object obj) {
490: return format(dateStyle, timeStyle, obj, getLocale());
491: }
492:
493: /**
494: * Returns the specified date as a string formatted according to the
495: * specified {@link Locale} and date and/or time styles.
496: *
497: * @param dateStyle the style pattern for the date
498: * @param timeStyle the style pattern for the time
499: * @param obj the date to be formatted
500: * @param locale the {@link Locale} to be used for formatting the date
501: * @return a formatted representation of the given date
502: * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
503: * @since VelocityTools 1.1
504: */
505: public String format(String dateStyle, String timeStyle,
506: Object obj, Locale locale) {
507: return format(dateStyle, timeStyle, obj, locale, getTimeZone());
508: }
509:
510: /**
511: * Returns the specified date as a string formatted according to the
512: * specified {@link Locale} and date and/or time styles.
513: *
514: * @param dateStyle the style pattern for the date
515: * @param timeStyle the style pattern for the time
516: * @param obj the date to be formatted
517: * @param locale the {@link Locale} to be used for formatting the date
518: * @param timezone the {@link TimeZone} the date should be formatted for
519: * @return a formatted representation of the given date
520: * @see java.text.DateFormat
521: * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
522: * @since VelocityTools 1.1
523: */
524: public String format(String dateStyle, String timeStyle,
525: Object obj, Locale locale, TimeZone timezone) {
526: Date date = toDate(obj);
527: DateFormat df = getDateFormat(dateStyle, timeStyle, locale,
528: timezone);
529: if (date == null || df == null) {
530: return null;
531: }
532: return df.format(date);
533: }
534:
535: // -------------------------- DateFormat creation methods --------------
536:
537: /**
538: * Returns a {@link DateFormat} instance for the specified
539: * format, {@link Locale}, and {@link TimeZone}. If the format
540: * specified is a standard style pattern, then a date-time instance
541: * will be returned with both the date and time styles set to the
542: * specified style. If it is a custom format, then a customized
543: * {@link SimpleDateFormat} will be returned.
544: *
545: * @param format the custom or standard formatting pattern to be used
546: * @param locale the {@link Locale} to be used
547: * @param timezone the {@link TimeZone} to be used
548: * @return an instance of {@link DateFormat}
549: * @see SimpleDateFormat
550: * @see DateFormat
551: * @since VelocityTools 1.1
552: */
553: public DateFormat getDateFormat(String format, Locale locale,
554: TimeZone timezone) {
555: if (format == null) {
556: return null;
557: }
558:
559: DateFormat df = null;
560: // do they want a date instance
561: if (format.endsWith("_date")) {
562: String fmt = format.substring(0, format.length() - 5);
563: int style = getStyleAsInt(fmt);
564: df = getDateFormat(style, -1, locale, timezone);
565: }
566: // do they want a time instance?
567: else if (format.endsWith("_time")) {
568: String fmt = format.substring(0, format.length() - 5);
569: int style = getStyleAsInt(fmt);
570: df = getDateFormat(-1, style, locale, timezone);
571: }
572: // ok, they either want a custom or date-time instance
573: else {
574: int style = getStyleAsInt(format);
575: if (style < 0) {
576: // we have a custom format
577: df = new SimpleDateFormat(format, locale);
578: df.setTimeZone(timezone);
579: } else {
580: // they want a date-time instance
581: df = getDateFormat(style, style, locale, timezone);
582: }
583: }
584: return df;
585: }
586:
587: /**
588: * Returns a {@link DateFormat} instance for the specified
589: * date style, time style, {@link Locale}, and {@link TimeZone}.
590: *
591: * @param dateStyle the date style
592: * @param timeStyle the time style
593: * @param locale the {@link Locale} to be used
594: * @param timezone the {@link TimeZone} to be used
595: * @return an instance of {@link DateFormat}
596: * @see #getDateFormat(int timeStyle, int dateStyle, Locale locale, TimeZone timezone)
597: * @since VelocityTools 1.1
598: */
599: public DateFormat getDateFormat(String dateStyle, String timeStyle,
600: Locale locale, TimeZone timezone) {
601: int ds = getStyleAsInt(dateStyle);
602: int ts = getStyleAsInt(timeStyle);
603: return getDateFormat(ds, ts, locale, timezone);
604: }
605:
606: /**
607: * Returns a {@link DateFormat} instance for the specified
608: * time style, date style, {@link Locale}, and {@link TimeZone}.
609: *
610: * @param dateStyle the date style (date will be ignored if this is
611: * less than zero and the date style is not)
612: * @param timeStyle the time style (time will be ignored if this is
613: * less than zero and the date style is not)
614: * @param locale the {@link Locale} to be used
615: * @param timezone the {@link TimeZone} to be used
616: * @return an instance of {@link DateFormat} or <code>null</code>
617: * if an instance cannot be constructed with the given
618: * parameters
619: * @since VelocityTools 1.1
620: */
621: protected DateFormat getDateFormat(int dateStyle, int timeStyle,
622: Locale locale, TimeZone timezone) {
623: try {
624: DateFormat df;
625: if (dateStyle < 0 && timeStyle < 0) {
626: // no style was specified, use default instance
627: df = DateFormat.getInstance();
628: } else if (timeStyle < 0) {
629: // only a date style was specified
630: df = DateFormat.getDateInstance(dateStyle, locale);
631: } else if (dateStyle < 0) {
632: // only a time style was specified
633: df = DateFormat.getTimeInstance(timeStyle, locale);
634: } else {
635: df = DateFormat.getDateTimeInstance(dateStyle,
636: timeStyle, locale);
637: }
638: df.setTimeZone(timezone);
639: return df;
640: } catch (Exception suppressed) {
641: // let it go...
642: return null;
643: }
644: }
645:
646: /**
647: * Checks a string to see if it matches one of the standard DateFormat
648: * style patterns: FULL, LONG, MEDIUM, SHORT, or DEFAULT. If it does,
649: * it will return the integer constant for that pattern. If not, it
650: * will return -1.
651: *
652: * @see DateFormat
653: * @param style the string to be checked
654: * @return the int identifying the style pattern
655: * @since VelocityTools 1.1
656: */
657: protected int getStyleAsInt(String style) {
658: // avoid needlessly running through all the string comparisons
659: if (style == null || style.length() < 4 || style.length() > 7) {
660: return -1;
661: }
662: if (style.equalsIgnoreCase("full")) {
663: return DateFormat.FULL;
664: }
665: if (style.equalsIgnoreCase("long")) {
666: return DateFormat.LONG;
667: }
668: if (style.equalsIgnoreCase("medium")) {
669: return DateFormat.MEDIUM;
670: }
671: if (style.equalsIgnoreCase("short")) {
672: return DateFormat.SHORT;
673: }
674: if (style.equalsIgnoreCase("default")) {
675: return DateFormat.DEFAULT;
676: }
677: // ok, it's not any of the standard patterns
678: return -1;
679: }
680:
681: // ------------------------- date conversion methods ---------------
682:
683: /**
684: * Converts an object to an instance of {@link Date} using the
685: * format returned by {@link #getFormat()},the {@link Locale} returned
686: * by {@link #getLocale()}, and the {@link TimeZone} returned by
687: * {@link #getTimeZone()} if the object is not already an instance
688: * of Date, Calendar, or Long.
689: *
690: * @param obj the date to convert
691: * @return the object as a {@link Date} or <code>null</code> if no
692: * conversion is possible
693: */
694: public Date toDate(Object obj) {
695: return toDate(getFormat(), obj, getLocale(), getTimeZone());
696: }
697:
698: /**
699: * Converts an object to an instance of {@link Date} using the
700: * specified format,the {@link Locale} returned by
701: * {@link #getLocale()}, and the {@link TimeZone} returned by
702: * {@link #getTimeZone()} if the object is not already an instance
703: * of Date, Calendar, or Long.
704: *
705: * @param format - the format the date is in
706: * @param obj - the date to convert
707: * @return the object as a {@link Date} or <code>null</code> if no
708: * conversion is possible
709: * @see #toDate(String format, Object obj, Locale locale)
710: */
711: public Date toDate(String format, Object obj) {
712: return toDate(format, obj, getLocale(), getTimeZone());
713: }
714:
715: /**
716: * Converts an object to an instance of {@link Date} using the
717: * specified format and {@link Locale} if the object is not already
718: * an instance of Date, Calendar, or Long.
719: *
720: * @param format - the format the date is in
721: * @param obj - the date to convert
722: * @param locale - the {@link Locale}
723: * @return the object as a {@link Date} or <code>null</code> if no
724: * conversion is possible
725: * @see SimpleDateFormat#parse
726: */
727: public Date toDate(String format, Object obj, Locale locale) {
728: return toDate(format, obj, locale, getTimeZone());
729: }
730:
731: /**
732: * Converts an object to an instance of {@link Date} using the
733: * specified format, {@link Locale}, and {@link TimeZone} if the
734: * object is not already an instance of Date, Calendar, or Long.
735: *
736: * @param format - the format the date is in
737: * @param obj - the date to convert
738: * @param locale - the {@link Locale}
739: * @param timezone - the {@link TimeZone}
740: * @return the object as a {@link Date} or <code>null</code> if no
741: * conversion is possible
742: * @see #getDateFormat
743: * @see SimpleDateFormat#parse
744: */
745: public Date toDate(String format, Object obj, Locale locale,
746: TimeZone timezone) {
747: if (obj == null) {
748: return null;
749: }
750: if (obj instanceof Date) {
751: return (Date) obj;
752: }
753: if (obj instanceof Calendar) {
754: return ((Calendar) obj).getTime();
755: }
756: if (obj instanceof Number) {
757: Date d = new Date();
758: d.setTime(((Number) obj).longValue());
759: return d;
760: }
761: try {
762: //try parsing w/a customized SimpleDateFormat
763: DateFormat parser = getDateFormat(format, locale, timezone);
764: return parser.parse(String.valueOf(obj));
765: } catch (Exception e) {
766: return null;
767: }
768: }
769:
770: /**
771: * Converts an object to an instance of {@link Calendar} using the
772: * locale returned by {@link #getLocale()} if necessary.
773: *
774: * @param obj the date to convert
775: * @return the converted date
776: * @see #toCalendar(Object obj, Locale locale)
777: */
778: public Calendar toCalendar(Object obj) {
779: return toCalendar(obj, getLocale());
780: }
781:
782: /**
783: * Converts an object to an instance of {@link Calendar} using the
784: * locale returned by {@link #getLocale()} if necessary.
785: *
786: * @param obj the date to convert
787: * @param locale the locale used
788: * @return the converted date
789: * @see #toDate(String format, Object obj, Locale locale)
790: * @see Calendar
791: */
792: public Calendar toCalendar(Object obj, Locale locale) {
793: if (obj == null) {
794: return null;
795: }
796: if (obj instanceof Calendar) {
797: return (Calendar) obj;
798: }
799: //try to get a date out of it
800: Date date = toDate(obj);
801: if (date == null) {
802: return null;
803: }
804:
805: //convert the date to a calendar
806: Calendar cal = Calendar.getInstance(locale);
807: cal.setTime(date);
808: // HACK: Force all fields to update. see link for explanation of this.
809: //http://java.sun.com/j2se/1.4/docs/api/java/util/Calendar.html
810: cal.getTime();
811: return cal;
812: }
813:
814: // ------------------------- default toString() implementation ------------
815:
816: /**
817: * @return the result of {@link #getDate()} formatted according to the result
818: * of {@link #getFormat()}.
819: * @see #format(String format, Object obj)
820: */
821: public String toString() {
822: return format(getFormat(), getDate());
823: }
824:
825: }
|