source: josm/trunk/src/org/openstreetmap/josm/tools/PrimaryDateParser.java@ 1163

Last change on this file since 1163 was 627, checked in by framm, 17 years ago
  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
1package org.openstreetmap.josm.tools;
2
3import java.text.ParseException;
4import java.util.Calendar;
5import java.util.Date;
6import java.util.GregorianCalendar;
7import java.util.TimeZone;
8
9import javax.xml.datatype.DatatypeConfigurationException;
10import javax.xml.datatype.DatatypeFactory;
11
12
13/**
14 * Handles a number of different date formats encountered in OSM. This is built
15 * based on similar code in JOSM. This class is not threadsafe, a separate
16 * instance must be created per thread.
17 *
18 * @author Brett Henderson
19 */
20public class PrimaryDateParser {
21 private DatatypeFactory datatypeFactory;
22 private FallbackDateParser fallbackDateParser;
23 private Calendar calendar;
24
25
26 /**
27 * Creates a new instance.
28 */
29 public PrimaryDateParser() {
30 // Build an xml data type factory.
31 try {
32 datatypeFactory = DatatypeFactory.newInstance();
33
34 } catch (DatatypeConfigurationException e) {
35 throw new RuntimeException("Unable to instantiate xml datatype factory.", e);
36 }
37
38 fallbackDateParser = new FallbackDateParser();
39
40 calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
41 }
42
43
44 private boolean isDateInShortStandardFormat(String date) {
45 char[] dateChars;
46 // We can only parse the date if it is in a very specific format.
47 // eg. 2007-09-23T08:25:43Z
48
49 if (date.length() != 20) {
50 return false;
51 }
52
53 dateChars = date.toCharArray();
54
55 // Make sure any fixed characters are in the correct place.
56 if (dateChars[4] != '-') {
57 return false;
58 }
59 if (dateChars[7] != '-') {
60 return false;
61 }
62 if (dateChars[10] != 'T') {
63 return false;
64 }
65 if (dateChars[13] != ':') {
66 return false;
67 }
68 if (dateChars[16] != ':') {
69 return false;
70 }
71 if (dateChars[19] != 'Z') {
72 return false;
73 }
74
75 // Ensure all remaining characters are numbers.
76 for (int i = 0; i < 4; i++) {
77 if (dateChars[i] < '0' || dateChars[i] > '9') {
78 return false;
79 }
80 }
81 for (int i = 5; i < 7; i++) {
82 if (dateChars[i] < '0' || dateChars[i] > '9') {
83 return false;
84 }
85 }
86 for (int i = 8; i < 10; i++) {
87 if (dateChars[i] < '0' || dateChars[i] > '9') {
88 return false;
89 }
90 }
91 for (int i = 11; i < 13; i++) {
92 if (dateChars[i] < '0' || dateChars[i] > '9') {
93 return false;
94 }
95 }
96 for (int i = 14; i < 16; i++) {
97 if (dateChars[i] < '0' || dateChars[i] > '9') {
98 return false;
99 }
100 }
101 for (int i = 17; i < 19; i++) {
102 if (dateChars[i] < '0' || dateChars[i] > '9') {
103 return false;
104 }
105 }
106
107 // No problems found so it is in the special case format.
108 return true;
109 }
110
111
112 private boolean isDateInLongStandardFormat(String date) {
113 char[] dateChars;
114 // We can only parse the date if it is in a very specific format.
115 // eg. 2007-09-23T08:25:43.000Z
116
117 if (date.length() != 24) {
118 return false;
119 }
120
121 dateChars = date.toCharArray();
122
123 // Make sure any fixed characters are in the correct place.
124 if (dateChars[4] != '-') {
125 return false;
126 }
127 if (dateChars[7] != '-') {
128 return false;
129 }
130 if (dateChars[10] != 'T') {
131 return false;
132 }
133 if (dateChars[13] != ':') {
134 return false;
135 }
136 if (dateChars[16] != ':') {
137 return false;
138 }
139 if (dateChars[19] != '.') {
140 return false;
141 }
142 if (dateChars[23] != 'Z') {
143 return false;
144 }
145
146 // Ensure all remaining characters are numbers.
147 for (int i = 0; i < 4; i++) {
148 if (dateChars[i] < '0' || dateChars[i] > '9') {
149 return false;
150 }
151 }
152 for (int i = 5; i < 7; i++) {
153 if (dateChars[i] < '0' || dateChars[i] > '9') {
154 return false;
155 }
156 }
157 for (int i = 8; i < 10; i++) {
158 if (dateChars[i] < '0' || dateChars[i] > '9') {
159 return false;
160 }
161 }
162 for (int i = 11; i < 13; i++) {
163 if (dateChars[i] < '0' || dateChars[i] > '9') {
164 return false;
165 }
166 }
167 for (int i = 14; i < 16; i++) {
168 if (dateChars[i] < '0' || dateChars[i] > '9') {
169 return false;
170 }
171 }
172 for (int i = 17; i < 19; i++) {
173 if (dateChars[i] < '0' || dateChars[i] > '9') {
174 return false;
175 }
176 }
177 for (int i = 20; i < 23; i++) {
178 if (dateChars[i] < '0' || dateChars[i] > '9') {
179 return false;
180 }
181 }
182
183 // No problems found so it is in the special case format.
184 return true;
185 }
186
187
188 private Date parseShortStandardDate(String date) {
189 int year;
190 int month;
191 int day;
192 int hour;
193 int minute;
194 int second;
195
196 year = Integer.parseInt(date.substring(0, 4));
197 month = Integer.parseInt(date.substring(5, 7));
198 day = Integer.parseInt(date.substring(8, 10));
199 hour = Integer.parseInt(date.substring(11, 13));
200 minute = Integer.parseInt(date.substring(14, 16));
201 second = Integer.parseInt(date.substring(17, 19));
202
203 calendar.clear();
204 calendar.set(Calendar.YEAR, year);
205 calendar.set(Calendar.MONTH, month - 1);
206 calendar.set(Calendar.DAY_OF_MONTH, day);
207 calendar.set(Calendar.HOUR_OF_DAY, hour);
208 calendar.set(Calendar.MINUTE, minute);
209 calendar.set(Calendar.SECOND, second);
210
211 return calendar.getTime();
212 }
213
214
215 private Date parseLongStandardDate(String date) {
216 int year;
217 int month;
218 int day;
219 int hour;
220 int minute;
221 int second;
222 int millisecond;
223
224 year = Integer.parseInt(date.substring(0, 4));
225 month = Integer.parseInt(date.substring(5, 7));
226 day = Integer.parseInt(date.substring(8, 10));
227 hour = Integer.parseInt(date.substring(11, 13));
228 minute = Integer.parseInt(date.substring(14, 16));
229 second = Integer.parseInt(date.substring(17, 19));
230 millisecond = Integer.parseInt(date.substring(20, 23));
231
232 calendar.clear();
233 calendar.set(Calendar.YEAR, year);
234 calendar.set(Calendar.MONTH, month - 1);
235 calendar.set(Calendar.DAY_OF_MONTH, day);
236 calendar.set(Calendar.HOUR_OF_DAY, hour);
237 calendar.set(Calendar.MINUTE, minute);
238 calendar.set(Calendar.SECOND, second);
239 calendar.set(Calendar.MILLISECOND, millisecond);
240
241 return calendar.getTime();
242 }
243
244
245 /**
246 * Attempts to parse the specified date.
247 *
248 * @param date
249 * The date to parse.
250 * @return The date.
251 * @throws ParseException
252 * Occurs if the date does not match any of the supported date
253 * formats.
254 */
255 public Date parse(String date) throws ParseException {
256 try {
257 if (isDateInShortStandardFormat(date)) {
258 return parseShortStandardDate(date);
259 } else if (isDateInLongStandardFormat(date)) {
260 return parseLongStandardDate(date);
261 } else {
262 return datatypeFactory.newXMLGregorianCalendar(date).toGregorianCalendar().getTime();
263 }
264
265 } catch (IllegalArgumentException e) {
266 return fallbackDateParser.parse(date);
267 }
268 }
269}
Note: See TracBrowser for help on using the repository browser.