1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.format.datetime;
18
19 import java.text.DateFormat;
20 import java.text.ParseException;
21 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 import org.springframework.format.annotation.DateTimeFormat;
31 import org.springframework.format.annotation.DateTimeFormat.ISO;
32 import org.springframework.util.StringUtils;
33
34
35
36
37
38
39
40
41
42
43
44 public class DateFormatter implements Formatter<Date> {
45
46 private static final Map<ISO, String> ISO_PATTERNS;
47
48 static {
49 Map<ISO, String> formats = new HashMap<DateTimeFormat.ISO, String>(4);
50 formats.put(ISO.DATE, "yyyy-MM-dd");
51 formats.put(ISO.TIME, "HH:mm:ss.SSSZ");
52 formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
53 ISO_PATTERNS = Collections.unmodifiableMap(formats);
54 }
55
56
57 private String pattern;
58
59 private int style = DateFormat.DEFAULT;
60
61 private String stylePattern;
62
63 private ISO iso;
64
65 private TimeZone timeZone;
66
67 private boolean lenient = false;
68
69
70
71
72
73 public DateFormatter() {
74 }
75
76
77
78
79 public DateFormatter(String pattern) {
80 this.pattern = pattern;
81 }
82
83
84
85
86
87
88 public void setPattern(String pattern) {
89 this.pattern = pattern;
90 }
91
92
93
94
95
96
97 public void setIso(ISO iso) {
98 this.iso = iso;
99 }
100
101
102
103
104
105
106
107
108
109
110 public void setStyle(int style) {
111 this.style = style;
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 public void setStylePattern(String stylePattern) {
129 this.stylePattern = stylePattern;
130 }
131
132
133
134
135 public void setTimeZone(TimeZone timeZone) {
136 this.timeZone = timeZone;
137 }
138
139
140
141
142
143
144 public void setLenient(boolean lenient) {
145 this.lenient = lenient;
146 }
147
148
149 @Override
150 public String print(Date date, Locale locale) {
151 return getDateFormat(locale).format(date);
152 }
153
154 @Override
155 public Date parse(String text, Locale locale) throws ParseException {
156 return getDateFormat(locale).parse(text);
157 }
158
159
160 protected DateFormat getDateFormat(Locale locale) {
161 DateFormat dateFormat = createDateFormat(locale);
162 if (this.timeZone != null) {
163 dateFormat.setTimeZone(this.timeZone);
164 }
165 dateFormat.setLenient(this.lenient);
166 return dateFormat;
167 }
168
169 private DateFormat createDateFormat(Locale locale) {
170 if (StringUtils.hasLength(this.pattern)) {
171 return new SimpleDateFormat(this.pattern, locale);
172 }
173 if (this.iso != null && this.iso != ISO.NONE) {
174 String pattern = ISO_PATTERNS.get(this.iso);
175 if (pattern == null) {
176 throw new IllegalStateException("Unsupported ISO format " + this.iso);
177 }
178 SimpleDateFormat format = new SimpleDateFormat(pattern);
179 format.setTimeZone(TimeZone.getTimeZone("UTC"));
180 return format;
181 }
182 if (StringUtils.hasLength(this.stylePattern)) {
183 int dateStyle = getStylePatternForChar(0);
184 int timeStyle = getStylePatternForChar(1);
185 if (dateStyle != -1 && timeStyle != -1) {
186 return DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
187 }
188 if (dateStyle != -1) {
189 return DateFormat.getDateInstance(dateStyle, locale);
190 }
191 if (timeStyle != -1) {
192 return DateFormat.getTimeInstance(timeStyle, locale);
193 }
194 throw new IllegalStateException("Unsupported style pattern '"+ this.stylePattern+ "'");
195
196 }
197 return DateFormat.getDateInstance(this.style, locale);
198 }
199
200 private int getStylePatternForChar(int index) {
201 if (this.stylePattern != null && this.stylePattern.length() > index) {
202 switch (this.stylePattern.charAt(index)) {
203 case 'S': return DateFormat.SHORT;
204 case 'M': return DateFormat.MEDIUM;
205 case 'L': return DateFormat.LONG;
206 case 'F': return DateFormat.FULL;
207 case '-': return -1;
208 }
209 }
210 throw new IllegalStateException("Unsupported style pattern '" + this.stylePattern + "'");
211 }
212
213 }