001: package com.ibm.webdav;
002:
003: /*
004: * (C) Copyright IBM Corp. 2000 All rights reserved.
005: *
006: * The program is provided "AS IS" without any warranty express or
007: * implied, including the warranty of non-infringement and the implied
008: * warranties of merchantibility and fitness for a particular purpose.
009: * IBM will not be liable for any damages suffered by you as a result
010: * of using the Program. In no event will IBM be liable for any
011: * special, indirect or consequential damages or lost profits even if
012: * IBM has been advised of the possibility of their occurrence. IBM
013: * will not be liable for any third party claims against you.
014: *
015: * Portions Copyright (C) Simulacra Media Ltd, 2004.
016: */
017:
018: import java.io.*;
019: import java.text.*;
020: import java.util.*;
021:
022: /**
023: * <code>SimpleRFC1123DateFormat</code> is a concrete class for formatting and
024: * parsing RFC 1123 format dates. It allows for formatting
025: * (date -> text), parsing (text -> date), and normalization.
026: *
027: * @see java.util.Calendar
028: * @see java.util.GregorianCalendar
029: * @see java.util.TimeZone
030: * @see DateFormat
031: * @see DateFormatSymbols
032: * @see DecimalFormat
033: * @version 1.31 04/22/98
034: * @author Mark Davis, Chen-Lieh Huang, Alan Liu, Jason Crawford
035: */
036: public class SimpleRFC1123DateFormat extends DateFormat {
037:
038: // the official serial version ID which says cryptically
039: // which version we're compatible with
040: static final long serialVersionUID = 4774881970558875024L;
041:
042: // the internal serial version which says which version was written
043: // - 0 (default) for version up to JDK 1.1.3
044: // - 1 for version from JDK 1.1.4, which includes a new field
045: static final int currentSerialVersion = 1;
046: private int serialVersionOnStream = currentSerialVersion;
047:
048: static Hashtable htMonths = new Hashtable();
049: static {
050: htMonths.put("Jan", new Integer(1));
051: htMonths.put("Feb", new Integer(2));
052: htMonths.put("Mar", new Integer(3));
053: htMonths.put("Apr", new Integer(4));
054: htMonths.put("May", new Integer(5));
055: htMonths.put("Jun", new Integer(6));
056: htMonths.put("Jul", new Integer(7));
057: htMonths.put("Aug", new Integer(8));
058: htMonths.put("Sep", new Integer(9));
059: htMonths.put("Oct", new Integer(10));
060: htMonths.put("Nov", new Integer(11));
061: htMonths.put("Dec", new Integer(12));
062: };
063:
064: /**
065: * Construct a SimpleDateFormat using the default pattern for the default
066: * locale. <b>Note:</b> Not all locales support SimpleDateFormat; for full
067: * generality, use the factory methods in the DateFormat class.
068: *
069: * @see java.text.DateFormat
070: */
071: public SimpleRFC1123DateFormat() {
072: initialize();
073: }
074:
075: /**
076: * Overrides Cloneable
077: */
078: public Object clone() {
079: SimpleRFC1123DateFormat other = (SimpleRFC1123DateFormat) super
080: .clone();
081: // other.formatData = (DateFormatSymbols) formatData.clone();
082: return other;
083: }
084:
085: /**
086: * Override equals.
087: */
088: public boolean equals(Object obj) {
089: if (!super .equals(obj))
090: return false; // super does class check
091:
092: // todo: I think we are supposed to check if they are equivalent, but for now a class check will do. In fact I think
093: // just being the same class is adequate.
094:
095: return true;
096: }
097:
098: /**
099: * Overrides DateFormat
100: * <p>Formats a date or time, which is the standard millis
101: * since January 1, 1970, 00:00:00 GMT.
102: * @param date the date-time value to be formatted into a date-time string.
103: * @param toAppendTo where the new date-time text is to be appended.
104: * @param pos the formatting position. On input: an alignment field,
105: * if desired. On output: the offsets of the alignment field.
106: * @return the formatted date-time string.
107: * @see java.util.DateFormat
108: */
109: public StringBuffer format(Date date, StringBuffer toAppendTo,
110: FieldPosition pos) {
111: java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(
112: "EEE, dd MMM yyyy HH:mm:ss 'GMT'");
113: df.setTimeZone(TimeZone.getTimeZone("GMT"));
114: df.format(date, toAppendTo, pos);
115: return toAppendTo;
116: }
117:
118: /* Initialize calendar and numberFormat fields */
119:
120: private void initialize() {
121: // The format object must be constructed using the symbols for this zone.
122: // However, the calendar should use the current default TimeZone.
123: // If this is not contained in the locale zone strings, then the zone
124: // will be formatted using generic GMT+/-H:MM nomenclature.
125: TimeZone tz = TimeZone.getTimeZone("UDT");
126: calendar = Calendar.getInstance(tz);
127: // numberFormat isn't used by us, but we inherit behavior that we have to respect.
128: NumberFormat numberFormat = NumberFormat.getInstance();
129: /*
130: numberFormat.setGroupingUsed(false);
131: if (numberFormat instanceof DecimalFormat)
132: ((DecimalFormat)numberFormat).setDecimalSeparatorAlwaysShown(false);
133: numberFormat.setParseIntegerOnly(true); // So that dd.mm.yy can be parsed
134: numberFormat.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"
135: */
136: setNumberFormat(numberFormat);
137: /*
138: initializeDefaultCentury();
139: */
140: }
141:
142: public static void main(String args[]) {
143: SimpleRFC1123DateFormat sr = new SimpleRFC1123DateFormat();
144: java.text.ParsePosition pp = new java.text.ParsePosition(0);
145: Date dt = null;
146: String arg1 = null;
147:
148: arg1 = "Sunday, 05-Jan-2000 08:42:03 GMT";
149: dt = sr.parse(arg1, new java.text.ParsePosition(0));
150: System.out.println(arg1 + " gives " + dt);
151: arg1 = "Sun, 05-Jan-98 08:42:03 GMT";
152: dt = sr.parse(arg1, new java.text.ParsePosition(0));
153: System.out.println(arg1 + " gives " + dt);
154: StringBuffer sbb = new StringBuffer();
155: sr.format(dt, sbb, new java.text.FieldPosition(0));
156: System.out.println(sbb);
157: System.exit(0);
158: }
159:
160: /**
161: * Overrides DateFormat
162: * @see java.util.DateFormat
163: */
164: public Date parse(String text, java.text.ParsePosition pos) {
165: int start0 = pos.getIndex();
166: Calendar calendar = getCalendar();
167: calendar.clear(); // Clears all the time fields
168:
169: int start = text.indexOf(',', start0);
170: if (-1 == start)
171: return null;
172:
173: start += 2;
174: int day = Integer
175: .parseInt(text.substring(start + 0, start + 2));
176: String stMonth = text.substring(start + 3, start + 6);
177: Integer itMonth = (Integer) htMonths.get(stMonth);
178: if (itMonth == null)
179: return null;
180: int month = itMonth.intValue();
181:
182: char pivotChar = text.charAt(start + 9);
183: int year;
184: if ((pivotChar < '0') || (pivotChar > '9')) {
185: // apparently a two digit year
186: year = Integer.parseInt(text
187: .substring(start + 7, start + 9));
188: if (year < 40) {
189: year += 2000;
190: } else {
191: year += 1900;
192: }
193: ;
194: start -= 2;
195: } else {
196: year = Integer.parseInt(text.substring(start + 7,
197: start + 11));
198: }
199: int hour = Integer.parseInt(text.substring(start + 12,
200: start + 14));
201: int minute = Integer.parseInt(text.substring(start + 15,
202: start + 17));
203: int second = Integer.parseInt(text.substring(start + 18,
204: start + 20));
205: String stGMT = text.substring(start + 21, start + 24);
206: if (!stGMT.equals("GMT")) {
207: return null;
208: } else {
209: calendar.set(Calendar.ZONE_OFFSET, /*GMT:*/0); // NYC is ZONE_OFFSET=5 or 4
210: //calendar.set( Calendar.DST_OFFSET, sum );
211: pos.setIndex(start + 29);
212: }
213:
214: calendar.set(year, month - 1, day, hour, minute, second);
215: Date retval = calendar.getTime();
216: //System.out.println( " "+ text + "******" + retval );
217: return retval;
218: }
219:
220: /**
221: * Override readObject.
222: */
223: private void readObject(ObjectInputStream stream)
224: throws IOException, ClassNotFoundException {
225: stream.defaultReadObject();
226: /*
227: if (serialVersionOnStream < 1) {
228: // didn't have defaultCenturyStart field
229: initializeDefaultCentury();
230: }
231: else {
232: // fill in dependent transient field
233: parseAmbiguousDatesAsAfter(defaultCenturyStart);
234: }
235: */
236: serialVersionOnStream = currentSerialVersion;
237: }
238: }
|