001: /*
002: * RFC822Date.java
003: *
004: * Copyright (C) 2000-2002 Peter Graves
005: * $Id: RFC822Date.java,v 1.1.1.1 2002/09/24 16:10:14 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j.mail;
023:
024: import java.io.Serializable;
025: import java.text.SimpleDateFormat;
026: import java.util.ArrayList;
027: import java.util.Calendar;
028: import java.util.Date;
029: import java.util.Locale;
030: import java.util.StringTokenizer;
031: import java.util.TimeZone;
032: import org.armedbear.j.FastStringBuffer;
033: import org.armedbear.j.Utilities;
034:
035: public final class RFC822Date implements Serializable {
036: private Date date;
037:
038: private RFC822Date() {
039: }
040:
041: public RFC822Date(Date date) {
042: this .date = date;
043: }
044:
045: public Date getDate() {
046: return date;
047: }
048:
049: public long getTime() {
050: if (date != null)
051: return date.getTime();
052: return 0;
053: }
054:
055: public static RFC822Date parseDate(String input) {
056: if (input == null || input.length() == 0)
057: return new RFC822Date();
058: final StringTokenizer st = new StringTokenizer(input, " ,");
059: final ArrayList tokens = new ArrayList();
060: while (st.hasMoreTokens())
061: tokens.add(st.nextToken());
062: final int tokenCount = tokens.size();
063: int month = -1;
064: int dayOfMonth = -1;
065: int year = -1;
066: int hour = -1;
067: int minute = -1;
068: int second = -1;
069: for (int i = 0; i < tokenCount; i++) {
070: String token = (String) tokens.get(i);
071: switch (token.charAt(0)) {
072: case 'J':
073: if (token.equals("Jan"))
074: month = 0;
075: else if (token.equals("Jun"))
076: month = 5;
077: else if (token.equals("Jul"))
078: month = 6;
079: break;
080: case 'F':
081: if (token.equals("Feb"))
082: month = 1;
083: break;
084: case 'M':
085: if (token.equals("Mar"))
086: month = 2;
087: else if (token.equals("May"))
088: month = 4;
089: break;
090: case 'A':
091: if (token.equals("Apr"))
092: month = 3;
093: else if (token.equals("Aug"))
094: month = 7;
095: break;
096: case 'S':
097: if (token.equals("Sep"))
098: month = 8;
099: break;
100: case 'O':
101: if (token.equals("Oct"))
102: month = 9;
103: break;
104: case 'N':
105: if (token.equals("Nov"))
106: month = 10;
107: break;
108: case 'D':
109: if (token.equals("Dec"))
110: month = 11;
111: break;
112: }
113: if (month >= 0) {
114: tokens.set(i, null);
115: if (i > 0) {
116: String before = (String) tokens.get(i - 1);
117: try {
118: dayOfMonth = Integer.parseInt(before);
119: } catch (NumberFormatException e) {
120: }
121: if (dayOfMonth >= 1 && dayOfMonth <= 31) {
122: tokens.set(i - 1, null);
123: break;
124: }
125: }
126: if (i < tokenCount - 1) {
127: String after = (String) tokens.get(i + 1);
128: try {
129: dayOfMonth = Integer.parseInt(after);
130: } catch (NumberFormatException e) {
131: }
132: tokens.set(i + 1, null);
133: }
134: break;
135: }
136: }
137: // Year.
138: for (int i = 0; i < tokenCount; i++) {
139: String token = (String) tokens.get(i);
140: if (token == null)
141: continue;
142: try {
143: year = Integer.parseInt(token);
144: } catch (NumberFormatException e) {
145: }
146: if (year >= 1900 && year < 2100) {
147: tokens.set(i, null);
148: break;
149: }
150: year = -1;
151: }
152: if (year == -1) {
153: // Be slightly more permissive.
154: for (int i = 0; i < tokenCount; i++) {
155: String token = (String) tokens.get(i);
156: if (token == null)
157: continue;
158: try {
159: year = Integer.parseInt(token);
160: } catch (NumberFormatException e) {
161: }
162: if (year >= 0 && year < 200) {
163: year += 1900;
164: if (year < 1971) // There was no email before 1971.
165: year += 100;
166: tokens.set(i, null);
167: break;
168: }
169: }
170: }
171: // Time.
172: for (int i = 0; i < tokenCount; i++) {
173: String token = (String) tokens.get(i);
174: if (token == null)
175: continue;
176: int index = token.indexOf(':');
177: if (index < 0)
178: continue;
179: try {
180: hour = Integer.parseInt(token.substring(0, index));
181: } catch (NumberFormatException e) {
182: continue;
183: }
184: if (hour > 24)
185: continue;
186: if (index + 1 >= token.length())
187: continue;
188: if (!Character.isDigit(token.charAt(index + 1)))
189: continue;
190: token = token.substring(index + 1);
191: try {
192: minute = Utilities.parseInt(token);
193: } catch (NumberFormatException e) {
194: continue;
195: }
196: index = token.indexOf(':');
197: if (index >= 0) {
198: token = token.substring(index + 1);
199: try {
200: second = Utilities.parseInt(token);
201: } catch (NumberFormatException e) {
202: }
203: }
204: tokens.set(i, null);
205: break;
206: }
207: // Time zone.
208: TimeZone tz = null;
209: for (int i = 0; i < tokenCount; i++) {
210: String token = (String) tokens.get(i);
211: if (token == null)
212: continue;
213: if (token.length() == 5) {
214: boolean maybe = true;
215: char c = token.charAt(0);
216: if (c == '-' || c == '+') {
217: for (int j = 1; j <= 4; j++) {
218: if (!Character.isDigit(token.charAt(j))) {
219: maybe = false;
220: break;
221: }
222: }
223: }
224: if (maybe) {
225: tz = TimeZone.getTimeZone("GMT" + token);
226: break;
227: }
228: }
229: }
230: if (tz == null) {
231: for (int i = 0; i < tokenCount; i++) {
232: String token = (String) tokens.get(i);
233: if (token == null)
234: continue;
235: if (token.length() == 3) {
236: if (token.charAt(2) != 'T')
237: continue;
238: if (token.charAt(0) < 'A' || token.charAt(0) > 'Z')
239: continue;
240: if (token.charAt(1) < 'A' || token.charAt(1) > 'Z')
241: continue;
242: if (token.charAt(1) == 'D') {
243: // Java thinks PDT, EDT, etc. are the same as GMT.
244: // Pacific, Mountain, Central, Eastern.
245: if ("PMCE".indexOf(token.charAt(0)) >= 0) {
246: switch (token.charAt(0)) {
247: case 'P':
248: token = "PST";
249: break;
250: case 'M':
251: token = "MST";
252: break;
253: case 'C':
254: token = "CST";
255: break;
256: case 'E':
257: token = "EST";
258: break;
259: }
260: }
261: }
262: tz = TimeZone.getTimeZone(token);
263: if (tz != null)
264: break;
265: }
266: }
267: }
268: if (tz == null)
269: tz = TimeZone.getTimeZone("GMT+0000");
270: if (month < 0 || dayOfMonth < 0 || year < 0 || hour < 0
271: || minute < 0)
272: return new RFC822Date();
273: Calendar cal = Calendar.getInstance();
274: cal.setTimeZone(tz);
275: cal.set(year, month, dayOfMonth, hour, minute);
276: if (second >= 0)
277: cal.set(Calendar.SECOND, second);
278: return new RFC822Date(cal.getTime());
279: }
280:
281: private static final SimpleDateFormat toStringFormat = new SimpleDateFormat(
282: "EEE, dd MMM yyyy HH:mm:ss", Locale.US);
283:
284: public String toString() {
285: if (date == null)
286: return "null";
287: return toStringFormat.format(date);
288: }
289:
290: public static int compare(RFC822Date date1, RFC822Date date2) {
291: if (date1.date == null)
292: return -1;
293: if (date2.date == null)
294: return 1;
295: if (date1.date.before(date2.date))
296: return -1;
297: if (date1.date.after(date2.date))
298: return 1;
299: return 0;
300: }
301:
302: public final boolean equals(RFC822Date d) {
303: if (d == null)
304: return false;
305: else if (date == null)
306: return d.date == null;
307: else
308: return date.equals(d.date);
309: }
310:
311: // Compares date only (i.e. ignores hours, minutes, seconds).
312: public boolean before(RFC822Date d) {
313: if (date == null) {
314: if (d.date == null)
315: return false;
316: else
317: return true;
318: }
319: if (d.date == null)
320: return false;
321: int this Year = date.getYear();
322: int otherYear = d.date.getYear();
323: if (this Year < otherYear)
324: return true;
325: if (this Year > otherYear)
326: return false;
327: // Same year.
328: int this Month = date.getMonth();
329: int otherMonth = d.date.getMonth();
330: if (this Month < otherMonth)
331: return true;
332: if (this Month > otherMonth)
333: return false;
334: // Same year and month.
335: return date.getDate() < d.date.getDate();
336: }
337:
338: // Compares date only (i.e. ignores hours, minutes, seconds).
339: public boolean after(RFC822Date d) {
340: if (date == null)
341: return false;
342: if (d.date == null)
343: return true;
344: int this Year = date.getYear();
345: int otherYear = d.date.getYear();
346: if (this Year > otherYear)
347: return true;
348: if (this Year < otherYear)
349: return false;
350: // Same year.
351: int this Month = date.getMonth();
352: int otherMonth = d.date.getMonth();
353: if (this Month > otherMonth)
354: return true;
355: if (this Month < otherMonth)
356: return false;
357: // Same year and month.
358: return date.getDate() > d.date.getDate();
359: }
360:
361: // Used only by getDateTimeString.
362: private static final SimpleDateFormat df = new SimpleDateFormat(
363: "EEE, d MMM yyyy HH:mm:ss ", Locale.US);
364:
365: public static String getDateTimeString() {
366: return getDateTimeString(Calendar.getInstance());
367: }
368:
369: public static String getDateTimeString(Calendar calendar) {
370: FastStringBuffer sb = new FastStringBuffer(48);
371: sb.append(df.format(calendar.getTime()));
372: int offset = calendar.get(Calendar.ZONE_OFFSET)
373: + calendar.get(Calendar.DST_OFFSET);
374: if (offset == 0) {
375: sb.append("+0000"); // '+' by convention.
376: } else {
377: if (offset < 0) {
378: sb.append('-');
379: offset = -offset;
380: }
381: int hours = offset / (60 * 60 * 1000);
382: if (hours >= 10) {
383: sb.append(String.valueOf(hours));
384: } else {
385: sb.append('0');
386: sb.append(String.valueOf(hours));
387: }
388: int minutes = offset % (60 * 60 * 1000);
389: if (minutes >= 10) {
390: sb.append(String.valueOf(minutes));
391: } else {
392: sb.append('0');
393: sb.append(String.valueOf(minutes));
394: }
395: }
396: return sb.toString();
397: }
398:
399: public static final int getOffset(Calendar calendar) {
400: return calendar.get(Calendar.ZONE_OFFSET)
401: + calendar.get(Calendar.DST_OFFSET);
402: }
403:
404: // public static void main(String[] args)
405: // {
406: // String input = "7 Nov 00 14:32:06 IST";
407: // System.out.print(input + " ==> " );
408: // System.out.println(parseDate(input));
409: // input = "Sun, 12 Nov 00 14:58:09 EST";
410: // System.out.print(input + " ==> " );
411: // System.out.println(parseDate(input));
412: // input = "Thu, 28 Dec 2000 09:47:08 -0800";
413: // System.out.print(input + " ==> " );
414: // System.out.println(parseDate(input));
415: // }
416: }
|