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

Last change on this file since 2512 was 2512, checked in by stoecker, 15 years ago

i18n updated, fixed files to reduce problems when applying patches, fix #4017

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