1 7 8 20 21 package java.util; 22 23 import java.io.ObjectInputStream ; 24 import java.io.ObjectOutputStream ; 25 import java.io.IOException ; 26 import sun.util.calendar.CalendarSystem; 27 import sun.util.calendar.CalendarUtils; 28 import sun.util.calendar.BaseCalendar; 29 import sun.util.calendar.Gregorian; 30 31 132 133 public class SimpleTimeZone extends TimeZone { 134 141 public SimpleTimeZone(int rawOffset, String ID) 142 { 143 this.rawOffset = rawOffset; 144 setID (ID); 145 dstSavings = millisPerHour; } 147 148 197 public SimpleTimeZone(int rawOffset, String ID, 198 int startMonth, int startDay, int startDayOfWeek, int startTime, 199 int endMonth, int endDay, int endDayOfWeek, int endTime) 200 { 201 this(rawOffset, ID, 202 startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, 203 endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, 204 millisPerHour); 205 } 206 207 255 public SimpleTimeZone(int rawOffset, String ID, 256 int startMonth, int startDay, int startDayOfWeek, int startTime, 257 int endMonth, int endDay, int endDayOfWeek, int endTime, 258 int dstSavings) 259 { 260 this(rawOffset, ID, 261 startMonth, startDay, startDayOfWeek, startTime, WALL_TIME, 262 endMonth, endDay, endDayOfWeek, endTime, WALL_TIME, 263 dstSavings); 264 } 265 266 311 public SimpleTimeZone(int rawOffset, String ID, 312 int startMonth, int startDay, int startDayOfWeek, 313 int startTime, int startTimeMode, 314 int endMonth, int endDay, int endDayOfWeek, 315 int endTime, int endTimeMode, 316 int dstSavings) { 317 318 setID(ID); 319 this.rawOffset = rawOffset; 320 this.startMonth = startMonth; 321 this.startDay = startDay; 322 this.startDayOfWeek = startDayOfWeek; 323 this.startTime = startTime; 324 this.startTimeMode = startTimeMode; 325 this.endMonth = endMonth; 326 this.endDay = endDay; 327 this.endDayOfWeek = endDayOfWeek; 328 this.endTime = endTime; 329 this.endTimeMode = endTimeMode; 330 this.dstSavings = dstSavings; 331 332 decodeRules(); 334 if (dstSavings <= 0) { 335 throw new IllegalArgumentException ("Illegal daylight saving value: " + dstSavings); 336 } 337 } 338 339 344 public void setStartYear(int year) 345 { 346 startYear = year; 347 invalidateCache(); 348 } 349 350 368 public void setStartRule(int startMonth, int startDay, int startDayOfWeek, int startTime) 369 { 370 this.startMonth = startMonth; 371 this.startDay = startDay; 372 this.startDayOfWeek = startDayOfWeek; 373 this.startTime = startTime; 374 startTimeMode = WALL_TIME; 375 decodeStartRule(); 376 invalidateCache(); 377 } 378 379 395 public void setStartRule(int startMonth, int startDay, int startTime) { 396 setStartRule(startMonth, startDay, 0, startTime); 397 } 398 399 418 public void setStartRule(int startMonth, int startDay, int startDayOfWeek, 419 int startTime, boolean after) 420 { 421 if (after) { 423 setStartRule(startMonth, startDay, -startDayOfWeek, startTime); 424 } else { 425 setStartRule(startMonth, -startDay, -startDayOfWeek, startTime); 426 } 427 } 428 429 448 public void setEndRule(int endMonth, int endDay, int endDayOfWeek, 449 int endTime) 450 { 451 this.endMonth = endMonth; 452 this.endDay = endDay; 453 this.endDayOfWeek = endDayOfWeek; 454 this.endTime = endTime; 455 this.endTimeMode = WALL_TIME; 456 decodeEndRule(); 457 invalidateCache(); 458 } 459 460 476 public void setEndRule(int endMonth, int endDay, int endTime) 477 { 478 setEndRule(endMonth, endDay, 0, endTime); 479 } 480 481 501 public void setEndRule(int endMonth, int endDay, int endDayOfWeek, int endTime, boolean after) 502 { 503 if (after) { 504 setEndRule(endMonth, endDay, -endDayOfWeek, endTime); 505 } else { 506 setEndRule(endMonth, -endDay, -endDayOfWeek, endTime); 507 } 508 } 509 510 521 public int getOffset(long date) { 522 return getOffsets(date, null); 523 } 524 525 528 int getOffsets(long date, int[] offsets) { 529 int offset = rawOffset; 530 531 computeOffset: 532 if (useDaylight) { 533 synchronized (this) { 534 if (cacheStart != 0) { 535 if (date >= cacheStart && date < cacheEnd) { 536 offset += dstSavings; 537 break computeOffset; 538 } 539 } 540 } 541 BaseCalendar cal = date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ? 542 gcal : (BaseCalendar) CalendarSystem.forName("julian"); 543 BaseCalendar.Date cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE); 544 cal.getCalendarDate(date + rawOffset, cdate); 546 int year = cdate.getNormalizedYear(); 547 if (year >= startYear) { 548 cdate.setTimeOfDay(0, 0, 0, 0); 550 offset = getOffset(cal, cdate, year, date); 551 } 552 } 553 554 if (offsets != null) { 555 offsets[0] = rawOffset; 556 offsets[1] = offset - rawOffset; 557 } 558 return offset; 559 } 560 561 587 public int getOffset(int era, int year, int month, int day, int dayOfWeek, 588 int millis) 589 { 590 if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) { 591 throw new IllegalArgumentException ("Illegal era " + era); 592 } 593 594 int y = year; 595 if (era == GregorianCalendar.BC) { 596 y = 1 - y; 598 } 599 600 if (y >= 292278994) { 606 y = 2800 + y % 2800; 607 } else if (y <= -292269054) { 608 y = (int) CalendarUtils.mod((long) y, 28); 612 } 613 614 int m = month + 1; 616 617 BaseCalendar cal = gcal; 619 BaseCalendar.Date cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE); 620 cdate.setDate(y, m, day); 621 long time = cal.getTime(cdate); time += millis - rawOffset; 624 if (time < GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER) { 631 cal = (BaseCalendar) CalendarSystem.forName("julian"); 632 cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE); 633 cdate.setNormalizedDate(y, m, day); 634 time = cal.getTime(cdate) + millis - rawOffset; 635 } 636 637 if ((cdate.getNormalizedYear() != y) 638 || (cdate.getMonth() != m) 639 || (cdate.getDayOfMonth() != day) 640 || (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) 644 || (millis < 0 || millis >= (24*60*60*1000))) { 645 throw new IllegalArgumentException (); 646 } 647 648 if (!useDaylight || year < startYear || era != GregorianCalendar.CE) { 649 return rawOffset; 650 } 651 652 return getOffset(cal, cdate, y, time); 653 } 654 655 private int getOffset(BaseCalendar cal, BaseCalendar.Date cdate, int year, long time) { 656 synchronized (this) { 657 if (cacheStart != 0) { 658 if (time >= cacheStart && time < cacheEnd) { 659 return rawOffset + dstSavings; 660 } 661 if (year == cacheYear) { 662 return rawOffset; 663 } 664 } 665 } 666 667 long start = getStart(cal, cdate, year); 668 long end = getEnd(cal, cdate, year); 669 int offset = rawOffset; 670 if (start <= end) { 671 if (time >= start && time < end) { 672 offset += dstSavings; 673 } 674 synchronized (this) { 675 cacheYear = year; 676 cacheStart = start; 677 cacheEnd = end; 678 } 679 } else { 680 if (time < end) { 681 start = getStart(cal, cdate, year - 1); 684 if (time >= start) { 685 offset += dstSavings; 686 } 687 } else if (time >= start) { 688 end = getEnd(cal, cdate, year + 1); 691 if (time < end) { 692 offset += dstSavings; 693 } 694 } 695 if (start <= end) { 696 synchronized (this) { 697 cacheYear = (long) startYear - 1; 699 cacheStart = start; 700 cacheEnd = end; 701 } 702 } 703 } 704 return offset; 705 } 706 707 private long getStart(BaseCalendar cal, BaseCalendar.Date cdate, int year) { 708 int time = startTime; 709 if (startTimeMode != UTC_TIME) { 710 time -= rawOffset; 711 } 712 return getTransition(cal, cdate, startMode, year, startMonth, startDay, 713 startDayOfWeek, time); 714 } 715 716 private long getEnd(BaseCalendar cal, BaseCalendar.Date cdate, int year) { 717 int time = endTime; 718 if (startTimeMode != UTC_TIME) { 719 time -= rawOffset; 720 } 721 if (startTimeMode == WALL_TIME) { 722 time -= dstSavings; 723 } 724 return getTransition(cal, cdate, endMode, year, endMonth, endDay, 725 endDayOfWeek, time); 726 } 727 728 private long getTransition(BaseCalendar cal, BaseCalendar.Date cdate, 729 int mode, int year, int month, int dayOfMonth, 730 int dayOfWeek, int timeOfDay) { 731 cdate.setNormalizedYear(year); 732 cdate.setMonth(month + 1); 733 switch (mode) { 734 case DOM_MODE: 735 cdate.setDayOfMonth(dayOfMonth); 736 break; 737 738 case DOW_IN_MONTH_MODE: 739 cdate.setDayOfMonth(1); 740 if (dayOfMonth < 0) { 741 cdate.setDayOfMonth(cal.getMonthLength(cdate)); 742 } 743 cdate = (BaseCalendar.Date) cal.getNthDayOfWeek(dayOfMonth, dayOfWeek, cdate); 744 break; 745 746 case DOW_GE_DOM_MODE: 747 cdate.setDayOfMonth(dayOfMonth); 748 cdate = (BaseCalendar.Date) cal.getNthDayOfWeek(1, dayOfWeek, cdate); 749 break; 750 751 case DOW_LE_DOM_MODE: 752 cdate.setDayOfMonth(dayOfMonth); 753 cdate = (BaseCalendar.Date) cal.getNthDayOfWeek(-1, dayOfWeek, cdate); 754 break; 755 } 756 return cal.getTime(cdate) + timeOfDay; 757 } 758 759 764 public int getRawOffset() 765 { 766 return rawOffset; 769 } 770 771 776 public void setRawOffset(int offsetMillis) 777 { 778 this.rawOffset = offsetMillis; 779 } 780 781 790 public void setDSTSavings(int millisSavedDuringDST) { 791 if (millisSavedDuringDST <= 0) { 792 throw new IllegalArgumentException ("Illegal daylight saving value: " 793 + millisSavedDuringDST); 794 } 795 dstSavings = millisSavedDuringDST; 796 } 797 798 810 public int getDSTSavings() { 811 if (useDaylight) { 812 return dstSavings; 813 } 814 return 0; 815 } 816 817 822 public boolean useDaylightTime() 823 { 824 return useDaylight; 825 } 826 827 832 public boolean inDaylightTime(Date date) 833 { 834 return (getOffset(date.getTime()) != rawOffset); 835 } 836 837 841 public Object clone() 842 { 843 return super.clone(); 844 } 845 846 850 public synchronized int hashCode() 851 { 852 return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^ 853 endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset; 854 } 855 856 863 public boolean equals(Object obj) 864 { 865 if (this == obj) { 866 return true; 867 } 868 if (!(obj instanceof SimpleTimeZone )) { 869 return false; 870 } 871 872 SimpleTimeZone that = (SimpleTimeZone ) obj; 873 874 return getID().equals(that.getID()) && 875 hasSameRules(that); 876 } 877 878 885 public boolean hasSameRules(TimeZone other) { 886 if (this == other) { 887 return true; 888 } 889 if (!(other instanceof SimpleTimeZone )) { 890 return false; 891 } 892 SimpleTimeZone that = (SimpleTimeZone ) other; 893 return rawOffset == that.rawOffset && 894 useDaylight == that.useDaylight && 895 (!useDaylight 896 || (dstSavings == that.dstSavings && 898 startMode == that.startMode && 899 startMonth == that.startMonth && 900 startDay == that.startDay && 901 startDayOfWeek == that.startDayOfWeek && 902 startTime == that.startTime && 903 startTimeMode == that.startTimeMode && 904 endMode == that.endMode && 905 endMonth == that.endMonth && 906 endDay == that.endDay && 907 endDayOfWeek == that.endDayOfWeek && 908 endTime == that.endTime && 909 endTimeMode == that.endTimeMode && 910 startYear == that.startYear)); 911 } 912 913 917 public String toString() { 918 return getClass().getName() + 919 "[id=" + getID() + 920 ",offset=" + rawOffset + 921 ",dstSavings=" + dstSavings + 922 ",useDaylight=" + useDaylight + 923 ",startYear=" + startYear + 924 ",startMode=" + startMode + 925 ",startMonth=" + startMonth + 926 ",startDay=" + startDay + 927 ",startDayOfWeek=" + startDayOfWeek + 928 ",startTime=" + startTime + 929 ",startTimeMode=" + startTimeMode + 930 ",endMode=" + endMode + 931 ",endMonth=" + endMonth + 932 ",endDay=" + endDay + 933 ",endDayOfWeek=" + endDayOfWeek + 934 ",endTime=" + endTime + 935 ",endTimeMode=" + endTimeMode + ']'; 936 } 937 938 940 948 private int startMonth; 949 950 973 private int startDay; 974 975 983 private int startDayOfWeek; 984 985 992 private int startTime; 993 994 999 private int startTimeMode; 1000 1001 1009 private int endMonth; 1010 1011 1034 private int endDay; 1035 1036 1044 private int endDayOfWeek; 1045 1046 1053 private int endTime; 1054 1055 1061 private int endTimeMode; 1062 1063 1070 private int startYear; 1071 1072 1079 private int rawOffset; 1080 1081 1086 private boolean useDaylight=false; 1088 private static final int millisPerHour = 60*60*1000; 1089 private static final int millisPerDay = 24*millisPerHour; 1090 1091 1099 private final byte monthLength[] = staticMonthLength; 1100 private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 1101 private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 1102 1103 1130 private int startMode; 1131 1132 1159 private int endMode; 1160 1161 1169 private int dstSavings; 1170 1171 private static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); 1172 1173 1185 private transient long cacheYear; 1186 private transient long cacheStart; 1187 private transient long cacheEnd; 1188 1189 1192 private static final int DOM_MODE = 1; private static final int DOW_IN_MONTH_MODE = 2; private static final int DOW_GE_DOM_MODE = 3; private static final int DOW_LE_DOM_MODE = 4; 1197 1203 public static final int WALL_TIME = 0; 1205 1209 public static final int STANDARD_TIME = 1; 1210 1211 1216 public static final int UTC_TIME = 2; 1217 1218 static final long serialVersionUID = -403250971215465050L; 1220 1221 static final int currentSerialVersion = 2; 1226 1227 1251 private int serialVersionOnStream = currentSerialVersion; 1252 1253 synchronized private void invalidateCache() { 1254 cacheYear = startYear - 1; 1255 cacheStart = cacheEnd = 0; 1256 } 1257 1258 1311 1321 private void decodeRules() 1322 { 1323 decodeStartRule(); 1324 decodeEndRule(); 1325 } 1326 1327 1351 private void decodeStartRule() { 1352 useDaylight = (startDay != 0) && (endDay != 0); 1353 if (startDay != 0) { 1354 if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) { 1355 throw new IllegalArgumentException ( 1356 "Illegal start month " + startMonth); 1357 } 1358 if (startTime < 0 || startTime >= millisPerDay) { 1359 throw new IllegalArgumentException ( 1360 "Illegal start time " + startTime); 1361 } 1362 if (startDayOfWeek == 0) { 1363 startMode = DOM_MODE; 1364 } else { 1365 if (startDayOfWeek > 0) { 1366 startMode = DOW_IN_MONTH_MODE; 1367 } else { 1368 startDayOfWeek = -startDayOfWeek; 1369 if (startDay > 0) { 1370 startMode = DOW_GE_DOM_MODE; 1371 } else { 1372 startDay = -startDay; 1373 startMode = DOW_LE_DOM_MODE; 1374 } 1375 } 1376 if (startDayOfWeek > Calendar.SATURDAY) { 1377 throw new IllegalArgumentException ( 1378 "Illegal start day of week " + startDayOfWeek); 1379 } 1380 } 1381 if (startMode == DOW_IN_MONTH_MODE) { 1382 if (startDay < -5 || startDay > 5) { 1383 throw new IllegalArgumentException ( 1384 "Illegal start day of week in month " + startDay); 1385 } 1386 } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) { 1387 throw new IllegalArgumentException ( 1388 "Illegal start day " + startDay); 1389 } 1390 } 1391 } 1392 1393 1398 private void decodeEndRule() { 1399 useDaylight = (startDay != 0) && (endDay != 0); 1400 if (endDay != 0) { 1401 if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) { 1402 throw new IllegalArgumentException ( 1403 "Illegal end month " + endMonth); 1404 } 1405 if (endTime < 0 || endTime >= millisPerDay) { 1406 throw new IllegalArgumentException ( 1407 "Illegal end time " + endTime); 1408 } 1409 if (endDayOfWeek == 0) { 1410 endMode = DOM_MODE; 1411 } else { 1412 if (endDayOfWeek > 0) { 1413 endMode = DOW_IN_MONTH_MODE; 1414 } else { 1415 endDayOfWeek = -endDayOfWeek; 1416 if (endDay > 0) { 1417 endMode = DOW_GE_DOM_MODE; 1418 } else { 1419 endDay = -endDay; 1420 endMode = DOW_LE_DOM_MODE; 1421 } 1422 } 1423 if (endDayOfWeek > Calendar.SATURDAY) { 1424 throw new IllegalArgumentException ( 1425 "Illegal end day of week " + endDayOfWeek); 1426 } 1427 } 1428 if (endMode == DOW_IN_MONTH_MODE) { 1429 if (endDay < -5 || endDay > 5) { 1430 throw new IllegalArgumentException ( 1431 "Illegal end day of week in month " + endDay); 1432 } 1433 } else if (endDay < 1 || endDay > staticMonthLength[endMonth]) { 1434 throw new IllegalArgumentException ( 1435 "Illegal end day " + endDay); 1436 } 1437 } 1438 } 1439 1440 1449 private void makeRulesCompatible() 1450 { 1451 switch (startMode) { 1452 case DOM_MODE: 1453 startDay = 1 + (startDay / 7); 1454 startDayOfWeek = Calendar.SUNDAY; 1455 break; 1456 1457 case DOW_GE_DOM_MODE: 1458 if (startDay != 1) { 1461 startDay = 1 + (startDay / 7); 1462 } 1463 break; 1464 1465 case DOW_LE_DOM_MODE: 1466 if (startDay >= 30) { 1467 startDay = -1; 1468 } else { 1469 startDay = 1 + (startDay / 7); 1470 } 1471 break; 1472 } 1473 1474 switch (endMode) { 1475 case DOM_MODE: 1476 endDay = 1 + (endDay / 7); 1477 endDayOfWeek = Calendar.SUNDAY; 1478 break; 1479 1480 case DOW_GE_DOM_MODE: 1481 if (endDay != 1) { 1484 endDay = 1 + (endDay / 7); 1485 } 1486 break; 1487 1488 case DOW_LE_DOM_MODE: 1489 if (endDay >= 30) { 1490 endDay = -1; 1491 } else { 1492 endDay = 1 + (endDay / 7); 1493 } 1494 break; 1495 } 1496 1497 1507 switch (startTimeMode) { 1508 case UTC_TIME: 1509 startTime += rawOffset; 1510 break; 1511 } 1512 while (startTime < 0) { 1513 startTime += millisPerDay; 1514 startDayOfWeek = 1 + ((startDayOfWeek+5) % 7); } 1516 while (startTime >= millisPerDay) { 1517 startTime -= millisPerDay; 1518 startDayOfWeek = 1 + (startDayOfWeek % 7); } 1520 1521 switch (endTimeMode) { 1522 case UTC_TIME: 1523 endTime += rawOffset + dstSavings; 1524 break; 1525 case STANDARD_TIME: 1526 endTime += dstSavings; 1527 } 1528 while (endTime < 0) { 1529 endTime += millisPerDay; 1530 endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); } 1532 while (endTime >= millisPerDay) { 1533 endTime -= millisPerDay; 1534 endDayOfWeek = 1 + (endDayOfWeek % 7); } 1536 } 1537 1538 1542 private byte[] packRules() 1543 { 1544 byte[] rules = new byte[6]; 1545 rules[0] = (byte)startDay; 1546 rules[1] = (byte)startDayOfWeek; 1547 rules[2] = (byte)endDay; 1548 rules[3] = (byte)endDayOfWeek; 1549 1550 rules[4] = (byte)startTimeMode; 1552 rules[5] = (byte)endTimeMode; 1553 1554 return rules; 1555 } 1556 1557 1561 private void unpackRules(byte[] rules) 1562 { 1563 startDay = rules[0]; 1564 startDayOfWeek = rules[1]; 1565 endDay = rules[2]; 1566 endDayOfWeek = rules[3]; 1567 1568 if (rules.length >= 6) { 1570 startTimeMode = rules[4]; 1571 endTimeMode = rules[5]; 1572 } 1573 } 1574 1575 1579 private int[] packTimes() { 1580 int[] times = new int[2]; 1581 times[0] = startTime; 1582 times[1] = endTime; 1583 return times; 1584 } 1585 1586 1590 private void unpackTimes(int[] times) { 1591 startTime = times[0]; 1592 endTime = times[1]; 1593 } 1594 1595 1611 private void writeObject(ObjectOutputStream stream) 1612 throws IOException 1613 { 1614 byte[] rules = packRules(); 1616 int[] times = packTimes(); 1617 1618 makeRulesCompatible(); 1620 1621 stream.defaultWriteObject(); 1623 1624 stream.writeInt(rules.length); 1626 stream.write(rules); 1627 stream.writeObject(times); 1628 1629 unpackRules(rules); 1632 unpackTimes(times); 1633 } 1634 1635 1641 private void readObject(ObjectInputStream stream) 1642 throws IOException , ClassNotFoundException 1643 { 1644 stream.defaultReadObject(); 1645 1646 if (serialVersionOnStream < 1) { 1647 if (startDayOfWeek == 0) { 1651 startDayOfWeek = Calendar.SUNDAY; 1652 } 1653 if (endDayOfWeek == 0) { 1654 endDayOfWeek = Calendar.SUNDAY; 1655 } 1656 1657 startMode = endMode = DOW_IN_MONTH_MODE; 1660 dstSavings = millisPerHour; 1661 } else { 1662 int length = stream.readInt(); 1666 byte[] rules = new byte[length]; 1667 stream.readFully(rules); 1668 unpackRules(rules); 1669 } 1670 1671 if (serialVersionOnStream >= 2) { 1672 int[] times = (int[]) stream.readObject(); 1673 unpackTimes(times); 1674 } 1675 1676 serialVersionOnStream = currentSerialVersion; 1677 } 1678} 1679 | Popular Tags |