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

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

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 7.5 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 final FallbackDateParser fallbackDateParser;
23 private final 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 // 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 char[] 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 static boolean isDateInLongStandardFormat(String date) {
109 // We can only parse the date if it is in a very specific format.
110 // eg. 2007-09-23T08:25:43.000Z
111
112 if (date.length() != 24) {
113 return false;
114 }
115
116 char[] dateChars = date.toCharArray();
117
118 // Make sure any fixed characters are in the correct place.
119 if (dateChars[4] != '-') {
120 return false;
121 }
122 if (dateChars[7] != '-') {
123 return false;
124 }
125 if (dateChars[10] != 'T') {
126 return false;
127 }
128 if (dateChars[13] != ':') {
129 return false;
130 }
131 if (dateChars[16] != ':') {
132 return false;
133 }
134 if (dateChars[19] != '.') {
135 return false;
136 }
137 if (dateChars[23] != 'Z') {
138 return false;
139 }
140
141 // Ensure all remaining characters are numbers.
142 for (int i = 0; i < 4; i++) {
143 if (dateChars[i] < '0' || dateChars[i] > '9') {
144 return false;
145 }
146 }
147 for (int i = 5; i < 7; i++) {
148 if (dateChars[i] < '0' || dateChars[i] > '9') {
149 return false;
150 }
151 }
152 for (int i = 8; i < 10; i++) {
153 if (dateChars[i] < '0' || dateChars[i] > '9') {
154 return false;
155 }
156 }
157 for (int i = 11; i < 13; i++) {
158 if (dateChars[i] < '0' || dateChars[i] > '9') {
159 return false;
160 }
161 }
162 for (int i = 14; i < 16; i++) {
163 if (dateChars[i] < '0' || dateChars[i] > '9') {
164 return false;
165 }
166 }
167 for (int i = 17; i < 19; i++) {
168 if (dateChars[i] < '0' || dateChars[i] > '9') {
169 return false;
170 }
171 }
172 for (int i = 20; i < 23; i++) {
173 if (dateChars[i] < '0' || dateChars[i] > '9') {
174 return false;
175 }
176 }
177
178 // No problems found so it is in the special case format.
179 return true;
180 }
181
182 private Date parseShortStandardDate(String date) {
183 int year = Integer.parseInt(date.substring(0, 4));
184 int month = Integer.parseInt(date.substring(5, 7));
185 int day = Integer.parseInt(date.substring(8, 10));
186 int hour = Integer.parseInt(date.substring(11, 13));
187 int minute = Integer.parseInt(date.substring(14, 16));
188 int second = Integer.parseInt(date.substring(17, 19));
189
190 calendar.clear();
191 calendar.set(Calendar.YEAR, year);
192 calendar.set(Calendar.MONTH, month - 1);
193 calendar.set(Calendar.DAY_OF_MONTH, day);
194 calendar.set(Calendar.HOUR_OF_DAY, hour);
195 calendar.set(Calendar.MINUTE, minute);
196 calendar.set(Calendar.SECOND, second);
197
198 return calendar.getTime();
199 }
200
201 private Date parseLongStandardDate(String date) {
202 int year = Integer.parseInt(date.substring(0, 4));
203 int month = Integer.parseInt(date.substring(5, 7));
204 int day = Integer.parseInt(date.substring(8, 10));
205 int hour = Integer.parseInt(date.substring(11, 13));
206 int minute = Integer.parseInt(date.substring(14, 16));
207 int second = Integer.parseInt(date.substring(17, 19));
208 int millisecond = Integer.parseInt(date.substring(20, 23));
209
210 calendar.clear();
211 calendar.set(Calendar.YEAR, year);
212 calendar.set(Calendar.MONTH, month - 1);
213 calendar.set(Calendar.DAY_OF_MONTH, day);
214 calendar.set(Calendar.HOUR_OF_DAY, hour);
215 calendar.set(Calendar.MINUTE, minute);
216 calendar.set(Calendar.SECOND, second);
217 calendar.set(Calendar.MILLISECOND, millisecond);
218
219 return calendar.getTime();
220 }
221
222 /**
223 * Attempts to parse the specified date.
224 *
225 * @param date
226 * The date to parse.
227 * @return The date.
228 * @throws ParseException
229 * Occurs if the date does not match any of the supported date
230 * formats.
231 */
232 public Date parse(String date) throws ParseException {
233 try {
234 if (isDateInShortStandardFormat(date)) {
235 return parseShortStandardDate(date);
236 } else if (isDateInLongStandardFormat(date)) {
237 return parseLongStandardDate(date);
238 } else {
239 return datatypeFactory.newXMLGregorianCalendar(date).toGregorianCalendar().getTime();
240 }
241
242 } catch (IllegalArgumentException e) {
243 return fallbackDateParser.parse(date);
244 }
245 }
246}
Note: See TracBrowser for help on using the repository browser.