1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53:
70: public class ZoneInfo extends TimeZone
71: {
72: private static final int SECS_SHIFT = 22;
73: private static final long OFFSET_MASK = (1 << 21) - 1;
74: private static final int OFFSET_SHIFT = 64 - 21;
75: private static final long IS_DST = 1 << 21;
76:
77:
82: private int rawOffset;
83:
84:
87: private int dstSavings;
88:
89:
92: private boolean useDaylight;
93:
94:
104: private long[] transitions;
105:
106:
112: private SimpleTimeZone lastRule;
113:
114:
118: private static SimpleTimeZone gmtZone = null;
119:
120: static final long serialVersionUID = -3740626706860383657L;
121:
122:
136: public ZoneInfo(int rawOffset, String id, long[] transitions,
137: SimpleTimeZone lastRule)
138: {
139: if (transitions == null || transitions.length < 1)
140: throw new IllegalArgumentException("transitions must not be null");
141: if (lastRule == null)
142: throw new IllegalArgumentException("lastRule must not be null");
143: this.rawOffset = rawOffset;
144: this.transitions = transitions;
145: this.lastRule = lastRule;
146: setID(id);
147: computeDSTSavings();
148: }
149:
150:
168: public int getOffset(int era, int year, int month, int day, int dayOfWeek,
169: int millis)
170: {
171: if (gmtZone == null)
172: gmtZone = new SimpleTimeZone(0, "GMT");
173:
174: if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
175: throw new IllegalArgumentException("dayOfWeek out of range");
176: if (month < Calendar.JANUARY || month > Calendar.DECEMBER)
177: throw new IllegalArgumentException("month out of range:" + month);
178:
179: if (era != GregorianCalendar.AD)
180: return (int) (((transitions[0] << OFFSET_SHIFT) >> OFFSET_SHIFT) * 1000);
181:
182: GregorianCalendar cal = new GregorianCalendar((TimeZone) gmtZone);
183: cal.set(year, month, day, 0, 0, 0);
184: if (cal.get(Calendar.DAY_OF_MONTH) != day)
185: throw new IllegalArgumentException("day out of range");
186:
187: return getOffset(cal.getTimeInMillis() - rawOffset + millis);
188: }
189:
190: private long findTransition(long secs)
191: {
192: if (secs < (transitions[0] >> SECS_SHIFT))
193: return transitions[0];
194:
195: if (secs >= (transitions[transitions.length-1] >> SECS_SHIFT))
196: return Long.MAX_VALUE;
197:
198: long val = (secs + 1) << SECS_SHIFT;
199: int lo = 1;
200: int hi = transitions.length;
201: int mid = 1;
202: while (lo < hi)
203: {
204: mid = (lo + hi) / 2;
205:
206: if (val <= transitions[mid-1])
207: hi = mid;
208:
209: else if (val > transitions[mid])
210: lo = mid + 1;
211: else
212: break;
213: }
214: return transitions[mid];
215: }
216:
217:
224: public int getOffset(long date)
225: {
226: long d = (date >= 0 ? date / 1000 : (date + 1) / 1000 - 1);
227: long transition = findTransition(d);
228:
229:
230: if (transition == Long.MAX_VALUE)
231: return lastRule.getOffset(date);
232:
233: return (int) (((transition << OFFSET_SHIFT) >> OFFSET_SHIFT) * 1000);
234: }
235:
236:
241: public int getRawOffset()
242: {
243: return rawOffset;
244: }
245:
246:
250: public void setRawOffset(int rawOffset)
251: {
252: this.rawOffset = rawOffset;
253: lastRule.setRawOffset(rawOffset);
254: }
255:
256: private void computeDSTSavings()
257: {
258: if (lastRule.useDaylightTime())
259: {
260: dstSavings = lastRule.getDSTSavings();
261: useDaylight = true;
262: }
263: else
264: {
265: dstSavings = 0;
266: useDaylight = false;
267:
268:
269:
270:
271: long currentSecs = System.currentTimeMillis() / 1000;
272: int i;
273: for (i = transitions.length - 1;
274: i >= 0 && currentSecs < (transitions[i] >> SECS_SHIFT);
275: i--)
276: if ((transitions[i] & IS_DST) != 0)
277: {
278: dstSavings = (int) (((transitions[i] << OFFSET_SHIFT)
279: >> OFFSET_SHIFT) * 1000)
280: - rawOffset;
281: useDaylight = true;
282: break;
283: }
284: }
285: }
286:
287:
293: public int getDSTSavings()
294: {
295: return dstSavings;
296: }
297:
298:
302: public boolean useDaylightTime()
303: {
304: return useDaylight;
305: }
306:
307:
311: public boolean inDaylightTime(Date date)
312: {
313: long d = date.getTime();
314: d = (d >= 0 ? d / 1000 : (d + 1) / 1000 - 1);
315: long transition = findTransition(d);
316:
317:
318: if (transition == Long.MAX_VALUE)
319: return lastRule.inDaylightTime(date);
320:
321: return (transition & IS_DST) != 0;
322: }
323:
324:
329: public synchronized int hashCode()
330: {
331: int hash = lastRule.hashCode();
332:
333: return hash;
334: }
335:
336: public synchronized boolean equals(Object o)
337: {
338: if (! hasSameRules((TimeZone) o))
339: return false;
340:
341: ZoneInfo zone = (ZoneInfo) o;
342: return getID().equals(zone.getID());
343: }
344:
345:
353: public boolean hasSameRules(TimeZone o)
354: {
355: if (this == o)
356: return true;
357: if (! (o instanceof ZoneInfo))
358: return false;
359: ZoneInfo zone = (ZoneInfo) o;
360: if (zone.hashCode() != hashCode() || rawOffset != zone.rawOffset)
361: return false;
362: if (! lastRule.equals(zone.lastRule))
363: return false;
364:
365: return true;
366: }
367:
368:
372: public String toString()
373: {
374: return getClass().getName() + "[" + "id=" + getID() + ",offset="
375: + rawOffset + ",transitions=" + transitions.length
376: + ",useDaylight=" + useDaylight
377: + (useDaylight ? (",dstSavings=" + dstSavings) : "")
378: + ",lastRule=" + lastRule.toString() + "]";
379: }
380:
381:
387: public static TimeZone readTZFile(String id, String file)
388: {
389: DataInputStream dis = null;
390: try
391: {
392: FileInputStream fis = new FileInputStream(file);
393: BufferedInputStream bis = new BufferedInputStream(fis);
394: dis = new DataInputStream(bis);
395:
396:
397: byte[] tzif = new byte[5];
398: dis.readFully(tzif);
399: int tzif2 = 4;
400: if (tzif[0] == 'T' && tzif[1] == 'Z'
401: && tzif[2] == 'i' && tzif[3] == 'f')
402: {
403: if (tzif[4] >= '2')
404: tzif2 = 8;
405:
406: skipFully(dis, 16 - 1);
407: }
408: else
409:
410: skipFully(dis, 16 - 5);
411:
412: int ttisgmtcnt = dis.readInt();
413: int ttisstdcnt = dis.readInt();
414: int leapcnt = dis.readInt();
415: int timecnt = dis.readInt();
416: int typecnt = dis.readInt();
417: int charcnt = dis.readInt();
418: if (tzif2 == 8)
419: {
420: skipFully(dis, timecnt * (4 + 1) + typecnt * (4 + 1 + 1) + charcnt
421: + leapcnt * (4 + 4) + ttisgmtcnt + ttisstdcnt);
422:
423: dis.readFully(tzif);
424: if (tzif[0] != 'T' || tzif[1] != 'Z' || tzif[2] != 'i'
425: || tzif[3] != 'f' || tzif[4] < '2')
426: return null;
427:
428:
429: skipFully(dis, 16 - 1);
430: ttisgmtcnt = dis.readInt();
431: ttisstdcnt = dis.readInt();
432: leapcnt = dis.readInt();
433: timecnt = dis.readInt();
434: typecnt = dis.readInt();
435: charcnt = dis.readInt();
436: }
437:
438:
439: if (typecnt <= 0 || timecnt < 0 || charcnt < 0
440: || leapcnt < 0 || ttisgmtcnt < 0 || ttisstdcnt < 0
441: || ttisgmtcnt > typecnt || ttisstdcnt > typecnt)
442: return null;
443:
444:
445: long[] times = new long[timecnt];
446: for (int i = 0; i < timecnt; i++)
447: if (tzif2 == 8)
448: times[i] = dis.readLong();
449: else
450: times[i] = (long) dis.readInt();
451:
452:
453: int[] types = new int[timecnt];
454: for (int i = 0; i < timecnt; i++)
455: {
456: types[i] = dis.readByte();
457: if (types[i] < 0)
458: types[i] += 256;
459: if (types[i] >= typecnt)
460: return null;
461: }
462:
463:
464: int[] offsets = new int[typecnt];
465: int[] typeflags = new int[typecnt];
466: for (int i = 0; i < typecnt; i++)
467: {
468: offsets[i] = dis.readInt();
469: if (offsets[i] >= IS_DST / 2 || offsets[i] <= -IS_DST / 2)
470: return null;
471: int dst = dis.readByte();
472: int abbrind = dis.readByte();
473: if (abbrind < 0)
474: abbrind += 256;
475: if (abbrind >= charcnt)
476: return null;
477: typeflags[i] = (dst != 0 ? (1 << 8) : 0) + abbrind;
478: }
479:
480:
481: byte[] names = new byte[charcnt];
482: dis.readFully(names);
483:
484:
485: skipFully(dis, leapcnt * (tzif2 + 4) + ttisstdcnt + ttisgmtcnt);
486:
487:
488: String tzstr = null;
489: if (tzif2 == 8 && dis.readByte() == '\n')
490: {
491: tzstr = dis.readLine();
492: if (tzstr.length() <= 0)
493: tzstr = null;
494: }
495:
496:
497: int std_ind = -1;
498: int dst_ind = -1;
499: if (timecnt == 0)
500: std_ind = 0;
501: else
502: for (int i = timecnt - 1; i >= 0; i--)
503: {
504: if (std_ind == -1 && (typeflags[types[i]] & (1 << 8)) == 0)
505: std_ind = types[i];
506: else if (dst_ind == -1 && (typeflags[types[i]] & (1 << 8)) != 0)
507: dst_ind = types[i];
508: if (dst_ind != -1 && std_ind != -1)
509: break;
510: }
511:
512: if (std_ind == -1)
513: return null;
514:
515: int j = typeflags[std_ind] & 255;
516: while (j < charcnt && names[j] != 0)
517: j++;
518: String std_zonename = new String(names, typeflags[std_ind] & 255,
519: j - (typeflags[std_ind] & 255),
520: "ASCII");
521:
522: String dst_zonename = "";
523: if (dst_ind != -1)
524: {
525: j = typeflags[dst_ind] & 255;
526: while (j < charcnt && names[j] != 0)
527: j++;
528: dst_zonename = new String(names, typeflags[dst_ind] & 255,
529: j - (typeflags[dst_ind] & 255), "ASCII");
530: }
531:
532:
533:
534: String std_offset_string = "";
535: String dst_offset_string = "";
536: if (tzstr == null
537: && (dst_ind != -1
538: || (offsets[std_ind] != 0
539: && !std_zonename.startsWith("GMT+")
540: && !std_zonename.startsWith("GMT-"))))
541: {
542: std_offset_string = Integer.toString(-offsets[std_ind] / 3600);
543: int seconds = -offsets[std_ind] % 3600;
544: if (seconds != 0)
545: {
546: if (seconds < 0)
547: seconds *= -1;
548: if (seconds < 600)
549: std_offset_string += ":0" + Integer.toString(seconds / 60);
550: else
551: std_offset_string += ":" + Integer.toString(seconds / 60);
552: seconds = seconds % 60;
553: if (seconds >= 10)
554: std_offset_string += ":" + Integer.toString(seconds);
555: else if (seconds > 0)
556: std_offset_string += ":0" + Integer.toString(seconds);
557: }
558:
559: if (dst_ind != -1 && offsets[dst_ind] != offsets[std_ind] + 3600)
560: {
561: dst_offset_string = Integer.toString(-offsets[dst_ind] / 3600);
562: seconds = -offsets[dst_ind] % 3600;
563: if (seconds != 0)
564: {
565: if (seconds < 0)
566: seconds *= -1;
567: if (seconds < 600)
568: dst_offset_string
569: += ":0" + Integer.toString(seconds / 60);
570: else
571: dst_offset_string
572: += ":" + Integer.toString(seconds / 60);
573: seconds = seconds % 60;
574: if (seconds >= 10)
575: dst_offset_string += ":" + Integer.toString(seconds);
576: else if (seconds > 0)
577: dst_offset_string += ":0" + Integer.toString(seconds);
578: }
579: }
580: }
581:
582:
591: String[] change_spec = { null, null };
592: if (tzstr == null && dst_ind != -1 && timecnt > 10)
593: {
594: long nowPlus5y = System.currentTimeMillis() / 1000
595: + 5 * 365 * 86400;
596: int first;
597:
598: for (first = timecnt - 1; first >= 0; first--)
599: if (times[first] < nowPlus5y
600: || (types[first] != std_ind && types[first] != dst_ind)
601: || types[first] != types[timecnt - 2 + ((first ^ timecnt) & 1)])
602: break;
603: first++;
604:
605: if (timecnt - first >= 10 && types[timecnt - 1] != types[timecnt - 2])
606: {
607: GregorianCalendar cal
608: = new GregorianCalendar(new SimpleTimeZone(0, "GMT"));
609:
610: int[] values = new int[2 * 11];
611: int i;
612: for (i = timecnt - 1; i >= first; i--)
613: {
614: int base = (i % 2) * 11;
615: int offset = offsets[types[i > first ? i - 1 : i + 1]];
616: cal.setTimeInMillis((times[i] + offset) * 1000);
617: if (i >= timecnt - 2)
618: {
619: values[base + 0] = cal.get(Calendar.YEAR);
620: values[base + 1] = cal.get(Calendar.MONTH);
621: values[base + 2] = cal.get(Calendar.DAY_OF_MONTH);
622: values[base + 3]
623: = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
624: values[base + 4] = cal.get(Calendar.DAY_OF_WEEK);
625: values[base + 5] = cal.get(Calendar.HOUR_OF_DAY);
626: values[base + 6] = cal.get(Calendar.MINUTE);
627: values[base + 7] = cal.get(Calendar.SECOND);
628: values[base + 8] = values[base + 2];
629: values[base + 9] = values[base + 2];
630: values[base + 10] = 0;
631: }
632: else
633: {
634: int year = cal.get(Calendar.YEAR);
635: int month = cal.get(Calendar.MONTH);
636: int day_of_month = cal.get(Calendar.DAY_OF_MONTH);
637: int month_days
638: = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
639: int day_of_week = cal.get(Calendar.DAY_OF_WEEK);
640: int hour = cal.get(Calendar.HOUR_OF_DAY);
641: int minute = cal.get(Calendar.MINUTE);
642: int second = cal.get(Calendar.SECOND);
643: if (year != values[base + 0] - 1
644: || month != values[base + 1]
645: || hour != values[base + 5]
646: || minute != values[base + 6]
647: || second != values[base + 7])
648: break;
649: if (day_of_week == values[base + 4])
650: {
651:
652: if (day_of_month < values[base + 8])
653: values[base + 8] = day_of_month;
654: if (day_of_month > values[base + 9])
655: values[base + 9] = day_of_month;
656: if (values[base + 10] < 0)
657: break;
658: if (values[base + 10] == 0)
659: {
660: values[base + 10] = 1;
661:
662:
663: if (values[base + 2] > 28)
664: values[base + 2] = 3;
665:
666:
667: else if (values[base + 2]
668: <= values[base + 3] - 7)
669: values[base + 3] = 2;
670: }
671: if (values[base + 10] == 1)
672: {
673:
674:
675: if (day_of_month > 28)
676: values[base + 10] = 3;
677:
678:
679: else if (day_of_month <= month_days - 7)
680: values[base + 10] = 2;
681: }
682: else if ((values[base + 10] == 2
683: && day_of_month > 28)
684: || (values[base + 10] == 3
685: && day_of_month <= month_days - 7))
686: break;
687: }
688: else
689: {
690:
691: if (day_of_month != values[base + 2]
692: || values[base + 10] > 0)
693: break;
694: values[base + 4] = day_of_week;
695: values[base + 10] = -1;
696: }
697: values[base + 0] -= 1;
698: }
699: }
700:
701: if (i < first)
702: {
703: for (i = 0; i < 2; i++)
704: {
705: int base = 11 * i;
706: if (values[base + 10] == 0)
707: continue;
708: if (values[base + 10] == -1)
709: {
710: int[] dayCount
711: = { 0, 31, 59, 90, 120, 151,
712: 181, 212, 243, 273, 304, 334 };
713: int d = dayCount[values[base + 1]
714: - Calendar.JANUARY];
715: d += values[base + 2];
716: change_spec[i] = ",J" + Integer.toString(d);
717: }
718: else if (values[base + 10] == 2)
719: {
720:
721:
722: if (values[base + 8] + 6 != values[base + 9])
723: continue;
724:
725: int d;
726: d = values[base + 1] - Calendar.JANUARY + 1;
727:
728:
729:
730:
731:
732:
733: if ((values[base + 8] % 7) == 1)
734: {
735: change_spec[i] = ",M" + Integer.toString(d);
736: d = (values[base + 8] + 6) / 7;
737: }
738: else
739: {
740: change_spec[i] = ",A" + Integer.toString(d);
741: d = values[base + 8];
742: }
743: change_spec[i] += "." + Integer.toString(d);
744: d = values[base + 4] - Calendar.SUNDAY;
745: change_spec[i] += "." + Integer.toString(d);
746: }
747: else
748: {
749:
750:
751:
752:
753:
754:
755:
756: if (values[base + 10] == 1
757: && values[base + 1] != Calendar.FEBRUARY)
758: continue;
759:
760: int d;
761: d = values[base + 1] - Calendar.JANUARY + 1;
762: change_spec[i] = ",M" + Integer.toString(d);
763: d = values[base + 4] - Calendar.SUNDAY;
764: change_spec[i] += ".5." + Integer.toString(d);
765: }
766:
767:
768:
769: if (values[base + 5] != 2
770: || values[base + 6] != 0
771: || values[base + 7] != 0)
772: {
773: int d = values[base + 5];
774: change_spec[i] += "/" + Integer.toString(d);
775: if (values[base + 6] != 0 || values[base + 7] != 0)
776: {
777: d = values[base + 6];
778: if (d < 10)
779: change_spec[i]
780: += ":0" + Integer.toString(d);
781: else
782: change_spec[i] += ":" + Integer.toString(d);
783: d = values[base + 7];
784: if (d >= 10)
785: change_spec[i]
786: += ":" + Integer.toString(d);
787: else if (d > 0)
788: change_spec[i]
789: += ":0" + Integer.toString(d);
790: }
791: }
792: }
793: if (types[(timecnt - 1) & -2] == std_ind)
794: {
795: String tmp = change_spec[0];
796: change_spec[0] = change_spec[1];
797: change_spec[1] = tmp;
798: }
799: }
800: }
801: }
802:
803: if (tzstr == null)
804: {
805: tzstr = std_zonename + std_offset_string;
806: if (change_spec[0] != null && change_spec[1] != null)
807: tzstr += dst_zonename + dst_offset_string
808: + change_spec[0] + change_spec[1];
809: }
810:
811: if (timecnt == 0)
812: return new SimpleTimeZone(offsets[std_ind] * 1000,
813: id != null ? id : tzstr);
814:
815: SimpleTimeZone endRule = createLastRule(tzstr);
816: if (endRule == null)
817: return null;
818:
819:
825: for (int i = 0; i < typecnt; i++)
826: if ((typeflags[i] & (1 << 8)) == 0)
827: {
828: times[0] = (times[0] << SECS_SHIFT) | (offsets[i] & OFFSET_MASK);
829: break;
830: }
831:
832: for (int i = 1; i < timecnt; i++)
833: times[i] = (times[i] << SECS_SHIFT)
834: | (offsets[types[i - 1]] & OFFSET_MASK)
835: | ((typeflags[types[i - 1]] & (1 << 8)) != 0 ? IS_DST : 0);
836:
837: return new ZoneInfo(offsets[std_ind] * 1000, id != null ? id : tzstr,
838: times, endRule);
839: }
840: catch (IOException ioe)
841: {
842:
843: return null;
844: }
845: finally
846: {
847: try
848: {
849: if (dis != null)
850: dis.close();
851: }
852: catch(IOException ioe)
853: {
854:
855: }
856: }
857: }
858:
859:
864: private static void skipFully(InputStream is, long l) throws IOException
865: {
866: while (l > 0)
867: {
868: long k = is.skip(l);
869: if (k <= 0)
870: throw new EOFException();
871: l -= k;
872: }
873: }
874:
875:
883: private static SimpleTimeZone createLastRule(String tzstr)
884: {
885: String stdName = null;
886: int stdOffs;
887: int dstOffs;
888: try
889: {
890: int idLength = tzstr.length();
891:
892: int index = 0;
893: int prevIndex;
894: char c;
895:
896:
897: do
898: c = tzstr.charAt(index);
899: while (c != '+' && c != '-' && c != ',' && c != ':'
900: && ! Character.isDigit(c) && c != '\0' && ++index < idLength);
901:
902: if (index >= idLength)
903: return new SimpleTimeZone(0, tzstr);
904:
905: stdName = tzstr.substring(0, index);
906: prevIndex = index;
907:
908:
909: do
910: c = tzstr.charAt(index++);
911: while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
912: && index < idLength);
913: if (index < idLength)
914: index--;
915:
916: {
917: String offset = tzstr.substring(prevIndex, index);
918: prevIndex = index;
919:
920: if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
921: stdOffs = parseTime(offset.substring(1));
922: else
923: stdOffs = parseTime(offset);
924:
925: if (offset.charAt(0) == '-')
926: stdOffs = -stdOffs;
927:
928:
929: stdOffs = -stdOffs;
930: }
931:
932:
933: if (index >= idLength)
934: return new SimpleTimeZone(stdOffs, stdName);
935:
936:
937: do
938: c = tzstr.charAt(index);
939: while (c != '+' && c != '-' && c != ',' && c != ':'
940: && ! Character.isDigit(c) && c != '\0' && ++index < idLength);
941:
942:
943: if (index >= idLength)
944: return new SimpleTimeZone(stdOffs, stdName);
945:
946:
947: prevIndex = index;
948: do
949: c = tzstr.charAt(index++);
950: while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c))
951: && index < idLength);
952: if (index < idLength)
953: index--;
954:
955: if (index == prevIndex && (c == ',' || c == ';'))
956: {
957:
958:
959: dstOffs = stdOffs + 60 * 60 * 1000;
960: }
961: else
962: {
963: String offset = tzstr.substring(prevIndex, index);
964: prevIndex = index;
965:
966: if (offset.charAt(0) == '+' || offset.charAt(0) == '-')
967: dstOffs = parseTime(offset.substring(1));
968: else
969: dstOffs = parseTime(offset);
970:
971: if (offset.charAt(0) == '-')
972: dstOffs = -dstOffs;
973:
974:
975: dstOffs = -dstOffs;
976: }
977:
978:
979: if (index >= idLength)
980: return new SimpleTimeZone(stdOffs, stdName);
981:
982:
983: if (tzstr.charAt(index) == ','
984: || tzstr.charAt(index) == ';')
985: {
986: index++;
987: int offs = index;
988: while (tzstr.charAt(index) != ','
989: && tzstr.charAt(index) != ';')
990: index++;
991: String startTime = tzstr.substring(offs, index);
992: index++;
993: String endTime = tzstr.substring(index);
994:
995: index = startTime.indexOf('/');
996: int startMillis;
997: int endMillis;
998: String startDate;
999: String endDate;
1000: if (index != -1)
1001: {
1002: startDate = startTime.substring(0, index);
1003: startMillis = parseTime(startTime.substring(index + 1));
1004: }
1005: else
1006: {
1007: startDate = startTime;
1008:
1009: startMillis = 2 * 60 * 60 * 1000;
1010: }
1011: index = endTime.indexOf('/');
1012: if (index != -1)
1013: {
1014: endDate = endTime.substring(0, index);
1015: endMillis = parseTime(endTime.substring(index + 1));
1016: }
1017: else
1018: {
1019: endDate = endTime;
1020:
1021: endMillis = 2 * 60 * 60 * 1000;
1022: }
1023:
1024: int[] start = getDateParams(startDate);
1025: int[] end = getDateParams(endDate);
1026: return new SimpleTimeZone(stdOffs, tzstr, start[0], start[1],
1027: start[2], startMillis, end[0], end[1],
1028: end[2], endMillis, (dstOffs - stdOffs));
1029: }
1030: }
1031:
1032: catch (IndexOutOfBoundsException _)
1033: {
1034: }
1035: catch (NumberFormatException _)
1036: {
1037: }
1038:
1039: return null;
1040: }
1041:
1042:
1047: private static int[] getDateParams(String date)
1048: {
1049: int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1050: int month;
1051: int type = 0;
1052:
1053: if (date.charAt(0) == 'M' || date.charAt(0) == 'm')
1054: type = 1;
1055: else if (date.charAt(0) == 'A' || date.charAt(0) == 'a')
1056: type = 2;
1057:
1058: if (type > 0)
1059: {
1060: int day;
1061:
1062:
1063:
1064:
1065:
1066:
1067:
1068:
1069:
1070:
1071:
1072:
1073: month = Integer.parseInt(date.substring(1, date.indexOf('.')));
1074: int week = Integer.parseInt(date.substring(date.indexOf('.') + 1,
1075: date.lastIndexOf('.')));
1076: int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.')
1077: + 1));
1078: dayOfWeek++;
1079:
1080: if (type == 2)
1081: {
1082: day = week;
1083: dayOfWeek = -dayOfWeek;
1084: }
1085: else if (week == 5)
1086: day = -1;
1087: else
1088: {
1089:
1090:
1091:
1092: day = (week - 1) * 7 + 1;
1093: dayOfWeek = -dayOfWeek;
1094: }
1095:
1096: month--;
1097: return new int[] { month, day, dayOfWeek };
1098: }
1099:
1100:
1101:
1102: int julianDay;
1103:
1104: if (date.charAt(0) != 'J' || date.charAt(0) != 'j')
1105: {
1106: julianDay = Integer.parseInt(date.substring(1));
1107: julianDay++;
1108:
1109: dayCount = new int[]
1110: {
1111: 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
1112: };
1113: }
1114: else
1115:
1116: julianDay = Integer.parseInt(date);
1117:
1118: int i = 11;
1119: while (i > 0)
1120: if (dayCount[i] < julianDay)
1121: break;
1122: else
1123: i--;
1124: julianDay -= dayCount[i];
1125: month = i;
1126: return new int[] { month, julianDay, 0 };
1127: }
1128:
1129:
1133: private static int parseTime(String time)
1134: {
1135: int millis = 0;
1136: int i = 0;
1137:
1138: while (i < time.length())
1139: if (time.charAt(i) == ':')
1140: break;
1141: else
1142: i++;
1143: millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i));
1144: if (i >= time.length())
1145: return millis;
1146:
1147: int iprev = ++i;
1148: while (i < time.length())
1149: if (time.charAt(i) == ':')
1150: break;
1151: else
1152: i++;
1153: millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i));
1154: if (i >= time.length())
1155: return millis;
1156:
1157: millis += 1000 * Integer.parseInt(time.substring(++i));
1158: return millis;
1159: }
1160: }