/* Copyright 2005-2006 Tim Fennell * * Licensed 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. */ package net.sourceforge.stripes.format; import net.sourceforge.stripes.exception.StripesRuntimeException; import java.util.Date; import java.util.Map; import java.util.HashMap; import java.util.Locale; import java.text.DateFormat; import java.text.SimpleDateFormat; /** * <p>Implements a basic formatter for Date objects. Accepts several known types and patterns, as * well as arbitrary patterns. Under the covers uses DateFormat and SimpleDateFormat objects * from the java.text package - it is advised that you become familiar with these classes before * attempting to use custom patterns.</p> * * <p>Format types affect the kind of information that is output. The supported format types * are (values are not case sensitive):</p> * <ul> * <li>date</li> * <li>time</li> * <li>datetime</li> * </ul> * * <p>Format strings affect the format of the selected output. One of the following known values * may be supplied as the format string (named values are not case sensitive). If the value is not * one of the following, it is passed to SimpleDateFormat as a pattern string. * <ul> * <li>short</li> * <li>medium</li> * <li>long</li> * <li>full</li> * </ul> * * @author Tim Fennell */ public class DateFormatter implements Formatter<Date> { /** Maintains a map of named formats that can be used instead of patterns. */ protected static final Map<String,Integer> namedPatterns = new HashMap<String,Integer>(); static { namedPatterns.put("short", DateFormat.SHORT ); namedPatterns.put("medium", DateFormat.MEDIUM); namedPatterns.put("long", DateFormat.LONG ); namedPatterns.put("full", DateFormat.FULL ); } private String formatType; private String formatPattern; private Locale locale; private DateFormat format; /** Sets the format type to be used to render dates as Strings. */ public void setFormatType(String formatType) { this.formatType = formatType; } /** Gets the format type to be used to render dates as Strings. */ public String getFormatType() { return formatType; } /** Sets the named format string or date pattern to use to format the date. */ public void setFormatPattern(String formatPattern) { this.formatPattern = formatPattern; } /** Gets the named format string or date pattern to use to format the date. */ public String getFormatPattern() { return formatPattern; } /** Sets the locale that output String should be in. */ public void setLocale(Locale locale) { this.locale = locale; } /** Gets the locale that output String should be in. */ public Locale getLocale() { return locale; } /** * Constructs the DateFormat used for formatting, based on the values passed to the * various setter methods on the class. If the formatString is one of the named formats * then a DateFormat instance is created of the specified type and format, otherwise * a SimpleDateFormat is constructed using the pattern provided and the formatType is ignored. * * @throws StripesRuntimeException if the formatType is not one of 'date', 'time' or 'datetime'. */ public void init() { // Default these values if they were not supplied if (formatPattern == null) { formatPattern = "short"; } if (formatType == null) { formatType = "date"; } String lcFormatString = formatPattern.toLowerCase(); String lcFormatType = formatType.toLowerCase(); // Now figure out how to construct our date format for our locale if ( namedPatterns.containsKey(lcFormatString) ) { if (lcFormatType.equals("date")) { format = DateFormat.getDateInstance(namedPatterns.get(lcFormatString), locale); } else if (lcFormatType.equals("datetime")) { format = DateFormat.getDateTimeInstance(namedPatterns.get(lcFormatString), namedPatterns.get(lcFormatString), locale); } else if (lcFormatType.equals("time")) { format = DateFormat.getTimeInstance(namedPatterns.get(lcFormatString), locale); } else { throw new StripesRuntimeException("Invalid formatType for Date: " + formatType + ". Allowed types are 'date', 'time' and 'datetime'."); } } else { format = new SimpleDateFormat(formatPattern, locale); } } /** * Gets the date format that will format the date. Subclasses that wish to alter the date format * should override init(), call super.init(), and then obtain the date format object. */ public DateFormat getDateFormat() { return this.format; } /** * Sets the date format that will format the date. Subclasses that wish to set the date format * should override init() and then set the date format object. */ public void setDateFormat(DateFormat dateFormat) { this.format = dateFormat; } /** Formats a Date as a String using the rules supplied when the formatter was built. */ public String format(Date input) { return this.format.format(input); } }