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: thisChar = pattern.charAt(i);
299: field = standardChars.indexOf(thisChar);
300: if (field == -1) {
301: current = null;
302: if ((thisChar >= 'A' && thisChar <= 'Z')
303: || (thisChar >= 'a' && thisChar <= 'z')) {
304:
305: throw new IllegalArgumentException("Invalid letter " + thisChar +
306: "encountered at character " + i
307: + ".");
308: } else if (thisChar == '\'') {
309:
310: pos = pattern.indexOf('\'',i+1);
311: if (pos == -1) {
312: throw new IllegalArgumentException("Quotes starting at character "
313: + i + " not closed.");
314: }
315: if ((pos+1 < pattern.length()) && (pattern.charAt(pos+1) == '\'')) {
316: tokens.add(pattern.substring(i+1,pos+1));
317: } else {
318: tokens.add(pattern.substring(i+1,pos));
319: }
320: i = pos;
321: } else {
322:
323: tokens.add(new Character(thisChar));
324: }
325: } else {
326:
327: if ((current != null) && (field == current.field)) {
328: current.size++;
329: } else {
330: current = new CompiledField(field,1,thisChar);
331: tokens.add(current);
332: }
333: }
334: }
335: }
336:
337:
344: public String toString()
345: {
346: StringBuffer output = new StringBuffer(getClass().getName());
347: output.append("[tokens=");
348: output.append(tokens);
349: output.append(", formatData=");
350: output.append(formatData);
351: output.append(", defaultCenturyStart=");
352: output.append(defaultCenturyStart);
353: output.append(", defaultCentury=");
354: output.append(defaultCentury);
355: output.append(", pattern=");
356: output.append(pattern);
357: output.append(", serialVersionOnStream=");
358: output.append(serialVersionOnStream);
359: output.append(", standardChars=");
360: output.append(standardChars);
361: output.append("]");
362: return output.toString();
363: }
364:
365:
369: public SimpleDateFormat()
370: {
371:
376: super();
377: Locale locale = Locale.getDefault();
378: calendar = new GregorianCalendar(locale);
379: computeCenturyStart();
380: tokens = new ArrayList();
381: formatData = new DateFormatSymbols(locale);
382: pattern = (formatData.dateFormats[DEFAULT] + ' '
383: + formatData.timeFormats[DEFAULT]);
384: compileFormat(pattern);
385: numberFormat = NumberFormat.getInstance(locale);
386: numberFormat.setGroupingUsed (false);
387: numberFormat.setParseIntegerOnly (true);
388: numberFormat.setMaximumFractionDigits (0);
389: }
390:
391:
399: public SimpleDateFormat(String pattern)
400: {
401: this(pattern, Locale.getDefault());
402: }
403:
404:
413: public SimpleDateFormat(String pattern, Locale locale)
414: {
415: super();
416: calendar = new GregorianCalendar(locale);
417: computeCenturyStart();
418: tokens = new ArrayList();
419: formatData = new DateFormatSymbols(locale);
420: compileFormat(pattern);
421: this.pattern = pattern;
422: numberFormat = NumberFormat.getInstance(locale);
423: numberFormat.setGroupingUsed (false);
424: numberFormat.setParseIntegerOnly (true);
425: numberFormat.setMaximumFractionDigits (0);
426: }
427:
428:
438: public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
439: {
440: super();
441: calendar = new GregorianCalendar();
442: computeCenturyStart ();
443: tokens = new ArrayList();
444: if (formatData == null)
445: throw new NullPointerException("formatData");
446: this.formatData = formatData;
447: compileFormat(pattern);
448: this.pattern = pattern;
449: numberFormat = NumberFormat.getInstance();
450: numberFormat.setGroupingUsed (false);
451: numberFormat.setParseIntegerOnly (true);
452: numberFormat.setMaximumFractionDigits (0);
453: }
454:
455:
461: public String toPattern()
462: {
463: return pattern;
464: }
465:
466:
472: public String toLocalizedPattern()
473: {
474: String localChars = formatData.getLocalPatternChars();
475: return translateLocalizedPattern(pattern, standardChars, localChars);
476: }
477:
478:
486: public void applyPattern(String pattern)
487: {
488: tokens = new ArrayList();
489: compileFormat(pattern);
490: this.pattern = pattern;
491: }
492:
493:
501: public void applyLocalizedPattern(String pattern)
502: {
503: String localChars = formatData.getLocalPatternChars();
504: pattern = translateLocalizedPattern(pattern, localChars, standardChars);
505: applyPattern(pattern);
506: }
507:
508:
524: private String translateLocalizedPattern(String pattern,
525: String oldChars, String newChars)
526: {
527: int len = pattern.length();
528: StringBuffer buf = new StringBuffer(len);
529: boolean quoted = false;
530: for (int i = 0; i < len; i++)
531: {
532: char ch = pattern.charAt(i);
533: if (ch == '\'')
534: quoted = ! quoted;
535: if (! quoted)
536: {
537: int j = oldChars.indexOf(ch);
538: if (j >= 0)
539: ch = newChars.charAt(j);
540: }
541: buf.append(ch);
542: }
543: return buf.toString();
544: }
545:
546:
552: public Date get2DigitYearStart()
553: {
554: return defaultCenturyStart;
555: }
556:
557:
563: public void set2DigitYearStart(Date date)
564: {
565: defaultCenturyStart = date;
566: calendar.clear();
567: calendar.setTime(date);
568: int year = calendar.get(Calendar.YEAR);
569: defaultCentury = year - (year % 100);
570: }
571:
572:
578: public DateFormatSymbols getDateFormatSymbols()
579: {
580: return (DateFormatSymbols) formatData.clone();
581: }
582:
583:
590: public void setDateFormatSymbols(DateFormatSymbols formatData)
591: {
592: if (formatData == null)
593: {
594: throw new
595: NullPointerException("The supplied format data was null.");
596: }
597: this.formatData = formatData;
598: }
599:
600:
619: public boolean equals(Object o)
620: {
621: if (!super.equals(o))
622: return false;
623:
624: if (!(o instanceof SimpleDateFormat))
625: return false;
626:
627: SimpleDateFormat sdf = (SimpleDateFormat)o;
628:
629: if (defaultCentury != sdf.defaultCentury)
630: return false;
631:
632: if (!toPattern().equals(sdf.toPattern()))
633: return false;
634:
635: if (!getDateFormatSymbols().equals(sdf.getDateFormatSymbols()))
636: return false;
637:
638: return true;
639: }
640:
641:
646: public int hashCode()
647: {
648: return super.hashCode() ^ toPattern().hashCode() ^ defaultCentury ^
649: getDateFormatSymbols().hashCode();
650: }
651:
652:
653:
658: private void formatWithAttribute(Date date, FormatBuffer buffer, FieldPosition pos)
659: {
660: String temp;
661: AttributedCharacterIterator.Attribute attribute;
662: calendar.setTime(date);
663:
664:
665: Iterator iter = tokens.iterator();
666: while (iter.hasNext())
667: {
668: Object o = iter.next();
669: if (o instanceof CompiledField)
670: {
671: CompiledField cf = (CompiledField) o;
672: int beginIndex = buffer.length();
673:
674: switch (cf.getField())
675: {
676: case ERA_FIELD:
677: buffer.append (formatData.eras[calendar.get (Calendar.ERA)], DateFormat.Field.ERA);
678: break;
679: case YEAR_FIELD:
680:
681:
682: buffer.setDefaultAttribute (DateFormat.Field.YEAR);
683: if (cf.getSize() == 2)
684: {
685: temp = "00"+String.valueOf (calendar.get (Calendar.YEAR));
686: buffer.append (temp.substring (temp.length() - 2));
687: }
688: else
689: withLeadingZeros (calendar.get (Calendar.YEAR), cf.getSize(), buffer);
690: break;
691: case MONTH_FIELD:
692: buffer.setDefaultAttribute (DateFormat.Field.MONTH);
693: if (cf.getSize() < 3)
694: withLeadingZeros (calendar.get (Calendar.MONTH) + 1, cf.getSize(), buffer);
695: else if (cf.getSize() < 4)
696: buffer.append (formatData.shortMonths[calendar.get (Calendar.MONTH)]);
697: else
698: buffer.append (formatData.months[calendar.get (Calendar.MONTH)]);
699: break;
700: case DATE_FIELD:
701: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_MONTH);
702: withLeadingZeros (calendar.get (Calendar.DATE), cf.getSize(), buffer);
703: break;
704: case HOUR_OF_DAY1_FIELD:
705: buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY1);
706: withLeadingZeros ( ((calendar.get (Calendar.HOUR_OF_DAY) + 23) % 24) + 1,
707: cf.getSize(), buffer);
708: break;
709: case HOUR_OF_DAY0_FIELD:
710: buffer.setDefaultAttribute (DateFormat.Field.HOUR_OF_DAY0);
711: withLeadingZeros (calendar.get (Calendar.HOUR_OF_DAY), cf.getSize(), buffer);
712: break;
713: case MINUTE_FIELD:
714: buffer.setDefaultAttribute (DateFormat.Field.MINUTE);
715: withLeadingZeros (calendar.get (Calendar.MINUTE),
716: cf.getSize(), buffer);
717: break;
718: case SECOND_FIELD:
719: buffer.setDefaultAttribute (DateFormat.Field.SECOND);
720: withLeadingZeros(calendar.get (Calendar.SECOND),
721: cf.getSize(), buffer);
722: break;
723: case MILLISECOND_FIELD:
724: buffer.setDefaultAttribute (DateFormat.Field.MILLISECOND);
725: withLeadingZeros (calendar.get (Calendar.MILLISECOND), cf.getSize(), buffer);
726: break;
727: case DAY_OF_WEEK_FIELD:
728: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK);
729: if (cf.getSize() < 4)
730: buffer.append (formatData.shortWeekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
731: else
732: buffer.append (formatData.weekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
733: break;
734: case DAY_OF_YEAR_FIELD:
735: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_YEAR);
736: withLeadingZeros (calendar.get (Calendar.DAY_OF_YEAR), cf.getSize(), buffer);
737: break;
738: case DAY_OF_WEEK_IN_MONTH_FIELD:
739: buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK_IN_MONTH);
740: withLeadingZeros (calendar.get (Calendar.DAY_OF_WEEK_IN_MONTH),
741: cf.getSize(), buffer);
742: break;
743: case WEEK_OF_YEAR_FIELD:
744: buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_YEAR);
745: withLeadingZeros (calendar.get (Calendar.WEEK_OF_YEAR),
746: cf.getSize(), buffer);
747: break;
748: case WEEK_OF_MONTH_FIELD:
749: buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_MONTH);
750: withLeadingZeros (calendar.get (Calendar.WEEK_OF_MONTH),
751: cf.getSize(), buffer);
752: break;
753: case AM_PM_FIELD:
754: buffer.setDefaultAttribute (DateFormat.Field.AM_PM);
755: buffer.append (formatData.ampms[calendar.get (Calendar.AM_PM)]);
756: break;
757: case HOUR1_FIELD:
758: buffer.setDefaultAttribute (DateFormat.Field.HOUR1);
759: withLeadingZeros (((calendar.get (Calendar.HOUR) + 11) % 12) + 1,
760: cf.getSize(), buffer);
761: break;
762: case HOUR0_FIELD:
763: buffer.setDefaultAttribute (DateFormat.Field.HOUR0);
764: withLeadingZeros (calendar.get (Calendar.HOUR), cf.getSize(), buffer);
765: break;
766: case TIMEZONE_FIELD:
767: buffer.setDefaultAttribute (DateFormat.Field.TIME_ZONE);
768: TimeZone zone = calendar.getTimeZone();
769: boolean isDST = calendar.get (Calendar.DST_OFFSET) != 0;
770:
771: String zoneID = zone.getDisplayName
772: (isDST, cf.getSize() > 3 ? TimeZone.LONG : TimeZone.SHORT);
773: buffer.append (zoneID);
774: break;
775: case RFC822_TIMEZONE_FIELD:
776: buffer.setDefaultAttribute(DateFormat.Field.RFC822_TIME_ZONE);
777: int pureMinutes = (calendar.get(Calendar.ZONE_OFFSET) +
778: calendar.get(Calendar.DST_OFFSET)) / (1000 * 60);
779: String sign = (pureMinutes < 0) ? "-" : "+";
780: int hours = pureMinutes / 60;
781: int minutes = pureMinutes % 60;
782: buffer.append(sign);
783: withLeadingZeros(hours, 2, buffer);
784: withLeadingZeros(minutes, 2, buffer);
785: break;
786: default:
787: throw new IllegalArgumentException ("Illegal pattern character " +
788: cf.getCharacter());
789: }
790: if (pos != null && (buffer.getDefaultAttribute() == pos.getFieldAttribute()
791: || cf.getField() == pos.getField()))
792: {
793: pos.setBeginIndex(beginIndex);
794: pos.setEndIndex(buffer.length());
795: }
796: }
797: else
798: {
799: buffer.append(o.toString(), null);
800: }
801: }
802: }
803:
804: public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
805: {
806: formatWithAttribute(date, new StringFormatBuffer (buffer), pos);
807:
808: return buffer;
809: }
810:
811: public AttributedCharacterIterator formatToCharacterIterator(Object date)
812: throws IllegalArgumentException
813: {
814: if (date == null)
815: throw new NullPointerException("null argument");
816: if (!(date instanceof Date))
817: throw new IllegalArgumentException("argument should be an instance of java.util.Date");
818:
819: AttributedFormatBuffer buf = new AttributedFormatBuffer();
820: formatWithAttribute((Date)date, buf,
821: null);
822: buf.sync();
823:
824: return new FormatCharacterIterator(buf.getBuffer().toString(),
825: buf.getRanges(),
826: buf.getAttributes());
827: }
828:
829: private void withLeadingZeros(int value, int length, FormatBuffer buffer)
830: {
831: String valStr = String.valueOf(value);
832: for (length -= valStr.length(); length > 0; length--)
833: buffer.append('0');
834: buffer.append(valStr);
835: }
836:
837: private boolean expect(String source, ParsePosition pos, char ch)
838: {
839: int x = pos.getIndex();
840: boolean r = x < source.length() && source.charAt(x) == ch;
841: if (r)
842: pos.setIndex(x + 1);
843: else
844: pos.setErrorIndex(x);
845: return r;
846: }
847:
848:
857: public Date parse (String dateStr, ParsePosition pos)
858: {
859: int fmt_index = 0;
860: int fmt_max = pattern.length();
861:
862: calendar.clear();
863: boolean saw_timezone = false;
864: int quote_start = -1;
865: boolean is2DigitYear = false;
866: try
867: {
868: for (; fmt_index < fmt_max; ++fmt_index)
869: {
870: char ch = pattern.charAt(fmt_index);
871: if (ch == '\'')
872: {
873: int index = pos.getIndex();
874: if (fmt_index < fmt_max - 1
875: && pattern.charAt(fmt_index + 1) == '\'')
876: {
877: if (! expect (dateStr, pos, ch))
878: return null;
879: ++fmt_index;
880: }
881: else
882: quote_start = quote_start < 0 ? fmt_index : -1;
883: continue;
884: }
885:
886: if (quote_start != -1
887: || ((ch < 'a' || ch > 'z')
888: && (ch < 'A' || ch > 'Z')))
889: {
890: if (! expect (dateStr, pos, ch))
891: return null;
892: continue;
893: }
894:
895:
896:
897: int fmt_count = 1;
898: while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
899: {
900: ++fmt_count;
901: }
902:
903:
904:
905:
906: boolean limit_digits = false;
907: if (fmt_index < fmt_max
908: && standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
909: limit_digits = true;
910: --fmt_index;
911:
912:
913:
914:
915:
916:
917: int calendar_field;
918: boolean is_numeric = true;
919: int offset = 0;
920: boolean maybe2DigitYear = false;
921: boolean oneBasedHour = false;
922: boolean oneBasedHourOfDay = false;
923: Integer simpleOffset;
924: String[] set1 = null;
925: String[] set2 = null;
926: switch (ch)
927: {
928: case 'd':
929: calendar_field = Calendar.DATE;
930: break;
931: case 'D':
932: calendar_field = Calendar.DAY_OF_YEAR;
933: break;
934: case 'F':
935: calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
936: break;
937: case 'E':
938: is_numeric = false;
939: offset = 1;
940: calendar_field = Calendar.DAY_OF_WEEK;
941: set1 = formatData.getWeekdays();
942: set2 = formatData.getShortWeekdays();
943: break;
944: case 'w':
945: calendar_field = Calendar.WEEK_OF_YEAR;
946: break;
947: case 'W':
948: calendar_field = Calendar.WEEK_OF_MONTH;
949: break;
950: case 'M':
951: calendar_field = Calendar.MONTH;
952: if (fmt_count <= 2)
953: offset = -1;
954: else
955: {
956: is_numeric = false;
957: set1 = formatData.getMonths();
958: set2 = formatData.getShortMonths();
959: }
960: break;
961: case 'y':
962: calendar_field = Calendar.YEAR;
963: if (fmt_count <= 2)
964: maybe2DigitYear = true;
965: break;
966: case 'K':
967: calendar_field = Calendar.HOUR;
968: break;
969: case 'h':
970: calendar_field = Calendar.HOUR;
971: oneBasedHour = true;
972: break;
973: case 'H':
974: calendar_field = Calendar.HOUR_OF_DAY;
975: break;
976: case 'k':
977: calendar_field = Calendar.HOUR_OF_DAY;
978: oneBasedHourOfDay = true;
979: break;
980: case 'm':
981: calendar_field = Calendar.MINUTE;
982: break;
983: case 's':
984: calendar_field = Calendar.SECOND;
985: break;
986: case 'S':
987: calendar_field = Calendar.MILLISECOND;
988: break;
989: case 'a':
990: is_numeric = false;
991: calendar_field = Calendar.AM_PM;
992: set1 = formatData.getAmPmStrings();
993: break;
994: case 'z':
995: case 'Z':
996:
997:
998: is_numeric = false;
999: calendar_field = Calendar.ZONE_OFFSET;
1000: String[][] zoneStrings = formatData.getZoneStrings();
1001: int zoneCount = zoneStrings.length;
1002: int index = pos.getIndex();
1003: boolean found_zone = false;
1004: simpleOffset = computeOffset(dateStr.substring(index), pos);
1005: if (simpleOffset != null)
1006: {
1007: found_zone = true;
1008: saw_timezone = true;
1009: calendar.set(Calendar.DST_OFFSET, 0);
1010: offset = simpleOffset.intValue();
1011: }
1012: else
1013: {
1014: for (int j = 0; j < zoneCount; j++)
1015: {
1016: String[] strings = zoneStrings[j];
1017: int k;
1018: for (k = 0; k < strings.length; ++k)
1019: {
1020: if (dateStr.startsWith(strings[k], index))
1021: break;
1022: }
1023: if (k != strings.length)
1024: {
1025: found_zone = true;
1026: saw_timezone = true;
1027: TimeZone tz = TimeZone.getTimeZone (strings[0]);
1028:
1029: if(k == 3 || k == 4)
1030: calendar.set (Calendar.DST_OFFSET, tz.getDSTSavings());
1031: else
1032: calendar.set (Calendar.DST_OFFSET, 0);
1033: offset = tz.getRawOffset ();
1034: pos.setIndex(index + strings[k].length());
1035: break;
1036: }
1037: }
1038: }
1039: if (! found_zone)
1040: {
1041: pos.setErrorIndex(pos.getIndex());
1042: return null;
1043: }
1044: break;
1045: default:
1046: pos.setErrorIndex(pos.getIndex());
1047: return null;
1048: }
1049:
1050:
1051: int value;
1052: int index = -1;
1053: if (is_numeric)
1054: {
1055: numberFormat.setMinimumIntegerDigits(fmt_count);
1056: if (limit_digits)
1057: numberFormat.setMaximumIntegerDigits(fmt_count);
1058: if (maybe2DigitYear)
1059: index = pos.getIndex();
1060: Number n = numberFormat.parse(dateStr, pos);
1061: if (pos == null || ! (n instanceof Long))
1062: return null;
1063: value = n.intValue() + offset;
1064: }
1065: else if (set1 != null)
1066: {
1067: index = pos.getIndex();
1068: int i;
1069: boolean found = false;
1070: for (i = offset; i < set1.length; ++i)
1071: {
1072: if (set1[i] != null)
1073: if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(),
1074: index))
1075: {
1076: found = true;
1077: pos.setIndex(index + set1[i].length());
1078: break;
1079: }
1080: }
1081: if (!found && set2 != null)
1082: {
1083: for (i = offset; i < set2.length; ++i)
1084: {
1085: if (set2[i] != null)
1086: if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(),
1087: index))
1088: {
1089: found = true;
1090: pos.setIndex(index + set2[i].length());
1091: break;
1092: }
1093: }
1094: }
1095: if (!found)
1096: {
1097: pos.setErrorIndex(index);
1098: return null;
1099: }
1100: value = i;
1101: }
1102: else
1103: value = offset;
1104:
1105: if (maybe2DigitYear)
1106: {
1107:
1108:
1109: int digit_count = pos.getIndex() - index;
1110: if (digit_count == 2)
1111: {
1112: is2DigitYear = true;
1113: value += defaultCentury;
1114: }
1115: }
1116:
1117:
1118:
1119: if (oneBasedHour && value == 12)
1120: value = 0;
1121:
1122: if (oneBasedHourOfDay && value == 24)
1123: value = 0;
1124:
1125:
1126: calendar.set(calendar_field, value);
1127: }
1128:
1129: if (is2DigitYear)
1130: {
1131:
1132:
1133: int year = calendar.get(Calendar.YEAR);
1134: if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
1135: calendar.set(Calendar.YEAR, year + 100);
1136: }
1137: if (! saw_timezone)
1138: {
1139:
1140:
1141: calendar.clear (Calendar.DST_OFFSET);
1142: calendar.clear (Calendar.ZONE_OFFSET);
1143: }
1144: return calendar.getTime();
1145: }
1146: catch (IllegalArgumentException x)
1147: {
1148: pos.setErrorIndex(pos.getIndex());
1149: return null;
1150: }
1151: }
1152:
1153:
1191: private Integer computeOffset(String zoneString, ParsePosition pos)
1192: {
1193: Pattern pattern =
1194: Pattern.compile("(GMT)?([+-])([012])?([0-9]):?([0-9]{2})");
1195: Matcher matcher = pattern.matcher(zoneString);
1196:
1197:
1198: boolean hasAll = matcher.lookingAt();
1199: try
1200: {
1201:
1202: matcher.group(2);
1203: matcher.group(4);
1204: matcher.group(5);
1205: }
1206: catch (IllegalStateException ise)
1207: {
1208: hasAll = false;
1209: }
1210: if (hasAll)
1211: {
1212: int sign = matcher.group(2).equals("+") ? 1 : -1;
1213: int hour = Integer.parseInt(matcher.group(4));
1214: if (!matcher.group(3).equals(""))
1215: hour += (Integer.parseInt(matcher.group(3)) * 10);
1216: int minutes = Integer.parseInt(matcher.group(5));
1217:
1218: if (hour > 23)
1219: return null;
1220: int offset = sign * ((hour * 60) + minutes) * 60000;
1221:
1222:
1223: pos.setIndex(pos.getIndex() + matcher.end());
1224: return new Integer(offset);
1225: }
1226: else if (zoneString.startsWith("GMT"))
1227: {
1228: pos.setIndex(pos.getIndex() + 3);
1229: return new Integer(0);
1230: }
1231: return null;
1232: }
1233:
1234:
1235:
1236: private void computeCenturyStart()
1237: {
1238: int year = calendar.get(Calendar.YEAR);
1239: calendar.set(Calendar.YEAR, year - 80);
1240: set2DigitYearStart(calendar.getTime());
1241: }
1242:
1243:
1249: public Object clone()
1250: {
1251: SimpleDateFormat clone = (SimpleDateFormat) super.clone();
1252: clone.setDateFormatSymbols((DateFormatSymbols) formatData.clone());
1253: clone.set2DigitYearStart((Date) defaultCenturyStart.clone());
1254: return clone;
1255: }
1256:
1257: }