1:
39:
40:
41: package ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47:
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60:
61:
65: public class SimpleDateFormat extends DateFormat
66: {
67:
73: private class CompiledField
74: {
75:
79: int field;
80:
81:
85: int size;
86:
87:
90: private char character;
91:
92:
101: public CompiledField(int f, int s, char c)
102: {
103: field = f;
104: size = s;
105: character = c;
106: }
107:
108:
112: public int getField()
113: {
114: return field;
115: }
116:
117:
120: public int getSize()
121: {
122: return size;
123: }
124:
125:
128: public char getCharacter()
129: {
130: return character;
131: }
132:
133:
140: public String toString()
141: {
142: StringBuffer builder;
143:
144: builder = new StringBuffer(getClass().getName());
145: builder.append("[field=");
146: builder.append(field);
147: builder.append(", size=");
148: builder.append(size);
149: builder.append(", character=");
150: builder.append(character);
151: builder.append("]");
152:
153: return builder.toString();
154: }
155: }
156:
157:
164: private transient ArrayList tokens;
165:
166:
174: private DateFormatSymbols formatData;
175:
176:
189: private Date defaultCenturyStart;
190:
191:
199: private transient int defaultCentury;
200:
201:
213: private String pattern;
214:
215:
227: private int serialVersionOnStream = 1;
228:
229:
232: private static final long serialVersionUID = 4774881970558875024L;
233:
234:
235:
236:
237: private static final String standardChars = "GyMdkHmsSEDFwWahKzYeugAZ";
238:
239:
253: private void readObject(ObjectInputStream stream)
254: throws IOException, ClassNotFoundException
255: {
256: stream.defaultReadObject();
257: if (serialVersionOnStream < 1)
258: {
259: computeCenturyStart ();
260: serialVersionOnStream = 1;
261: }
262: else
263:
264: set2DigitYearStart(defaultCenturyStart);
265:
266:
267: tokens = new ArrayList();
268: try
269: {
270: compileFormat(pattern);
271: }
272: catch (IllegalArgumentException e)
273: {
274: throw new InvalidObjectException("The stream pattern was invalid.");
275: }
276: }
277:
278:
287: private void compileFormat(String pattern)
288: {
289:
290:
291:
292: char thisChar;
293: int pos;
294: int field;
295: CompiledField current = null;
296:
297: for (int i = 0; i < pattern.length(); i++)
298: {
299: thisChar = pattern.charAt(i);
300: field = standardChars.indexOf(thisChar);
301: if (field == -1)
302: {
303: current = null;
304: if ((thisChar >= 'A' && thisChar <= 'Z')
305: || (thisChar >= 'a' && thisChar <= 'z'))
306: {
307:
308: throw new IllegalArgumentException("Invalid letter "
309: + thisChar +
310: " encountered at character "
311: + i + ".");
312: }
313: else if (thisChar == '\'')
314: {
315:
316: pos = pattern.indexOf('\'', i + 1);
317:
318: if (pos == i + 1)
319: tokens.add("'");
320: else
321: {
322:
323:
324:
325: StringBuffer buf = new StringBuffer();
326: int oldPos = i + 1;
327: do
328: {
329: if (pos == -1)
330: throw new IllegalArgumentException("Quotes starting at character "
331: + i +
332: " not closed.");
333: buf.append(pattern.substring(oldPos, pos));
334: if (pos + 1 >= pattern.length()
335: || pattern.charAt(pos + 1) != '\'')
336: break;
337: buf.append('\'');
338: oldPos = pos + 2;
339: pos = pattern.indexOf('\'', pos + 2);
340: }
341: while (true);
342: tokens.add(buf.toString());
343: }
344: i = pos;
345: }
346: else
347: {
348:
349: tokens.add(new Character(thisChar));
350: }
351: }
352: else
353: {
354:
355: if ((current != null) && (field == current.field))
356: current.size++;
357: else
358: {
359: current = new CompiledField(field, 1, thisChar);
360: tokens.add(current);
361: }
362: }
363: }
364: }
365:
366:
373: public String toString()
374: {
375: StringBuffer output = new StringBuffer(getClass().getName());
376: output.append("[tokens=");
377: output.append(tokens);
378: output.append(", formatData=");
379: output.append(formatData);
380: output.append(", defaultCenturyStart=");
381: output.append(defaultCenturyStart);
382: output.append(", defaultCentury=");
383: output.append(defaultCentury);
384: output.append(", pattern=");
385: output.append(pattern);
386: output.append(", serialVersionOnStream=");
387: output.append(serialVersionOnStream);
388: output.append(", standardChars=");
389: output.append(standardChars);
390: output.append("]");
391: return output.toString();
392: }
393:
394:
398: public SimpleDateFormat()
399: {
400:
405: super();
406: Locale locale = Locale.getDefault();
407: calendar = new GregorianCalendar(locale);
408: computeCenturyStart();
409: tokens = new ArrayList();
410: formatData = new DateFormatSymbols(locale);
411: pattern = (formatData.dateFormats[DEFAULT] + ' '
412: + formatData.timeFormats[DEFAULT]);
413: compileFormat(pattern);
414: numberFormat = NumberFormat.getInstance(locale);
415: numberFormat.setGroupingUsed (false);
416: numberFormat.setParseIntegerOnly (true);
417: numberFormat.setMaximumFractionDigits (0);
418: }
419:
420:
428: public SimpleDateFormat(String pattern)
429: {
430: this(pattern, Locale.getDefault());
431: }
432:
433:
442: public SimpleDateFormat(String pattern, Locale locale)
443: {
444: super();
445: calendar = new GregorianCalendar(locale);
446: computeCenturyStart();
447: tokens = new ArrayList();
448: formatData = new DateFormatSymbols(locale);
449: compileFormat(pattern);
450: this.pattern = pattern;
451: numberFormat = NumberFormat.getInstance(locale);
452: numberFormat.setGroupingUsed (false);
453: numberFormat.setParseIntegerOnly (true);
454: numberFormat.setMaximumFractionDigits (0);
455: }
456:
457:
467: public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
468: {
469: super();
470: calendar = new GregorianCalendar();
471: computeCenturyStart ();
472: tokens = new ArrayList();
473: if (formatData == null)
474: throw new NullPointerException("formatData");
475: this.formatData = formatData;
476: compileFormat(pattern);
477: this.pattern = pattern;
478: numberFormat = NumberFormat.getInstance();
479: numberFormat.setGroupingUsed (false);
480: numberFormat.setParseIntegerOnly (true);
481: numberFormat.setMaximumFractionDigits (0);
482: }
483:
484:
490: public String toPattern()
491: {
492: return pattern;
493: }
494:
495:
501: public String toLocalizedPattern()
502: {
503: String localChars = formatData.getLocalPatternChars();
504: return translateLocalizedPattern(pattern, standardChars, localChars);
505: }
506:
507:
515: public void applyPattern(String pattern)
516: {
517: tokens = new ArrayList();
518: compileFormat(pattern);
519: this.pattern = pattern;
520: }
521:
522:
530: public void applyLocalizedPattern(String pattern)
531: {
532: String localChars = formatData.getLocalPatternChars();
533: pattern = translateLocalizedPattern(pattern, localChars, standardChars);
534: applyPattern(pattern);
535: }
536:
537:
553: private String translateLocalizedPattern(String pattern,
554: String oldChars, String newChars)
555: {
556: int len = pattern.length();
557: StringBuffer buf = new StringBuffer(len);
558: boolean quoted = false;
559: for (int i = 0; i < len; i++)
560: {
561: char ch = pattern.charAt(i);
562: if (ch == '\'')
563: quoted = ! quoted;
564: if (! quoted)
565: {
566: int j = oldChars.indexOf(ch);
567: if (j >= 0)
568: ch = newChars.charAt(j);
569: }
570: buf.append(ch);
571: }
572: return buf.toString();
573: }
574:
575:
581: public Date get2DigitYearStart()
582: {
583: return defaultCenturyStart;
584: }
585:
586:
592: public void set2DigitYearStart(Date date)
593: {
594: defaultCenturyStart = date;
595: calendar.clear();
596: calendar.setTime(date);
597: int year = calendar.get(Calendar.YEAR);
598: defaultCentury = year - (year % 100);
599: }
600:
601:
607: public DateFormatSymbols getDateFormatSymbols()
608: {
609: return (DateFormatSymbols) formatData.clone();
610: }
611:
612:
619: public void setDateFormatSymbols(DateFormatSymbols formatData)
620: {
621: if (formatData == null)
622: {
623: throw new
624: NullPointerException("The supplied format data was null.");
625: }
626: this.formatData = formatData;
627: }
628:
629:
648: public boolean equals(Object o)
649: {
650: if (!super.equals(o))
651: return false;
652:
653: if (!(o instanceof SimpleDateFormat))
654: return false;
655:
656: SimpleDateFormat sdf = (SimpleDateFormat)o;
657:
658: if (defaultCentury != sdf.defaultCentury)
659: return false;
660:
661: if (!toPattern().equals(sdf.toPattern()))
662: return false;
663:
664: if (!getDateFormatSymbols().equals(sdf.getDateFormatSymbols()))
665: return false;
666:
667: return true;
668: }
669:
670:
675: public int hashCode()
676: {
677: return super.hashCode() ^ toPattern().hashCode() ^ defaultCentury ^
678: getDateFormatSymbols().hashCode();
679: }
680:
681:
682:
687: private void formatWithAttribute(Date date, FormatBuffer buffer, FieldPosition pos)
688: {
689: String temp;
690: AttributedCharacterIterator.Attribute attribute;
691: calendar.setTime(date);
692:
693:
694: Iterator iter = tokens.iterator();
695: while (iter.hasNext())
696: {
697: Object o = iter.next();
698: if (o instanceof CompiledField)
699: {
700: CompiledField cf = (CompiledField) o;
701: int beginIndex = buffer.length();
702:
703: switch (cf.getField())
704: {
705: case ERA_FIELD:
706: buffer.append (formatData.eras[calendar.get (Calendar.ERA)], DateFormat.Field.ERA);
707: break;
708: case YEAR_FIELD:
709:
710:
711: buffer.setDefaultAttribute (DateFormat.Field.YEAR);
712: if (cf.getSize() == 2)
713: {
714: temp = "00"+String.valueOf (calendar.get (Calendar.YEAR));
715: buffer.append (temp.substring (temp.length() - 2));
716: }
717: else
718: withLeadingZeros (calendar.get (Calendar.YEAR), cf.getSize(), buffer);
719: break;
720: case MONTH_FIELD:
721: buffer.setDefaultAttribute (DateFormat.Field.MONTH);
722: if (cf.getSize() < 3)
723: withLeadingZeros (calendar.get (Calendar.MONTH) + 1, cf.getSize(), buffer);
724: else if (cf.getSize() < 4)
725: buffer.append (formatData.shortMonths[calendar.get (Calendar.MONTH)]);
726: else
727: buffer.append (formatData.months[calendar.get (Calendar.MONTH)]);
728: break;
729: case DATE_FIELD:
730: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_MONTH);
731: withLeadingZeros (calendar.get (Calendar.DATE), cf.getSize(), buffer);
732: break;
733: case HOUR_OF_DAY1_FIELD:
734: buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY1);
735: withLeadingZeros ( ((calendar.get (Calendar.HOUR_OF_DAY) + 23) % 24) + 1,
736: cf.getSize(), buffer);
737: break;
738: case HOUR_OF_DAY0_FIELD:
739: buffer.setDefaultAttribute (DateFormat.Field.HOUR_OF_DAY0);
740: withLeadingZeros (calendar.get (Calendar.HOUR_OF_DAY), cf.getSize(), buffer);
741: break;
742: case MINUTE_FIELD:
743: buffer.setDefaultAttribute (DateFormat.Field.MINUTE);
744: withLeadingZeros (calendar.get (Calendar.MINUTE),
745: cf.getSize(), buffer);
746: break;
747: case SECOND_FIELD:
748: buffer.setDefaultAttribute (DateFormat.Field.SECOND);
749: withLeadingZeros(calendar.get (Calendar.SECOND),
750: cf.getSize(), buffer);
751: break;
752: case MILLISECOND_FIELD:
753: buffer.setDefaultAttribute (DateFormat.Field.MILLISECOND);
754: withLeadingZeros (calendar.get (Calendar.MILLISECOND), cf.getSize(), buffer);
755: break;
756: case DAY_OF_WEEK_FIELD:
757: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK);
758: if (cf.getSize() < 4)
759: buffer.append (formatData.shortWeekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
760: else
761: buffer.append (formatData.weekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
762: break;
763: case DAY_OF_YEAR_FIELD:
764: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_YEAR);
765: withLeadingZeros (calendar.get (Calendar.DAY_OF_YEAR), cf.getSize(), buffer);
766: break;
767: case DAY_OF_WEEK_IN_MONTH_FIELD:
768: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK_IN_MONTH);
769: withLeadingZeros (calendar.get (Calendar.DAY_OF_WEEK_IN_MONTH),
770: cf.getSize(), buffer);
771: break;
772: case WEEK_OF_YEAR_FIELD:
773: buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_YEAR);
774: withLeadingZeros (calendar.get (Calendar.WEEK_OF_YEAR),
775: cf.getSize(), buffer);
776: break;
777: case WEEK_OF_MONTH_FIELD:
778: buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_MONTH);
779: withLeadingZeros (calendar.get (Calendar.WEEK_OF_MONTH),
780: cf.getSize(), buffer);
781: break;
782: case AM_PM_FIELD:
783: buffer.setDefaultAttribute (DateFormat.Field.AM_PM);
784: buffer.append (formatData.ampms[calendar.get (Calendar.AM_PM)]);
785: break;
786: case HOUR1_FIELD:
787: buffer.setDefaultAttribute (DateFormat.Field.HOUR1);
788: withLeadingZeros (((calendar.get (Calendar.HOUR) + 11) % 12) + 1,
789: cf.getSize(), buffer);
790: break;
791: case HOUR0_FIELD:
792: buffer.setDefaultAttribute (DateFormat.Field.HOUR0);
793: withLeadingZeros (calendar.get (Calendar.HOUR), cf.getSize(), buffer);
794: break;
795: case TIMEZONE_FIELD:
796: buffer.setDefaultAttribute (DateFormat.Field.TIME_ZONE);
797: TimeZone zone = calendar.getTimeZone();
798: boolean isDST = calendar.get (Calendar.DST_OFFSET) != 0;
799:
800: String zoneID = zone.getDisplayName
801: (isDST, cf.getSize() > 3 ? TimeZone.LONG : TimeZone.SHORT);
802: buffer.append (zoneID);
803: break;
804: case RFC822_TIMEZONE_FIELD:
805: buffer.setDefaultAttribute(DateFormat.Field.RFC822_TIME_ZONE);
806: int pureMinutes = (calendar.get(Calendar.ZONE_OFFSET) +
807: calendar.get(Calendar.DST_OFFSET)) / (1000 * 60);
808: String sign = (pureMinutes < 0) ? "-" : "+";
809: pureMinutes = Math.abs(pureMinutes);
810: int hours = pureMinutes / 60;
811: int minutes = pureMinutes % 60;
812: buffer.append(sign);
813: withLeadingZeros(hours, 2, buffer);
814: withLeadingZeros(minutes, 2, buffer);
815: break;
816: default:
817: throw new IllegalArgumentException ("Illegal pattern character " +
818: cf.getCharacter());
819: }
820: if (pos != null && (buffer.getDefaultAttribute() == pos.getFieldAttribute()
821: || cf.getField() == pos.getField()))
822: {
823: pos.setBeginIndex(beginIndex);
824: pos.setEndIndex(buffer.length());
825: }
826: }
827: else
828: {
829: buffer.append(o.toString(), null);
830: }
831: }
832: }
833:
834: public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
835: {
836: formatWithAttribute(date, new StringFormatBuffer (buffer), pos);
837:
838: return buffer;
839: }
840:
841: public AttributedCharacterIterator formatToCharacterIterator(Object date)
842: throws IllegalArgumentException
843: {
844: if (date == null)
845: throw new NullPointerException("null argument");
846: if (!(date instanceof Date))
847: throw new IllegalArgumentException("argument should be an instance of java.util.Date");
848:
849: AttributedFormatBuffer buf = new AttributedFormatBuffer();
850: formatWithAttribute((Date)date, buf,
851: null);
852: buf.sync();
853:
854: return new FormatCharacterIterator(buf.getBuffer().toString(),
855: buf.getRanges(),
856: buf.getAttributes());
857: }
858:
859: private void withLeadingZeros(int value, int length, FormatBuffer buffer)
860: {
861: String valStr = String.valueOf(value);
862: for (length -= valStr.length(); length > 0; length--)
863: buffer.append('0');
864: buffer.append(valStr);
865: }
866:
867: private boolean expect(String source, ParsePosition pos, char ch)
868: {
869: int x = pos.getIndex();
870: boolean r = x < source.length() && source.charAt(x) == ch;
871: if (r)
872: pos.setIndex(x + 1);
873: else
874: pos.setErrorIndex(x);
875: return r;
876: }
877:
878:
887: public Date parse (String dateStr, ParsePosition pos)
888: {
889: int fmt_index = 0;
890: int fmt_max = pattern.length();
891:
892: calendar.clear();
893: boolean saw_timezone = false;
894: int quote_start = -1;
895: boolean is2DigitYear = false;
896: try
897: {
898: for (; fmt_index < fmt_max; ++fmt_index)
899: {
900: char ch = pattern.charAt(fmt_index);
901: if (ch == '\'')
902: {
903: int index = pos.getIndex();
904: if (fmt_index < fmt_max - 1
905: && pattern.charAt(fmt_index + 1) == '\'')
906: {
907: if (! expect (dateStr, pos, ch))
908: return null;
909: ++fmt_index;
910: }
911: else
912: quote_start = quote_start < 0 ? fmt_index : -1;
913: continue;
914: }
915:
916: if (quote_start != -1
917: || ((ch < 'a' || ch > 'z')
918: && (ch < 'A' || ch > 'Z')))
919: {
920: if (quote_start == -1 && ch == ' ')
921: {
922:
923:
924: int index = pos.getIndex();
925: int save = index;
926: while (index < dateStr.length()
927: && Character.isWhitespace(dateStr.charAt(index)))
928: ++index;
929: if (index > save)
930: pos.setIndex(index);
931: else
932: {
933:
934: pos.setErrorIndex(index);
935: return null;
936: }
937: }
938: else if (! expect (dateStr, pos, ch))
939: return null;
940: continue;
941: }
942:
943:
944:
945: int fmt_count = 1;
946: while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
947: {
948: ++fmt_count;
949: }
950:
951:
952:
953:
954: boolean limit_digits = false;
955: if (fmt_index < fmt_max
956: && standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
957: limit_digits = true;
958: --fmt_index;
959:
960:
961:
962:
963:
964:
965: int calendar_field;
966: boolean is_numeric = true;
967: int offset = 0;
968: boolean maybe2DigitYear = false;
969: boolean oneBasedHour = false;
970: boolean oneBasedHourOfDay = false;
971: Integer simpleOffset;
972: String[] set1 = null;
973: String[] set2 = null;
974: switch (ch)
975: {
976: case 'd':
977: calendar_field = Calendar.DATE;
978: break;
979: case 'D':
980: calendar_field = Calendar.DAY_OF_YEAR;
981: break;
982: case 'F':
983: calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
984: break;
985: case 'E':
986: is_numeric = false;
987: offset = 1;
988: calendar_field = Calendar.DAY_OF_WEEK;
989: set1 = formatData.getWeekdays();
990: set2 = formatData.getShortWeekdays();
991: break;
992: case 'w':
993: calendar_field = Calendar.WEEK_OF_YEAR;
994: break;
995: case 'W':
996: calendar_field = Calendar.WEEK_OF_MONTH;
997: break;
998: case 'M':
999: calendar_field = Calendar.MONTH;
1000: if (fmt_count <= 2)
1001: offset = -1;
1002: else
1003: {
1004: is_numeric = false;
1005: set1 = formatData.getMonths();
1006: set2 = formatData.getShortMonths();
1007: }
1008: break;
1009: case 'y':
1010: calendar_field = Calendar.YEAR;
1011: if (fmt_count <= 2)
1012: maybe2DigitYear = true;
1013: break;
1014: case 'K':
1015: calendar_field = Calendar.HOUR;
1016: break;
1017: case 'h':
1018: calendar_field = Calendar.HOUR;
1019: oneBasedHour = true;
1020: break;
1021: case 'H':
1022: calendar_field = Calendar.HOUR_OF_DAY;
1023: break;
1024: case 'k':
1025: calendar_field = Calendar.HOUR_OF_DAY;
1026: oneBasedHourOfDay = true;
1027: break;
1028: case 'm':
1029: calendar_field = Calendar.MINUTE;
1030: break;
1031: case 's':
1032: calendar_field = Calendar.SECOND;
1033: break;
1034: case 'S':
1035: calendar_field = Calendar.MILLISECOND;
1036: break;
1037: case 'a':
1038: is_numeric = false;
1039: calendar_field = Calendar.AM_PM;
1040: set1 = formatData.getAmPmStrings();
1041: break;
1042: case 'z':
1043: case 'Z':
1044:
1045:
1046: is_numeric = false;
1047: calendar_field = Calendar.ZONE_OFFSET;
1048: String[][] zoneStrings = formatData.getZoneStrings();
1049: int zoneCount = zoneStrings.length;
1050: int index = pos.getIndex();
1051: boolean found_zone = false;
1052: simpleOffset = computeOffset(dateStr.substring(index), pos);
1053: if (simpleOffset != null)
1054: {
1055: found_zone = true;
1056: saw_timezone = true;
1057: calendar.set(Calendar.DST_OFFSET, 0);
1058: offset = simpleOffset.intValue();
1059: }
1060: else
1061: {
1062: for (int j = 0; j < zoneCount; j++)
1063: {
1064: String[] strings = zoneStrings[j];
1065: int k;
1066: for (k = 0; k < strings.length; ++k)
1067: {
1068: if (dateStr.startsWith(strings[k], index))
1069: break;
1070: }
1071: if (k != strings.length)
1072: {
1073: found_zone = true;
1074: saw_timezone = true;
1075: TimeZone tz = TimeZone.getTimeZone (strings[0]);
1076:
1077: if(k == 3 || k == 4)
1078: calendar.set (Calendar.DST_OFFSET, tz.getDSTSavings());
1079: else
1080: calendar.set (Calendar.DST_OFFSET, 0);
1081: offset = tz.getRawOffset ();
1082: pos.setIndex(index + strings[k].length());
1083: break;
1084: }
1085: }
1086: }
1087: if (! found_zone)
1088: {
1089: pos.setErrorIndex(pos.getIndex());
1090: return null;
1091: }
1092: break;
1093: default:
1094: pos.setErrorIndex(pos.getIndex());
1095: return null;
1096: }
1097:
1098:
1099: int value;
1100: int index = -1;
1101: if (is_numeric)
1102: {
1103: numberFormat.setMinimumIntegerDigits(fmt_count);
1104: if (maybe2DigitYear)
1105: index = pos.getIndex();
1106: Number n = null;
1107: if (limit_digits)
1108: {
1109:
1110:
1111:
1112: int origPos = pos.getIndex();
1113: pos.setIndex(0);
1114: n = numberFormat.parse(dateStr.substring(origPos, origPos + fmt_count), pos);
1115: pos.setIndex(origPos + pos.getIndex());
1116: }
1117: else
1118: n = numberFormat.parse(dateStr, pos);
1119: if (pos == null || ! (n instanceof Long))
1120: return null;
1121: value = n.intValue() + offset;
1122: }
1123: else if (set1 != null)
1124: {
1125: index = pos.getIndex();
1126: int i;
1127: boolean found = false;
1128: for (i = offset; i < set1.length; ++i)
1129: {
1130: if (set1[i] != null)
1131: if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(),
1132: index))
1133: {
1134: found = true;
1135: pos.setIndex(index + set1[i].length());
1136: break;
1137: }
1138: }
1139: if (!found && set2 != null)
1140: {
1141: for (i = offset; i < set2.length; ++i)
1142: {
1143: if (set2[i] != null)
1144: if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(),
1145: index))
1146: {
1147: found = true;
1148: pos.setIndex(index + set2[i].length());
1149: break;
1150: }
1151: }
1152: }
1153: if (!found)
1154: {
1155: pos.setErrorIndex(index);
1156: return null;
1157: }
1158: value = i;
1159: }
1160: else
1161: value = offset;
1162:
1163: if (maybe2DigitYear)
1164: {
1165:
1166:
1167: int digit_count = pos.getIndex() - index;
1168: if (digit_count == 2)
1169: {
1170: is2DigitYear = true;
1171: value += defaultCentury;
1172: }
1173: }
1174:
1175:
1176:
1177: if (oneBasedHour && value == 12)
1178: value = 0;
1179:
1180: if (oneBasedHourOfDay && value == 24)
1181: value = 0;
1182:
1183:
1184: calendar.set(calendar_field, value);
1185: }
1186:
1187: if (is2DigitYear)
1188: {
1189:
1190:
1191: int year = calendar.get(Calendar.YEAR);
1192: if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
1193: calendar.set(Calendar.YEAR, year + 100);
1194: }
1195: if (! saw_timezone)
1196: {
1197:
1198:
1199: calendar.clear (Calendar.DST_OFFSET);
1200: calendar.clear (Calendar.ZONE_OFFSET);
1201: }
1202: return calendar.getTime();
1203: }
1204: catch (IllegalArgumentException x)
1205: {
1206: pos.setErrorIndex(pos.getIndex());
1207: return null;
1208: }
1209: }
1210:
1211:
1249: private Integer computeOffset(String zoneString, ParsePosition pos)
1250: {
1251: Pattern pattern =
1252: Pattern.compile("(GMT)?([+-])([012])?([0-9]):?([0-9]{2})");
1253: Matcher matcher = pattern.matcher(zoneString);
1254:
1255:
1256: boolean hasAll = matcher.lookingAt();
1257: try
1258: {
1259:
1260: matcher.group(2);
1261: matcher.group(4);
1262: matcher.group(5);
1263: }
1264: catch (IllegalStateException ise)
1265: {
1266: hasAll = false;
1267: }
1268: if (hasAll)
1269: {
1270: int sign = matcher.group(2).equals("+") ? 1 : -1;
1271: int hour = Integer.parseInt(matcher.group(4));
1272: if (!matcher.group(3).equals(""))
1273: hour += (Integer.parseInt(matcher.group(3)) * 10);
1274: int minutes = Integer.parseInt(matcher.group(5));
1275:
1276: if (hour > 23)
1277: return null;
1278: int offset = sign * ((hour * 60) + minutes) * 60000;
1279:
1280:
1281: pos.setIndex(pos.getIndex() + matcher.end());
1282: return new Integer(offset);
1283: }
1284: else if (zoneString.startsWith("GMT"))
1285: {
1286: pos.setIndex(pos.getIndex() + 3);
1287: return new Integer(0);
1288: }
1289: return null;
1290: }
1291:
1292:
1293:
1294: private void computeCenturyStart()
1295: {
1296: int year = calendar.get(Calendar.YEAR);
1297: calendar.set(Calendar.YEAR, year - 80);
1298: set2DigitYearStart(calendar.getTime());
1299: }
1300:
1301:
1307: public Object clone()
1308: {
1309: SimpleDateFormat clone = (SimpleDateFormat) super.clone();
1310: clone.setDateFormatSymbols((DateFormatSymbols) formatData.clone());
1311: clone.set2DigitYearStart((Date) defaultCenturyStart.clone());
1312: return clone;
1313: }
1314:
1315: }