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

Last change on this file since 3779 was 3719, checked in by bastiK, 13 years ago

added missing license information

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