/* 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);
}
}