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

Last change on this file since 8870 was 8870, checked in by Don-vip, 9 years ago

sonar - squid:S2325 - "private" methods that don't access instance data should be "static"

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools.date;
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 static 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 static 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 = Integer.parseInt(date.substring(0, 4));
186 int month = Integer.parseInt(date.substring(5, 7));
187 int day = Integer.parseInt(date.substring(8, 10));
188 int hour = Integer.parseInt(date.substring(11, 13));
189 int minute = Integer.parseInt(date.substring(14, 16));
190 int second = Integer.parseInt(date.substring(17, 19));
191
192 calendar.clear();
193 calendar.set(Calendar.YEAR, year);
194 calendar.set(Calendar.MONTH, month - 1);
195 calendar.set(Calendar.DAY_OF_MONTH, day);
196 calendar.set(Calendar.HOUR_OF_DAY, hour);
197 calendar.set(Calendar.MINUTE, minute);
198 calendar.set(Calendar.SECOND, second);
199
200 return calendar.getTime();
201 }
202
203 private Date parseLongStandardDate(String date) {
204 int year = Integer.parseInt(date.substring(0, 4));
205 int month = Integer.parseInt(date.substring(5, 7));
206 int day = Integer.parseInt(date.substring(8, 10));
207 int hour = Integer.parseInt(date.substring(11, 13));
208 int minute = Integer.parseInt(date.substring(14, 16));
209 int second = Integer.parseInt(date.substring(17, 19));
210 int millisecond = Integer.parseInt(date.substring(20, 23));
211
212 calendar.clear();
213 calendar.set(Calendar.YEAR, year);
214 calendar.set(Calendar.MONTH, month - 1);
215 calendar.set(Calendar.DAY_OF_MONTH, day);
216 calendar.set(Calendar.HOUR_OF_DAY, hour);
217 calendar.set(Calendar.MINUTE, minute);
218 calendar.set(Calendar.SECOND, second);
219 calendar.set(Calendar.MILLISECOND, millisecond);
220
221 return calendar.getTime();
222 }
223
224 /**
225 * Attempts to parse the specified date.
226 *
227 * @param date
228 * The date to parse.
229 * @return The date.
230 * @throws ParseException
231 * Occurs if the date does not match any of the supported date
232 * formats.
233 */
234 public Date parse(String date) throws ParseException {
235 try {
236 if (isDateInShortStandardFormat(date)) {
237 return parseShortStandardDate(date);
238 } else if (isDateInLongStandardFormat(date)) {
239 return parseLongStandardDate(date);
240 } else {
241 return datatypeFactory.newXMLGregorianCalendar(date).toGregorianCalendar().getTime();
242 }
243
244 } catch (IllegalArgumentException e) {
245 return fallbackDateParser.parse(date);
246 }
247 }
248}
Note: See TracBrowser for help on using the repository browser.