DateFormatter.java 5.7 KB
Newer Older
1
/*
2
 * Copyright 2002-2013 the original author or authors.
3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 * 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.
 */
16

17
package org.springframework.format.datetime;
18 19 20 21

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
22
import java.util.Collections;
23
import java.util.Date;
24
import java.util.HashMap;
25
import java.util.Locale;
26
import java.util.Map;
27
import java.util.TimeZone;
28

29
import org.springframework.format.Formatter;
30 31 32 33
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
34 35

/**
K
polish  
Keith Donald 已提交
36
 * A formatter for {@link java.util.Date} types.
37
 * Allows the configuration of an explicit date pattern and locale.
38
 *
39
 * @author Keith Donald
40
 * @author Juergen Hoeller
41
 * @author Phillip Webb
42
 * @since 3.0
43
 * @see SimpleDateFormat
44
 */
45
public class DateFormatter implements Formatter<Date> {
46

47 48
	private static final Map<ISO, String> ISO_PATTERNS;
	static {
49
		Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>(4);
50 51 52 53 54 55 56
		formats.put(ISO.DATE, "yyyy-MM-dd");
		formats.put(ISO.TIME, "HH:mm:ss.SSSZ");
		formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
		ISO_PATTERNS = Collections.unmodifiableMap(formats);
	}


57 58 59 60
	private String pattern;

	private int style = DateFormat.DEFAULT;

61 62 63 64
	private String stylePattern;

	private ISO iso;

65 66 67 68
	private TimeZone timeZone;

	private boolean lenient = false;

69 70

	/**
71
	 * Create a new default DateFormatter.
72
	 */
73 74 75 76 77 78 79 80 81
	public DateFormatter() {
	}

	/**
	 * Create a new DateFormatter for the given date pattern.
	 */
	public DateFormatter(String pattern) {
		this.pattern = pattern;
	}
82 83 84


	/**
85 86
	 * Set the pattern to use to format date values.
	 * <p>If not specified, DateFormat's default style will be used.
87 88 89 90 91
	 */
	public void setPattern(String pattern) {
		this.pattern = pattern;
	}

92 93 94 95 96 97 98 99 100
	/**
	 * Set the ISO format used for this date.
	 * @param iso the {@link ISO} format
	 * @since 3.2
	 */
	public void setIso(ISO iso) {
		this.iso = iso;
	}

101 102 103 104 105 106 107 108 109 110 111 112 113
	/**
	 * Set the style to use to format date values.
	 * <p>If not specified, DateFormat's default style will be used.
	 * @see DateFormat#DEFAULT
	 * @see DateFormat#SHORT
	 * @see DateFormat#MEDIUM
	 * @see DateFormat#LONG
	 * @see DateFormat#FULL
	 */
	public void setStyle(int style) {
		this.style = style;
	}

114 115 116 117 118 119 120 121 122 123
	/**
	 * Set the two character to use to format date values. The first character used for
	 * the date style, the second is for the time style. Supported characters are
	 * <ul>
	 * <li>'S' = Small</li>
	 * <li>'M' = Medium</li>
	 * <li>'L' = Long</li>
	 * <li>'F' = Full</li>
	 * <li>'-' = Omitted</li>
	 * <ul>
124
	 * This method mimics the styles supported by Joda-Time.
125 126 127 128 129 130 131
	 * @param stylePattern two characters from the set {"S", "M", "L", "F", "-"}
	 * @since 3.2
	 */
	public void setStylePattern(String stylePattern) {
		this.stylePattern = stylePattern;
	}

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	/**
	 * Set the TimeZone to normalize the date values into, if any.
	 */
	public void setTimeZone(TimeZone timeZone) {
		this.timeZone = timeZone;
	}

	/**
	 * Specify whether or not parsing is to be lenient. Default is false.
	 * <p>With lenient parsing, the parser may allow inputs that do not precisely match the format.
	 * With strict parsing, inputs must match the format exactly.
	 */
	public void setLenient(boolean lenient) {
		this.lenient = lenient;
	}

148

149
	public String print(Date date, Locale locale) {
150 151 152
		return getDateFormat(locale).format(date);
	}

153 154
	public Date parse(String text, Locale locale) throws ParseException {
		return getDateFormat(locale).parse(text);
155 156 157
	}


158
	protected DateFormat getDateFormat(Locale locale) {
159
		DateFormat dateFormat = createDateFormat(locale);
160 161 162 163
		if (this.timeZone != null) {
			dateFormat.setTimeZone(this.timeZone);
		}
		dateFormat.setLenient(this.lenient);
164
		return dateFormat;
165 166
	}

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
	private DateFormat createDateFormat(Locale locale) {
		if (StringUtils.hasLength(this.pattern)) {
			return new SimpleDateFormat(this.pattern, locale);
		}
		if (iso != null && iso != ISO.NONE) {
			String pattern = ISO_PATTERNS.get(iso);
			Assert.state(pattern != null, "Unsupported ISO format " + iso);
			SimpleDateFormat format = new SimpleDateFormat(pattern);
			format.setTimeZone(TimeZone.getTimeZone("UTC"));
			return format;
		}
		if(StringUtils.hasLength(stylePattern)) {
			int dateStyle = getStylePatternForChar(0);
			int timeStyle = getStylePatternForChar(1);
			if(dateStyle != -1 && timeStyle != -1) {
				return DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
			}
			if(dateStyle != -1) {
				return DateFormat.getDateInstance(dateStyle, locale);
			}
			if(timeStyle != -1) {
				return DateFormat.getTimeInstance(timeStyle, locale);
			}
			throw new IllegalStateException("Unsupported style pattern '"+ stylePattern+ "'");

		}
		return DateFormat.getDateInstance(this.style, locale);
	}

	private int getStylePatternForChar(int index) {
		if(stylePattern != null && stylePattern.length() > index) {
			switch (stylePattern.charAt(index)) {
				case 'S': return DateFormat.SHORT;
				case 'M': return DateFormat.MEDIUM;
				case 'L': return DateFormat.LONG;
				case 'F': return DateFormat.FULL;
				case '-': return -1;
			}
		}
		throw new IllegalStateException("Unsupported style pattern '"+ stylePattern+ "'");
	}
208

209
}