1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.sun.syndication.io.impl;
18
19 import java.text.DateFormat;
20 import java.text.SimpleDateFormat;
21 import java.text.ParsePosition;
22 import java.util.Date;
23 import java.util.TimeZone;
24 import java.util.Locale;
25
26 /***
27 * A helper class that parses Dates out of Strings with date time in RFC822 and W3CDateTime
28 * formats plus the variants Atom (0.3) and RSS (0.9, 0.91, 0.92, 0.93, 0.94, 1.0 and 2.0)
29 * specificators added to those formats.
30 * <p/>
31 * It uses the JDK java.text.SimpleDateFormat class attemtping the parse using a mask for
32 * each one of the possible formats.
33 * <p/>
34 *
35 * @author Alejandro Abdelnur
36 *
37 */
38 public class DateParser {
39
40 private static String[] ADDITIONAL_MASKS;
41
42 static {
43 ADDITIONAL_MASKS = PropertiesLoader.getPropertiesLoader().getTokenizedProperty("datetime.extra.masks","|");
44 }
45
46
47
48
49 private static final String[] RFC822_MASKS = {
50 "EEE, dd MMM yy HH:mm:ss z",
51 "EEE, dd MMM yy HH:mm z",
52 "dd MMM yy HH:mm:ss z",
53 "dd MMM yy HH:mm z"
54 };
55
56
57
58
59
60
61 private static final String[] W3CDATETIME_MASKS = {
62 "yyyy-MM-dd'T'HH:mm:ssz",
63 "yyyy-MM-dd'T'HH:mmz",
64 "yyyy-MM-dd",
65 "yyyy-MM",
66 "yyyy"
67 };
68
69 /***
70 * Private constructor to avoid DateParser instances creation.
71 */
72 private DateParser() {
73 }
74
75 /***
76 * Parses a Date out of a string using an array of masks.
77 * <p/>
78 * It uses the masks in order until one of them succedes or all fail.
79 * <p/>
80 *
81 * @param masks array of masks to use for parsing the string
82 * @param sDate string to parse for a date.
83 * @return the Date represented by the given string using one of the given masks.
84 * It returns <b>null</b> if it was not possible to parse the the string with any of the masks.
85 *
86 */
87 private static Date parseUsingMask(String[] masks,String sDate) {
88 sDate = (sDate!=null) ? sDate.trim() : null;
89 ParsePosition pp = null;
90 Date d = null;
91 for (int i=0;d==null && i<masks.length;i++) {
92 DateFormat df = new SimpleDateFormat(masks[i],Locale.US);
93
94 df.setLenient(true);
95 try {
96 pp = new ParsePosition(0);
97 d = df.parse(sDate,pp);
98 if (pp.getIndex()!=sDate.length()) {
99 d = null;
100 }
101
102 }
103 catch (Exception ex1) {
104
105 }
106 }
107 return d;
108 }
109
110 /***
111 * Parses a Date out of a String with a date in RFC822 format.
112 * <p/>
113 * It parsers the following formats:
114 * <ul>
115 * <li>"EEE, dd MMM yyyy HH:mm:ss z"</li>
116 * <li>"EEE, dd MMM yyyy HH:mm z"</li>
117 * <li>"EEE, dd MMM yy HH:mm:ss z"</li>
118 * <li>"EEE, dd MMM yy HH:mm z"</li>
119 * <li>"dd MMM yyyy HH:mm:ss z"</li>
120 * <li>"dd MMM yyyy HH:mm z"</li>
121 * <li>"dd MMM yy HH:mm:ss z"</li>
122 * <li>"dd MMM yy HH:mm z"</li>
123 * </ul>
124 * <p/>
125 * Refer to the java.text.SimpleDateFormat javadocs for details on the format of each element.
126 * <p/>
127 * @param sDate string to parse for a date.
128 * @return the Date represented by the given RFC822 string.
129 * It returns <b>null</b> if it was not possible to parse the given string into a Date.
130 *
131 */
132 public static Date parseRFC822(String sDate) {
133 return parseUsingMask(RFC822_MASKS,sDate);
134 }
135
136
137 /***
138 * Parses a Date out of a String with a date in W3C date-time format.
139 * <p/>
140 * It parsers the following formats:
141 * <ul>
142 * <li>"yyyy-MM-dd'T'HH:mm:ssz"</li>
143 * <li>"yyyy-MM-dd'T'HH:mmz"</li>
144 * <li>"yyyy-MM-dd"</li>
145 * <li>"yyyy-MM"</li>
146 * <li>"yyyy"</li>
147 * </ul>
148 * <p/>
149 * Refer to the java.text.SimpleDateFormat javadocs for details on the format of each element.
150 * <p/>
151 * @param sDate string to parse for a date.
152 * @return the Date represented by the given W3C date-time string.
153 * It returns <b>null</b> if it was not possible to parse the given string into a Date.
154 *
155 */
156 public static Date parseW3CDateTime(String sDate) {
157
158
159 int tIndex = sDate.indexOf("T");
160 if (tIndex>-1) {
161 if (sDate.endsWith("Z")) {
162 sDate = sDate.substring(0,sDate.length()-1)+"+00:00";
163 }
164 int tzdIndex = sDate.indexOf("+",tIndex);
165 if (tzdIndex==-1) {
166 tzdIndex = sDate.indexOf("-",tIndex);
167 }
168 if (tzdIndex>-1) {
169 String pre = sDate.substring(0,tzdIndex);
170 int secFraction = pre.indexOf(",");
171 if (secFraction>-1) {
172 pre = pre.substring(0,secFraction);
173 }
174 String post = sDate.substring(tzdIndex);
175 sDate = pre + "GMT" + post;
176 }
177 }
178 return parseUsingMask(W3CDATETIME_MASKS,sDate);
179 }
180
181
182 /***
183 * Parses a Date out of a String with a date in W3C date-time format or
184 * in a RFC822 format.
185 * <p>
186 * @param sDate string to parse for a date.
187 * @return the Date represented by the given W3C date-time string.
188 * It returns <b>null</b> if it was not possible to parse the given string into a Date.
189 *
190 * */
191 public static Date parseDate(String sDate) {
192 Date d = parseW3CDateTime(sDate);
193 if (d==null) {
194 d = parseRFC822(sDate);
195 if (d==null && ADDITIONAL_MASKS.length>0) {
196 d = parseUsingMask(ADDITIONAL_MASKS,sDate);
197 }
198 }
199 return d;
200 }
201
202 /***
203 * create a RFC822 representation of a date.
204 * <p/>
205 * Refer to the java.text.SimpleDateFormat javadocs for details on the format of each element.
206 * <p/>
207 * @param date Date to parse
208 * @return the RFC822 represented by the given Date
209 * It returns <b>null</b> if it was not possible to parse the date.
210 *
211 */
212 public static String formatRFC822(Date date) {
213 SimpleDateFormat dateFormater = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'",Locale.US);
214 dateFormater.setTimeZone(TimeZone.getTimeZone("GMT"));
215 return dateFormater.format(date);
216 }
217
218 /***
219 * create a W3C Date Time representation of a date.
220 * <p/>
221 * Refer to the java.text.SimpleDateFormat javadocs for details on the format of each element.
222 * <p/>
223 * @param date Date to parse
224 * @return the W3C Date Time represented by the given Date
225 * It returns <b>null</b> if it was not possible to parse the date.
226 *
227 */
228 public static String formatW3CDateTime(Date date) {
229 SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",Locale.US);
230 dateFormater.setTimeZone(TimeZone.getTimeZone("GMT"));
231 return dateFormater.format(date);
232 }
233
234 }