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

Revision 3719, 7.7 KB checked in by bastiK, 18 months ago (diff)

added missing license information

  • Property svn:eol-style set to native
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.