You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2007/02/16 02:27:20 UTC
svn commit: r508269 - in
/velocity/tools/trunk/src/java/org/apache/velocity/tools/generic:
ComparisonDateTool.java times.properties
Author: nbubna
Date: Thu Feb 15 17:27:20 2007
New Revision: 508269
URL: http://svn.apache.org/viewvc?view=rev&rev=508269
Log:
add the long overdue third rewrite of what was once Chris Townsen's 'ExtendedDateTool', now named 'ComparisonDateTool'
Added:
velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java (with props)
velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties (with props)
Added: velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java?view=auto&rev=508269
==============================================================================
--- velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java (added)
+++ velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java Thu Feb 15 17:27:20 2007
@@ -0,0 +1,697 @@
+package org.apache.velocity.tools.generic;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Tool for comparing {@link Date} and {@link Calendar} values
+ * in Velocity templates. This is a subclass of {@link DateTool}
+ * and thus provides all the functionality of that tool and
+ * augments it with the ability to find the relationship between
+ * any date and the current date, or between any two dates.
+ * This comparison can result in either a textual representation
+ * of the relationship (e.g. "3 weeks, 2 days ago", "tomorrow", or
+ * "3 hrs away") or the value of a specific time unit may be requested.
+ * When using the textual representations, you can configure the
+ * tool to use alternate resource bundles and to skip over units
+ * you do not want to be included.
+ * <p><pre>
+ * Example of formatting the "current" date:
+ * $date.whenIs('2005-07-04') -> 1 year ago
+ * $date.whenIs('2007-02-15').full -> 1 year 32 weeks 2 days 17 hours 38 minutes 44 seconds 178 milliseconds ago
+ * $date.whenIs('2007-02-15').days -> -730
+ * $date.whenIs($date.calendar) -> now
+ * $date.whenIs('2005-07-04', '2005-07-04') -> same time
+ * $date.difference('2005-07-04','2005-07-04') -> 0 milliseconds
+ * $date.difference('2005-07-04','2007-02-15').abbr -> 1 yr
+ *
+ * Example toolbox.xml config (if you want to use this with VelocityView):
+ * <tool>
+ * <key>date</key>
+ * <scope>application</scope>
+ * <class>org.apache.velocity.tools.generic.ComparisonDateTool</class>
+ * <parameter name="format" value="yyyy-MM-dd"/>
+ * <parameter name="bundle" value="org.apache.velocity.tools.generic.times"/>
+ * <parameter name="depth" value="1"/>
+ * <parameter name="skip" value="month,week,millisecond"/>
+ * </tool>
+ * </pre></p>
+ *
+ * @author Nathan Bubna
+ * @author Chris Townsen
+ * @since VelocityTools 1.4
+ * @version $Revision$ $Date: 2006-04-04 12:35:17 -0700 (Tue, 04 Apr 2006) $
+ */
+public class ComparisonDateTool extends DateTool
+{
+ /** The number of milliseconds in a second. */
+ public static final long MILLIS_PER_SECOND = 1000l;
+
+ /** The number of millseconds in a minute. */
+ public static final long MILLIS_PER_MINUTE = 60l * MILLIS_PER_SECOND;
+
+ /** The number of milliseconds in an hour. */
+ public static final long MILLIS_PER_HOUR = 60l * MILLIS_PER_MINUTE;
+
+ /** The number of milliseconds in a day. */
+ public static final long MILLIS_PER_DAY = 24l * MILLIS_PER_HOUR;
+
+ /** The number of milliseconds in a week. */
+ public static final long MILLIS_PER_WEEK = 7l * MILLIS_PER_DAY;
+
+ /** An approximation of the number of milliseconds in a month. */
+ public static final long MILLIS_PER_MONTH = 30l * MILLIS_PER_DAY;
+
+ /** An approximation of the number of milliseconds in a year. */
+ public static final long MILLIS_PER_YEAR = 365l * MILLIS_PER_DAY;
+
+ /** The key used for specifying a default locale via toolbox params. */
+ public static final String BUNDLE_NAME_KEY = "bundle";
+
+ /** The key used for specifying a different default depth via toolbox params. */
+ public static final String DEPTH_KEY = "depth";
+
+ /** The key used for specifying time units to be skipped over. */
+ public static final String SKIPPED_UNITS_KEY = "skip";
+
+ /** The default path of the relative format resource bundles. */
+ public static final String DEFAULT_BUNDLE_NAME =
+ "org.apache.velocity.tools.generic.times";
+
+
+ // time unit message keys
+ protected static final String MILLISECOND_KEY = "millisecond";
+ protected static final String SECOND_KEY = "second";
+ protected static final String MINUTE_KEY = "minute";
+ protected static final String HOUR_KEY = "hour";
+ protected static final String DAY_KEY = "day";
+ protected static final String WEEK_KEY = "week";
+ protected static final String MONTH_KEY = "month";
+ protected static final String YEAR_KEY = "year";
+
+ /** Array of all time unit message keys to their millisecond conversion factor. */
+ protected static final Map TIME_UNITS;
+ static
+ {
+ Map units = new LinkedHashMap(8);
+ units.put(MILLISECOND_KEY, Long.valueOf(1));
+ units.put(SECOND_KEY, Long.valueOf(MILLIS_PER_SECOND));
+ units.put(MINUTE_KEY, Long.valueOf(MILLIS_PER_MINUTE));
+ units.put(HOUR_KEY, Long.valueOf(MILLIS_PER_HOUR));
+ units.put(DAY_KEY, Long.valueOf(MILLIS_PER_DAY));
+ units.put(WEEK_KEY, Long.valueOf(MILLIS_PER_WEEK));
+ units.put(MONTH_KEY, Long.valueOf(MILLIS_PER_MONTH));
+ units.put(YEAR_KEY, Long.valueOf(MILLIS_PER_YEAR));
+ TIME_UNITS = Collections.unmodifiableMap(units);
+ }
+
+ // special message keys/prefixes/suffixes
+ protected static final String CURRENT_PREFIX = "current.";
+ protected static final String AFTER_KEY = "after";
+ protected static final String BEFORE_KEY = "before";
+ protected static final String EQUAL_KEY = "equal";
+ protected static final String ZERO_KEY = "zero";
+ protected static final String ABBR_SUFFIX = ".abbr";
+ protected static final String ONE_DAY_SUFFIX = ".day";
+ protected static final String PLURAL_SUFFIX = "s";
+
+ // display types
+ protected static final int CURRENT_TYPE = 0;
+ protected static final int RELATIVE_TYPE = 1;
+ protected static final int DIFF_TYPE = 2;
+
+ private String bundleName = DEFAULT_BUNDLE_NAME;
+ private ResourceBundle defaultBundle;
+ private Map timeUnits = TIME_UNITS;
+ private int depth = 1;
+
+
+ /**
+ * Calls the superclass implementation, then looks for a bundle name
+ * and any time units to be skipped.
+ */
+ protected void configure(ValueParser values)
+ {
+ // do DateTool config
+ super.configure(values);
+
+ // look for an alternate bundle
+ String bundle = values.getString(BUNDLE_NAME_KEY);
+ if (bundle != null)
+ {
+ this.bundleName = bundle;
+ }
+
+ this.depth = values.getInt(DEPTH_KEY, 1);
+
+ // look for time units to be ignored
+ String[] skip = values.getStrings(SKIPPED_UNITS_KEY);
+ if (skip != null)
+ {
+ timeUnits = new LinkedHashMap(TIME_UNITS);
+ for (int i=0; i < skip.length; i++)
+ {
+ timeUnits.remove(skip[i]);
+ }
+ }
+ }
+
+ /**
+ * Retrieves the specified text resource.
+ */
+ protected String getText(String key, Locale locale)
+ {
+ Locale defaultLocale = getLocale();
+ ResourceBundle bundle = null;
+ // if there is no locale or the specified locale equals the tool's default
+ if (locale == null || locale.equals(defaultLocale))
+ {
+ if (defaultBundle == null)
+ {
+ // load the bundle for the default locale
+ try
+ {
+ // and cache it
+ defaultBundle = ResourceBundle.getBundle(this.bundleName,
+ defaultLocale);
+ }
+ catch (MissingResourceException e) {}
+ }
+
+ // use the default locale's bundle
+ bundle = defaultBundle;
+ }
+ else
+ {
+ // load the bundle for the specified locale
+ try
+ {
+ bundle = ResourceBundle.getBundle(this.bundleName, locale);
+ }
+ catch (MissingResourceException e) {}
+ }
+
+ // if we found a bundle...
+ if (bundle != null)
+ {
+ try
+ {
+ // try to return the specified key
+ return bundle.getString(key);
+ }
+ catch (MissingResourceException e) {}
+ }
+
+ // otherwise, return the key as an error
+ return "???" + key + "???";
+ }
+
+
+ // ------------------------- static millisecond conversions ----------------
+
+ /**
+ * Returns the number of whole Years in the specified number of milliseconds.
+ */
+ public static long toYears(long ms)
+ {
+ return ms / MILLIS_PER_YEAR;
+ }
+
+ /**
+ * Returns the number of whole Months in the specified number of milliseconds.
+ */
+ public static long toMonths(long ms)
+ {
+ return ms / MILLIS_PER_MONTH;
+ }
+
+ /**
+ * Returns the number of whole Weeks in the specified number of milliseconds.
+ */
+ public static long toWeeks(long ms)
+ {
+ return ms / MILLIS_PER_WEEK;
+ }
+
+ /**
+ * Returns the number of whole Days in the specified number of milliseconds.
+ */
+ public static long toDays(long ms)
+ {
+ return ms / MILLIS_PER_DAY;
+ }
+
+ /**
+ * Returns the number of whole Hours in the specified number of milliseconds.
+ */
+ public static long toHours(long ms)
+ {
+ return ms / MILLIS_PER_HOUR;
+ }
+
+ /**
+ * Returns the number of whole Minutes in the specified number of milliseconds.
+ */
+ public static long toMinutes(long ms)
+ {
+ return ms / MILLIS_PER_MINUTE;
+ }
+
+ /**
+ * Returns the number of whole Seconds in the specified number of milliseconds.
+ */
+ public static long toSeconds(long ms)
+ {
+ return ms / MILLIS_PER_SECOND;
+ }
+
+
+ // ------------------------- date comparison ---------------------------
+
+ /**
+ * Returns a {@link Comparison} between the result of
+ * {@link #getCalendar()} and the specified date. The default
+ * rendering of that Comparison will be the largest unit difference
+ * between the dates followed by a description of their relative position.
+ *
+ * @param date The date in question
+ */
+ public Comparison whenIs(Object then)
+ {
+ return compare(getCalendar(), then, CURRENT_TYPE);
+ }
+
+ /**
+ * Returns a {@link Comparison} between the second specified date
+ * and the first specified date. The default
+ * rendering of that Comparison will be the largest unit difference
+ * between the dates followed by a description of their relative position.
+ *
+ * @param now The date to use as representative of "now"
+ * @param then The date in question
+ */
+ public Comparison whenIs(Object now, Object then)
+ {
+ return compare(now, then, RELATIVE_TYPE);
+ }
+
+ /**
+ * Returns a {@link Comparison} between the result of
+ * the second specified date and the first specified date. The default
+ * rendering of that Comparison will be the largest unit difference
+ * between the dates.
+ *
+ * @param now The date to use as representative of "now"
+ * @param then The secondary date
+ */
+ public Comparison difference(Object now, Object then)
+ {
+ return compare(now, then, DIFF_TYPE);
+ }
+
+ protected Comparison compare(Object now, Object then, int type)
+ {
+ Calendar calThen = toCalendar(then);
+ Calendar calNow = toCalendar(now);
+ if (calThen == null || calNow == null)
+ {
+ return null;
+ }
+
+ long ms = calThen.getTimeInMillis() - calNow.getTimeInMillis();
+ return new Comparison(ms, type, this.depth, false, null);
+ }
+
+
+ /**
+ * @param ms The time in milliseconds
+ * @param type Whether the time should be represented as relative to "now",
+ * relative to some other time, or as a mere difference.
+ * @param depth The maximum number of units deep to show
+ * @param abbr Whether the units should be abbreviated or not
+ * @param loc The locale to be used when looking up resources
+ */
+ protected String toString(long ms, int type, int depth,
+ boolean abbr, Locale loc)
+ {
+ // first check if there is a difference
+ if (ms == 0)
+ {
+ String sameKey = (abbr) ? ABBR_SUFFIX : "";
+ if (type == CURRENT_TYPE)
+ {
+ sameKey = CURRENT_PREFIX + EQUAL_KEY + sameKey;
+ }
+ else if (type == RELATIVE_TYPE)
+ {
+ sameKey = EQUAL_KEY + sameKey;
+ }
+ else
+ {
+ sameKey = ZERO_KEY + sameKey;
+ }
+ return getText(sameKey, loc);
+ }
+
+ boolean isBefore = false;
+ if (ms < 0)
+ {
+ isBefore = true;
+ // convert() only works with positive values
+ ms *= -1;
+ }
+
+ // get the base value
+ String friendly = toString(ms, depth, abbr, loc);
+
+ // if we only want the difference...
+ if (type == DIFF_TYPE)
+ {
+ // add the sign (if negative)
+ if (isBefore)
+ {
+ friendly = "-" + friendly;
+ }
+ // then return without direction suffix
+ return friendly;
+ }
+
+ // otherwise, get the appropriate direction key
+ String directionKey = (isBefore) ? BEFORE_KEY : AFTER_KEY;
+ if (type == CURRENT_TYPE)
+ {
+ directionKey = CURRENT_PREFIX + directionKey;
+
+ if (friendly != null && friendly.startsWith("1"))
+ {
+ // check for the corner case of "1 day ago" or "1 day away"
+ // and convert those to "yesterday" or "tomorrow"
+ String dayKey = (abbr) ? DAY_KEY + ABBR_SUFFIX : DAY_KEY;
+ if (friendly.equals("1 " + getText(dayKey, loc)))
+ {
+ // add .day
+ directionKey += ONE_DAY_SUFFIX;
+ // and return only the value of this key
+ // (which means we throw away the friendly value
+ // and don't bother abbreviating things)
+ return getText(directionKey, loc);
+ }
+ }
+ }
+
+ // in the default bundle, this doesn't change anything.
+ // but in may in user-provided bundles
+ if (abbr)
+ {
+ directionKey += ABBR_SUFFIX;
+ }
+
+ // then combine them
+ return friendly + " " + getText(directionKey, loc);
+ }
+
+
+ /**
+ * Converts the specified positive duration of milliseconds into larger
+ * units up to the specified number of positive units, beginning with the
+ * largest positive unit. e.g.
+ * <code>toString(181453, 3, false, null)</code> will return
+ * "3 minutes 1 second 453 milliseconds",
+ * <code>toString(181453, 2, false, null)</code> will return
+ * "3 minutes 1 second", and
+ * <code>toString(180000, 2, true, null)</code> will return
+ * "3 min".
+ */
+ protected String toString(long diff, int maxUnitDepth,
+ boolean abbreviate, Locale locale)
+ {
+ // these cases should be handled elsewhere
+ if (diff <= 0)
+ {
+ return null;
+ }
+ // can't go any deeper than we have units
+ if (maxUnitDepth > timeUnits.size())
+ {
+ maxUnitDepth = timeUnits.size();
+ }
+
+ long value = 0;
+ long remainder = 0;
+
+ // determine the largest unit and calculate the value and remainder
+ Iterator i = timeUnits.keySet().iterator();
+ String unitKey = (String)i.next();
+ Long unit = (Long)timeUnits.get(unitKey);
+ while (i.hasNext())
+ {
+ // get the next unit
+ String nextUnitKey = (String)i.next();
+ Long nextUnit = (Long)timeUnits.get(nextUnitKey);
+
+ // e.g. if diff < <nextUnit>
+ if (diff < nextUnit.longValue())
+ {
+ // then we're working with <unit>
+ value = diff / unit.longValue();
+ remainder = diff - (value * unit.longValue());
+ break;
+ }
+
+ // shift to the next unit
+ unitKey = nextUnitKey;
+ unit = nextUnit;
+ }
+
+ // if it was years, then we haven't done the math yet
+ if (unitKey.equals(YEAR_KEY))
+ {
+ value = diff / unit.longValue();
+ remainder = diff - (value * unit.longValue());
+ }
+
+ // select proper pluralization
+ if (value != 1)
+ {
+ unitKey += PLURAL_SUFFIX;
+ }
+
+ if (abbreviate)
+ {
+ unitKey += ABBR_SUFFIX;
+ }
+
+ // combine the value and the unit
+ String output = value + " " + getText(unitKey, locale);
+
+ // recurse over the remainder if it exists and more units are allowed
+ if (maxUnitDepth > 1 && remainder > 0)
+ {
+ output += " " + toString(remainder, maxUnitDepth - 1,
+ abbreviate, locale);
+ }
+ return output;
+ }
+
+
+
+ public class Comparison
+ {
+ private long milliseconds = 0;
+ private int type = CURRENT_TYPE;
+ private int maxUnitDepth = 1;
+ private boolean abbreviate = false;
+ private Locale locale;
+
+ public Comparison(long ms, int type, int depth, boolean abbr, Locale loc)
+ {
+ this.milliseconds = ms;
+ this.type = type;
+ this.maxUnitDepth = depth;
+ this.abbreviate = abbr;
+ this.locale = loc;
+ }
+
+ /**
+ * Sets whether or not this comparison is to be rendered in
+ * abbreviated form or not. By default, it is not abbreviated.
+ */
+ public Comparison abbr(boolean abbr)
+ {
+ return new Comparison(this.milliseconds, this.type,
+ this.maxUnitDepth, abbr, this.locale);
+ }
+
+ /**
+ * Set the maximum number of units to render for this comparison.
+ * By default, this is set to 1 unit.
+ */
+ public Comparison depth(int depth)
+ {
+ return new Comparison(this.milliseconds, this.type,
+ depth, this.abbreviate, this.locale);
+ }
+
+ /**
+ * Sets the locale used to look up the textual portions of the
+ * rendering. This defaults to the Locale configured for this tool,
+ * if any. If no locale was configured, this defaults to the system
+ * default.
+ */
+ public Comparison locale(Locale loc)
+ {
+ return new Comparison(this.milliseconds, this.type,
+ this.maxUnitDepth, this.abbreviate, loc);
+ }
+
+ /**
+ * Return the approximate number of years between the dates being compared.
+ */
+ public long getYears()
+ {
+ return ComparisonDateTool.toYears(this.milliseconds);
+ }
+
+ /**
+ * Return the approximate number of months between the dates being compared.
+ */
+ public long getMonths()
+ {
+ return ComparisonDateTool.toMonths(this.milliseconds);
+ }
+
+ /**
+ * Return the number of weeks between the dates being compared.
+ */
+ public long getWeeks()
+ {
+ return ComparisonDateTool.toWeeks(this.milliseconds);
+ }
+
+ /**
+ * Return the number of days between the dates being compared.
+ */
+ public long getDays()
+ {
+ return ComparisonDateTool.toDays(this.milliseconds);
+ }
+
+ /**
+ * Return the number of hours between the dates being compared.
+ */
+ public long getHours()
+ {
+ return ComparisonDateTool.toHours(this.milliseconds);
+ }
+
+ /**
+ * Return the number of minutes between the dates being compared.
+ */
+ public long getMinutes()
+ {
+ return ComparisonDateTool.toMinutes(this.milliseconds);
+ }
+
+ /**
+ * Return the number of seconds between the dates being compared.
+ */
+ public long getSeconds()
+ {
+ return ComparisonDateTool.toSeconds(this.milliseconds);
+ }
+
+ /**
+ * Return the number of milliseconds between the dates being compared.
+ */
+ public long getMilliseconds()
+ {
+ return this.milliseconds;
+ }
+
+ /**
+ * Sets the {@link #depth(int depth)} to which this comparison is rendered
+ * to the maximum number of time units available to the tool. By default,
+ * there are 8 units available, but the tool may be configured to "skip"
+ * any of the standard units, thus shortening the maximum depth.
+ */
+ public Comparison getFull()
+ {
+ return depth(ComparisonDateTool.this.timeUnits.size());
+ }
+
+ /**
+ * Sets this comparison to be rendered as a
+ * {@link ComparisonDateTool#difference}. This effectively means that
+ * the comparison will render as a period of time, without any suffix
+ * to describe the relative position of the dates being compared (e.g. "later"
+ * or "ago").
+ */
+ public Comparison getDifference()
+ {
+ return new Comparison(this.milliseconds, DIFF_TYPE,
+ this.maxUnitDepth, this.abbreviate, this.locale);
+ }
+
+ /**
+ * Sets this comparison to be rendered as if it where generated using
+ * the {@link ComparisonDateTool#whenIs(Object now, Object then)} method.
+ * This effectively means that the comparison will render with a suffix
+ * to describe the relative position of the dates being compared (e.g. "later"
+ * or "ago").
+ */
+ public Comparison getRelative()
+ {
+ return new Comparison(this.milliseconds, RELATIVE_TYPE,
+ this.maxUnitDepth, this.abbreviate, this.locale);
+ }
+
+ /**
+ * This is equivalent to calling {@link #abbr(boolean abbr)} with
+ * {@code true} as the argument, thus setting this comparison to be
+ * rendered in abbreviated form.
+ */
+ public Comparison getAbbr()
+ {
+ return abbr(true);
+ }
+
+ /**
+ * Renders this comparison to a String.
+ */
+ public String toString()
+ {
+ return ComparisonDateTool.this.toString(this.milliseconds,
+ this.type,
+ this.maxUnitDepth,
+ this.abbreviate,
+ this.locale);
+ }
+ }
+
+}
Propchange: velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/ComparisonDateTool.java
------------------------------------------------------------------------------
svn:keywords = Revision
Added: velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties?view=auto&rev=508269
==============================================================================
--- velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties (added)
+++ velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties Thu Feb 15 17:27:20 2007
@@ -0,0 +1,53 @@
+after=later
+before=earlier
+equal=same time
+zero=0 milliseconds
+current.after=away
+current.after.day=tomorrow
+current.before=ago
+current.before.day=yesterday
+current.equal=now
+
+millisecond=millisecond
+milliseconds=milliseconds
+second=second
+seconds=seconds
+minute=minute
+minutes=minutes
+hour=hour
+hours=hours
+day=day
+days=days
+week=week
+weeks=weeks
+month=month
+months=months
+year=year
+years=years
+
+
+# abbreviations
+after.abbr=later
+before.abbr=earlier
+equal.abbr=same
+zero.abbr=0 ms
+current.after.abbr=away
+current.before.abbr=ago
+current.equal.abbr=now
+
+millisecond.abbr=ms
+milliseconds.abbr=ms
+second.abbr=s
+seconds.abbr=s
+minute.abbr=min
+minutes.abbr=min
+hour.abbr=hr
+hours.abbr=hrs
+day.abbr=day
+days.abbr=days
+week.abbr=wk
+weeks.abbr=wks
+month.abbr=mo
+months.abbr=mos
+year.abbr=yr
+years.abbr=yrs
Propchange: velocity/tools/trunk/src/java/org/apache/velocity/tools/generic/times.properties
------------------------------------------------------------------------------
svn:eol-style = native