You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by nb...@apache.org on 2003/10/20 07:15:03 UTC

cvs commit: jakarta-velocity-tools/src/java/org/apache/velocity/tools/generic DateTool.java

nbubna      2003/10/19 22:15:03

  Modified:    src/java/org/apache/velocity/tools/generic DateTool.java
  Log:
  drastic overhaul of DateTool:
   -removed static method declarations
   -add support for standard, localized date/time style patterns
   -deprecate getFormattedDate()
   -add default getFormat()
   -add numerous methods for accessing/formatting dates (either the "current" one or arbitrary ones)
  
  basically, there's a ton of improvements, and they're even backwards compatible as far as templates using them are concerned
  
  Revision  Changes    Path
  1.4       +377 -48   jakarta-velocity-tools/src/java/org/apache/velocity/tools/generic/DateTool.java
  
  Index: DateTool.java
  ===================================================================
  RCS file: /home/cvs/jakarta-velocity-tools/src/java/org/apache/velocity/tools/generic/DateTool.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DateTool.java	4 Jul 2003 05:13:10 -0000	1.3
  +++ DateTool.java	20 Oct 2003 05:15:03 -0000	1.4
  @@ -66,20 +66,38 @@
   
   /**
    * Tool for working with {@link Date} and {@link Calendar}
  - * in Velocity templates.  
  + * in Velocity templates.  It is useful for accessing and
  + * formatting the "current" date as well as for formatting
  + * arbitrary {@link Date} and {@link Calendar} objects. Also
  + * the tool can be used to retrieve {@link DateFormat} instances
  + * or make conversions to and from various date types.
  + * <p><pre>
  + * Example uses:
  + *  $date                         -> Oct 19, 2003 9:54:50 PM
  + *  $date.long                    -> October 19, 2003 9:54:50 PM PDT
  + *  $date.medium_time             -> 9:54:50 PM
  + *  $date.full_date               -> Sunday, October 19, 2003
  + *  $date.get('default','short')  -> Oct 19, 2003 9:54 PM
  + *  $date.get('yyyy-M-d H:m:s')   -> 2003-10-19 21:54:50
    * 
  - * This tool is entirely threadsafe, and has no instance members.  
  + *  $myDate                        -> Tue Oct 07 03:14:50 PDT 2003
  + *  $date.format('medium',$myDate) -> Oct 7, 2003 3:14:50 AM 
  + * </pre></p>
  + *
  + * <p>This tool is entirely threadsafe, and has no instance members.
  + * It may be used in any scope (request, session, or application).
    * As such, the methods are highly interconnected, and overriding 
    * key methods provides an easy way to create subclasses that use 
  - * a non-default calendar, locale, or timezone.
  + * a non-default format, calendar, locale, or timezone.</p>
    *
    * @author <a href="mailto:nathan@esha.com">Nathan Bubna</a>
    * @version $Revision$ $Date$
    */
  -
   public class DateTool
   {
   
  +    /** The default format to be used when none is specified. */
  +    public static final String DEFAULT_FORMAT = "default";
   
       /**
        * Default constructor.
  @@ -110,10 +128,14 @@
       }
   
   
  -    // ------------------------- locale/timezone/date access ----------------
  -
  +    // ------------------------- default parameter access ----------------
   
       /**
  +     * This implementation returns the default locale. Subclasses
  +     * may override this to return alternate locales. Please note that
  +     * doing so will affect all formatting methods where no locale is
  +     * specified in the parameters.
  +     *
        * @return the default {@link Locale}
        */
       public Locale getLocale()
  @@ -121,8 +143,12 @@
           return Locale.getDefault();
       }
   
  -
       /**
  +     * This implementation returns the default TimeZone. Subclasses
  +     * may override this to return alternate timezones. Please note that
  +     * doing so will affect all formatting methods where no timezone is
  +     * specified in the parameters.
  +     *
        * @return the default {@link TimeZone}
        */
       public TimeZone getTimeZone()
  @@ -130,7 +156,6 @@
           return TimeZone.getDefault();
       }
   
  -
       /**
        * Returns a {@link Date} derived from the result of {@link #getCalendar}
        *
  @@ -141,18 +166,17 @@
           return getCalendar().getTime();
       }
   
  -
       /**
        * Returns a {@link Calendar} instance created using the timezone and
        * locale returned by getTimeZone() and getLocale().  This allows subclasses
        * to easily override the default locale and timezone used by this tool.
        *
  -     * Sub-classes may override this method to return a Calendar instance
  +     * <p>Sub-classes may override this method to return a Calendar instance
        * not based on the system date.
  -     * Doing so will also cause the getDate(), getNormalDate(), 
  -     * getFormattedDate(), and toString() methods to return dates equivalent 
  -     * to the Calendar returned by this method, because those methods return
  -     * values derived from the result of this method.
  +     * Doing so will also cause the getDate(), get(String), get(String,String), 
  +     * and toString() methods to return dates equivalent to the Calendar 
  +     * returned by this method, because those methods return values derived 
  +     * from the result of this method.</p>
        *
        * @return a {@link Calendar} instance created using the results of 
        *         {@link #getTimeZone()} and {@link #getLocale()}.
  @@ -163,53 +187,131 @@
           return Calendar.getInstance(getTimeZone(), getLocale());
       }
   
  +    /**
  +     * Return the pattern or style to be used for formatting dates when none
  +     * is specified. This implementation gives a 'default' date-time format. 
  +     * Subclasses may override this to provide a different default format.
  +     *
  +     * <p>NOTE: At some point in the future it may be feasible to configure
  +     * this value via the toolbox definition, but at present, it is not possible
  +     * to specify custom tool configurations there.  For now you should just 
  +     * override this in a subclass to have a different default.</p>
  +     */
  +    public String getFormat()
  +    {
  +        return DEFAULT_FORMAT;
  +    }
  +
   
       // ------------------------- formatting methods ---------------------------
   
       /**
  -     * Returns a formatted string representing the date as returned by
  -     * {@link #getDate()}.
  -     *
  -     * This method uses the same formatting instructions as
  -     * {@link SimpleDateFormat}:
  +     * @deprecated use {@link #get(String format)} instead
  +     */
  +    public String getFormattedDate(String format)
  +    {
  +        return format(format, getDate());
  +    }
  +
  +    /**
  +     * Returns a formatted string representing the date returned by
  +     * {@link #getDate()}.  In its default implementation, this method 
  +     * allows you to retrieve the current date in standard formats by
  +     * simply doing things like <code>$date.medium</code> or 
  +     * <code>$date.full</code>.  If you want only the date or time portion
  +     * you can specify that along with the standard formats. (e.g. 
  +     * <code>$date.medium_date</code> or <code>$date.short_time</code>)
  +     * More complex or custom formats can be retrieved
  +     * by using the full method syntax. (e.g. $date.get('E, MMMM d'))
        *
        * @param format the formatting instructions
  -     * @return a formatted string representing the date returned by
  -     *         {@link #getDate()} or <code>null</code> if the parameters
  -     *         are invalid
  -     * @see #format(String format, Object obj, Locale locale)
  +     * @return a formatted representation of the date returned by
  +     *         {@link #getDate()}
  +     * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
        */
  -    public String getFormattedDate(String format)
  +    public String get(String format)
       {
           return format(format, getDate());
       }
   
  +    /**
  +     * Returns a formatted string representing the date and/or time given by
  +     * {@link #getDate()} in standard, localized patterns.
  +     *
  +     * @param dateStyle the style pattern for the date
  +     * @param timeStyle the style pattern for the time
  +     * @return a formatted representation of the date returned by
  +     *         {@link #getDate()}
  +     * @see DateFormat
  +     * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String get(String dateStyle, String timeStyle)
  +    {
  +        return format(dateStyle, timeStyle, getDate(), getLocale());
  +    }
  +
  +
  +    /**
  +     * Converts the specified object to a date and formats it according to
  +     * the pattern or style returned by {@link #getFormat()}.
  +     * 
  +     * @param obj the date object to be formatted
  +     * @return the specified date formatted as a string
  +     * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String format(Object obj)
  +    {
  +        return format(getFormat(), obj);
  +    }
   
       /**
        * Converts the specified object to a date and returns
  -     * a formatted string representing that date using the locale
  +     * a formatted string representing that date in the locale
        * returned by {@link #getLocale()}.
        *
  -     * This method uses the same formatting instructions as
  -     * {@link SimpleDateFormat}:
  -     *
        * @param format the formatting instructions
        * @param obj the date object to be formatted
        * @return a formatted string for this locale representing the specified
        *         date or <code>null</code> if the parameters are invalid
  -     * @see #format(String format, Object obj, Locale locale)
  +     * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
        */
       public String format(String format, Object obj)
       {
           return format(format, obj, getLocale());
       }
   
  +    /**
  +     * Converts the specified object to a date and returns
  +     * a formatted string representing that date in the specified
  +     * {@link Locale}.
  +     *
  +     * @param format the formatting instructions
  +     * @param obj the date object to be formatted
  +     * @param locale the locale to be used when formatting
  +     * @return the given date as a formatted string
  +     * @see #format(String format, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String format(String format, Object obj, Locale locale)
  +    {
  +        return format(format, obj, locale, getTimeZone());
  +    }
   
       /**
  -     * Returns a formatted string representing the specified date and locale.
  +     * Returns a formatted string representing the specified date,
  +     * {@link Locale}, and {@link TimeZone}.
        *
        * <p>
  -     * This method uses the same formatting instructions as
  +     * The specified format may be a standard style pattern ('full', 'long',
  +     * 'medium', 'short', or 'default').
  +     * </p>
  +     * <p>
  +     * You may also specify that you want only the date or time portion be
  +     * appending '_date' or '_time' respectively to the standard style pattern.
  +     * (e.g. 'full_date' or 'long_time')
  +     * </p>
  +     * <p>
  +     * If the format fits neither of these patterns, then the output 
  +     * will be formatted according to the symbols defined by 
        * {@link SimpleDateFormat}:
        * <pre>
        *   Symbol   Meaning                 Presentation        Example
  @@ -238,22 +340,249 @@
        *   Examples: "E, MMMM d" will result in "Tue, July 24"
        *             "EEE, M-d (H:m)" will result in "Tuesday, 7-24 (14:12)"
        * </pre>
  -     *
  -     * @param format the formatting instructions
  +     * </p>
  +     * 
  +     * @param format the custom or standard pattern to be used
        * @param obj the date to format
        * @param locale the {@link Locale} to format the date for
  +     * @param timezone the {@link TimeZone} to be used when formatting
        * @return a formatted string representing the specified date or
        *         <code>null</code> if the parameters are invalid
        */
  -    public static String format(String format, Object obj, Locale locale)
  +    public String format(String format, Object obj, 
  +                         Locale locale, TimeZone timezone)
       {
           Date date = toDate(obj);
  -        if (date == null || format == null || locale == null)
  +        DateFormat df = getDateFormat(format, locale, timezone);
  +        if (date == null || df == null)
           {
               return null;
           }
  -        SimpleDateFormat formatter = new SimpleDateFormat(format, locale);
  -        return formatter.format(date);
  +        return df.format(date);
  +    }
  +
  +
  +    /**
  +     * Returns the specified date as a string formatted according to the
  +     * specified date and/or time styles.
  +     *
  +     * @param dateStyle the style pattern for the date
  +     * @param timeStyle the style pattern for the time
  +     * @param obj the date to be formatted
  +     * @return a formatted representation of the given date 
  +     * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String format(String dateStyle, String timeStyle, Object obj)
  +    {
  +        return format(dateStyle, timeStyle, obj, getLocale());
  +    }
  +
  +    /**
  +     * Returns the specified date as a string formatted according to the
  +     * specified {@link Locale} and date and/or time styles.
  +     *
  +     * @param dateStyle the style pattern for the date
  +     * @param timeStyle the style pattern for the time
  +     * @param obj the date to be formatted
  +     * @param locale the {@link Locale} to be used for formatting the date
  +     * @return a formatted representation of the given date 
  +     * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String format(String dateStyle, String timeStyle,
  +                         Object obj, Locale locale)
  +    {
  +        return format(dateStyle, timeStyle, obj, locale, getTimeZone());
  +    }
  +
  +    /**
  +     * Returns the specified date as a string formatted according to the
  +     * specified {@link Locale} and date and/or time styles.
  +     *
  +     * @param dateStyle the style pattern for the date
  +     * @param timeStyle the style pattern for the time
  +     * @param obj the date to be formatted
  +     * @param locale the {@link Locale} to be used for formatting the date
  +     * @param timezone the {@link TimeZone} the date should be formatted for
  +     * @return a formatted representation of the given date 
  +     * @see java.text.DateFormat
  +     * @see #format(String dateStyle, String timeStyle, Object obj, Locale locale, TimeZone timezone)
  +     */
  +    public String format(String dateStyle, String timeStyle,
  +                         Object obj, Locale locale, TimeZone timezone)
  +    {
  +        Date date = toDate(obj);
  +        DateFormat df = getDateFormat(dateStyle, timeStyle, locale, timezone);
  +        if (date == null || df == null)
  +        {
  +            return null;
  +        }
  +        return df.format(date);
  +    }
  +
  +
  +    // -------------------------- DateFormat creation methods --------------
  +
  +    /**
  +     * Returns a {@link DateFormat} instance for the specified
  +     * format, {@link Locale}, and {@link TimeZone}.  If the format
  +     * specified is a standard style pattern, then a date-time instance
  +     * will be returned with both the date and time styles set to the 
  +     * specified style.  If it is a custom format, then a customized
  +     * {@link SimpleDateFormat} will be returned.
  +     * 
  +     * @param format the custom or standard formatting pattern to be used
  +     * @param locale the {@link Locale} to be used
  +     * @param timezone the {@link TimeZone} to be used
  +     * @return an instance of {@link DateFormat}
  +     * @see SimpleDateFormat
  +     * @see DateFormat
  +     */
  +    public DateFormat getDateFormat(String format, Locale locale, 
  +                                    TimeZone timezone)
  +    {
  +        if (format == null)
  +        {
  +            return null;
  +        }
  +
  +        DateFormat df = null;
  +        // do they want a date instance
  +        if (format.endsWith("_date"))
  +        {
  +            String fmt = format.substring(0, format.length() - 5);
  +            int style = getStyleAsInt(fmt);
  +            df = getDateFormat(style, -1, locale, timezone);
  +        }
  +        // do they want a time instance?
  +        else if (format.endsWith("_time"))
  +        {
  +            String fmt = format.substring(0, format.length() - 5);
  +            int style = getStyleAsInt(fmt);
  +            df = getDateFormat(-1, style, locale, timezone);
  +        }
  +        // ok, they either want a custom or date-time instance
  +        else
  +        {
  +            int style = getStyleAsInt(format);
  +            if (style < 0)
  +            {
  +                // we have a custom format
  +                df = new SimpleDateFormat(format, locale);
  +                df.setTimeZone(timezone);
  +            }
  +            else
  +            {
  +                // they want a date-time instance
  +                df = getDateFormat(style, style, locale, timezone);
  +            }
  +        }
  +        return df;
  +    }
  +
  +    /**
  +     * Returns a {@link DateFormat} instance for the specified
  +     * date style, time style, {@link Locale}, and {@link TimeZone}.
  +     * 
  +     * @param dateStyle the date style 
  +     * @param timeStyle the time style 
  +     * @param locale the {@link Locale} to be used
  +     * @param timezone the {@link TimeZone} to be used
  +     * @return an instance of {@link DateFormat}
  +     * @see #getDateFormat(int timeStyle, int dateStyle, Locale locale, TimeZone timezone)
  +     */
  +    public DateFormat getDateFormat(String dateStyle, String timeStyle,
  +                                    Locale locale, TimeZone timezone)
  +    {
  +        int ds = getStyleAsInt(dateStyle);
  +        int ts = getStyleAsInt(timeStyle);
  +        return getDateFormat(ds, ts, locale, timezone);
  +    }
  +
  +    /**
  +     * Returns a {@link DateFormat} instance for the specified
  +     * time style, date style, {@link Locale}, and {@link TimeZone}.
  +     * 
  +     * @param dateStyle the date style (date will be ignored if this is
  +     *        less than zero and the date style is not)
  +     * @param timeStyle the time style (time will be ignored if this is
  +     *        less than zero and the date style is not)
  +     * @param locale the {@link Locale} to be used
  +     * @param timezone the {@link TimeZone} to be used
  +     * @return an instance of {@link DateFormat} or <code>null</code>
  +     *         if an instance cannot be constructed with the given
  +     *         parameters
  +     */
  +    protected DateFormat getDateFormat(int dateStyle, int timeStyle, 
  +                                       Locale locale, TimeZone timezone)
  +    {
  +        DateFormat df = null;
  +        try
  +        {
  +            if (dateStyle < 0 && timeStyle < 0)
  +            {
  +                // no style was specified, use default instance
  +                df = DateFormat.getInstance();
  +            }
  +            else if (timeStyle < 0)
  +            {
  +                // only a date style was specified
  +                df = DateFormat.getDateInstance(dateStyle, locale);
  +            }
  +            else if (dateStyle < 0)
  +            {
  +                // only a time style was specified
  +                df = DateFormat.getTimeInstance(timeStyle, locale);
  +            }
  +            else
  +            {
  +                df = DateFormat.getDateTimeInstance(dateStyle, timeStyle, 
  +                                                    locale);
  +            }
  +            df.setTimeZone(timezone);
  +        }
  +        finally
  +        {
  +            return df;
  +        }
  +    }
  +
  +    /**
  +     * Checks a string to see if it matches one of the standard DateFormat
  +     * style patterns: FULL, LONG, MEDIUM, SHORT, or DEFAULT. if it does it will return
  +     * the integer constant for that pattern.  if not, it will return -1.
  +     *
  +     * @see DateFormat
  +     * @param style the string to be checked
  +     * @return the int identifying the style pattern
  +     */
  +    protected int getStyleAsInt(String style)
  +    {
  +        // avoid needlessly running through all the string comparisons
  +        if (style == null || style.length() < 4 || style.length() > 7) {
  +            return -1;
  +        }
  +        if (style.equalsIgnoreCase("full"))
  +        {
  +            return DateFormat.FULL;
  +        }
  +        if (style.equalsIgnoreCase("long"))
  +        {
  +            return DateFormat.LONG;
  +        }
  +        if (style.equalsIgnoreCase("medium"))
  +        {
  +            return DateFormat.MEDIUM;
  +        }
  +        if (style.equalsIgnoreCase("short"))
  +        {
  +            return DateFormat.SHORT;
  +        }
  +        if (style.equalsIgnoreCase("default"))
  +        {
  +            return DateFormat.DEFAULT;
  +        }
  +        // ok, it's not any of the standard patterns
  +        return -1;
       }
   
   
  @@ -268,7 +597,7 @@
        * @return the object as a {@link Date} or <code>null</code> if no
        *         conversion is possible
        */
  -    public static Date toDate(Object obj)
  +    public Date toDate(Object obj)
       {
           if (obj == null)
           {
  @@ -290,6 +619,7 @@
           }
           try
           {
  +            //TODO? add better parsing support?
               //try parsing the obj as String w/a DateFormat
               DateFormat parser = DateFormat.getInstance();
               return parser.parse(String.valueOf(obj));
  @@ -300,7 +630,6 @@
           }
       }
   
  -
       /**
        * Converts an object to an instance of {@link Date} using the
        * specified format and the {@link Locale} returned by 
  @@ -317,8 +646,7 @@
       {
           return toDate(format, obj, getLocale());
       }
  -    
  -    
  +
       /**
        * Converts an object to an instance of {@link Date} using the
        * specified format and {@link Locale}if the object is not already
  @@ -331,7 +659,7 @@
        *         conversion is possible
        * @see SimpleDateFormat#parse
        */
  -    public static Date toDate(String format, Object obj, Locale locale)
  +    public Date toDate(String format, Object obj, Locale locale)
       {
           //first try the easiest conversions
           Date date = toDate(obj);
  @@ -341,6 +669,7 @@
           }
           try
           {
  +            //TODO? add better parsing support?
               //try parsing w/a customized SimpleDateFormat
               SimpleDateFormat parser = new SimpleDateFormat(format, locale);
               return parser.parse(String.valueOf(obj));
  @@ -351,7 +680,6 @@
           }
       }
   
  -
       /**
        * Converts an object to an instance of {@link Calendar} using the
        * locale returned by {@link #getLocale()} if necessary.
  @@ -365,7 +693,6 @@
           return toCalendar(obj, getLocale());
       }
   
  -
       /**
        * Converts an object to an instance of {@link Calendar} using the
        * locale returned by {@link #getLocale()} if necessary.
  @@ -376,7 +703,7 @@
        * @see #toDate(String format, Object obj, Locale locale)
        * @see Calendar
        */
  -    public static Calendar toCalendar(Object obj, Locale locale)
  +    public Calendar toCalendar(Object obj, Locale locale)
       {
           if (obj == null)
           {
  @@ -406,11 +733,13 @@
       // ------------------------- default toString() implementation ------------
   
       /**
  -     * @return the result of {@link #getDate()} as a string
  +     * @return the result of {@link #getDate()} formatted according to the result
  +     *         of {@link #getFormat()}.
  +     * @see #format(String format, Object obj)
        */
       public String toString()
       {
  -        return getDate().toString();
  +        return format(getFormat(), getDate());
       }
   
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org