< prev index next >

src/java.base/share/classes/java/util/SimpleTimeZone.java

Print this page




 531      * the offset value is adjusted with the amount of daylight
 532      * saving.
 533      *
 534      * @param date the time at which the time zone offset is found
 535      * @return the amount of time in milliseconds to add to UTC to get
 536      * local time.
 537      * @since 1.4
 538      */
 539     public int getOffset(long date) {
 540         return getOffsets(date, null);
 541     }
 542 
 543     /**
 544      * @see TimeZone#getOffsets
 545      */
 546     int getOffsets(long date, int[] offsets) {
 547         int offset = rawOffset;
 548 
 549       computeOffset:
 550         if (useDaylight) {
 551             synchronized (this) {
 552                 if (cacheStart != 0) {
 553                     if (date >= cacheStart && date < cacheEnd) {
 554                         offset += dstSavings;
 555                         break computeOffset;
 556                     }
 557                 }
 558             }
 559             BaseCalendar cal = date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ?
 560                 gcal : (BaseCalendar) CalendarSystem.forName("julian");
 561             BaseCalendar.Date cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
 562             // Get the year in local time
 563             cal.getCalendarDate(date + rawOffset, cdate);
 564             int year = cdate.getNormalizedYear();
 565             if (year >= startYear) {
 566                 // Clear time elements for the transition calculations
 567                 cdate.setTimeOfDay(0, 0, 0, 0);
 568                 offset = getOffset(cal, cdate, year, date);
 569             }
 570         }
 571 
 572         if (offsets != null) {
 573             offsets[0] = rawOffset;
 574             offsets[1] = offset - rawOffset;
 575         }
 576         return offset;
 577     }
 578 


 654 
 655         if ((cdate.getNormalizedYear() != y)
 656             || (cdate.getMonth() != m)
 657             || (cdate.getDayOfMonth() != day)
 658             // The validation should be cdate.getDayOfWeek() ==
 659             // dayOfWeek. However, we don't check dayOfWeek for
 660             // compatibility.
 661             || (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
 662             || (millis < 0 || millis >= (24*60*60*1000))) {
 663             throw new IllegalArgumentException();
 664         }
 665 
 666         if (!useDaylight || year < startYear || era != GregorianCalendar.CE) {
 667             return rawOffset;
 668         }
 669 
 670         return getOffset(cal, cdate, y, time);
 671     }
 672 
 673     private int getOffset(BaseCalendar cal, BaseCalendar.Date cdate, int year, long time) {
 674         synchronized (this) {
 675             if (cacheStart != 0) {
 676                 if (time >= cacheStart && time < cacheEnd) {
 677                     return rawOffset + dstSavings;
 678                 }
 679                 if (year == cacheYear) {
 680                     return rawOffset;
 681                 }
 682             }
 683         }
 684 
 685         long start = getStart(cal, cdate, year);
 686         long end = getEnd(cal, cdate, year);
 687         int offset = rawOffset;
 688         if (start <= end) {
 689             if (time >= start && time < end) {
 690                 offset += dstSavings;
 691             }
 692             synchronized (this) {
 693                 cacheYear = year;
 694                 cacheStart = start;
 695                 cacheEnd = end;
 696             }
 697         } else {
 698             if (time < end) {
 699                 // TODO: support Gregorian cutover. The previous year
 700                 // may be in the other calendar system.
 701                 start = getStart(cal, cdate, year - 1);
 702                 if (time >= start) {
 703                     offset += dstSavings;
 704                 }
 705             } else if (time >= start) {
 706                 // TODO: support Gregorian cutover. The next year
 707                 // may be in the other calendar system.
 708                 end = getEnd(cal, cdate, year + 1);
 709                 if (time < end) {
 710                     offset += dstSavings;
 711                 }
 712             }
 713             if (start <= end) {
 714                 synchronized (this) {
 715                     // The start and end transitions are in multiple years.
 716                     cacheYear = (long) startYear - 1;
 717                     cacheStart = start;
 718                     cacheEnd = end;
 719                 }
 720             }
 721         }
 722         return offset;
 723     }
 724 
 725     private long getStart(BaseCalendar cal, BaseCalendar.Date cdate, int year) {
 726         int time = startTime;
 727         if (startTimeMode != UTC_TIME) {
 728             time -= rawOffset;
 729         }
 730         return getTransition(cal, cdate, startMode, year, startMonth, startDay,
 731                              startDayOfWeek, time);
 732     }
 733 
 734     private long getEnd(BaseCalendar cal, BaseCalendar.Date cdate, int year) {
 735         int time = endTime;
 736         if (endTimeMode != UTC_TIME) {
 737             time -= rawOffset;
 738         }
 739         if (endTimeMode == WALL_TIME) {


 859      * given date; false otherwise.
 860      */
 861     public boolean inDaylightTime(Date date)
 862     {
 863         return (getOffset(date.getTime()) != rawOffset);
 864     }
 865 
 866     /**
 867      * Returns a clone of this <code>SimpleTimeZone</code> instance.
 868      * @return a clone of this instance.
 869      */
 870     public Object clone()
 871     {
 872         return super.clone();
 873     }
 874 
 875     /**
 876      * Generates the hash code for the SimpleDateFormat object.
 877      * @return the hash code for this object
 878      */
 879     public synchronized int hashCode()
 880     {
 881         return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
 882             endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
 883     }
 884 
 885     /**
 886      * Compares the equality of two <code>SimpleTimeZone</code> objects.
 887      *
 888      * @param obj  The <code>SimpleTimeZone</code> object to be compared with.
 889      * @return     True if the given <code>obj</code> is the same as this
 890      *             <code>SimpleTimeZone</code> object; false otherwise.
 891      */
 892     public boolean equals(Object obj)
 893     {
 894         if (this == obj) {
 895             return true;
 896         }
 897         if (!(obj instanceof SimpleTimeZone)) {
 898             return false;
 899         }


1184      * <p>If <code>useDaylight</code> is false, this value is ignored.
1185      * @serial
1186      * @since 1.1.4
1187      */
1188     private int endMode;
1189 
1190     /**
1191      * A positive value indicating the amount of time saved during DST in
1192      * milliseconds.
1193      * Typically one hour (3600000); sometimes 30 minutes (1800000).
1194      * <p>If <code>useDaylight</code> is false, this value is ignored.
1195      * @serial
1196      * @since 1.1.4
1197      */
1198     private int dstSavings;
1199 
1200     private static final Gregorian gcal = CalendarSystem.getGregorianCalendar();
1201 
1202     /**
1203      * Cache values representing a single period of daylight saving
1204      * time. When the cache values are valid, cacheStart is the start
1205      * time (inclusive) of daylight saving time and cacheEnd is the
1206      * end time (exclusive).
1207      *
1208      * cacheYear has a year value if both cacheStart and cacheEnd are
1209      * in the same year. cacheYear is set to startYear - 1 if
1210      * cacheStart and cacheEnd are in different years. cacheStart is 0
1211      * if the cache values are void. cacheYear is a long to support
1212      * Integer.MIN_VALUE - 1 (JCK requirement).
1213      */
1214     private transient long cacheYear;
1215     private transient long cacheStart;
1216     private transient long cacheEnd;









1217 
1218     /**
1219      * Constants specifying values of startMode and endMode.
1220      */
1221     private static final int DOM_MODE          = 1; // Exact day of month, "Mar 1"
1222     private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun"
1223     private static final int DOW_GE_DOM_MODE   = 3; // Day of week after day of month, "Sun>=15"
1224     private static final int DOW_LE_DOM_MODE   = 4; // Day of week before day of month, "Sun<=21"
1225 
1226     /**
1227      * Constant for a mode of start or end time specified as wall clock
1228      * time.  Wall clock time is standard time for the onset rule, and
1229      * daylight time for the end rule.
1230      * @since 1.4
1231      */
1232     public static final int WALL_TIME = 0; // Zero for backward compatibility
1233 
1234     /**
1235      * Constant for a mode of start or end time specified as standard time.
1236      * @since 1.4


1265      * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
1266      * <code>endMode</code>, and <code>dstSavings</code>.
1267      * </dd>
1268      * <dt><b>2</b></dt>
1269      * <dd>
1270      * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
1271      * and <code>endTimeMode</code>.
1272      * </dd>
1273      * </dl>
1274      * When streaming out this class, the most recent format
1275      * and the highest allowable <code>serialVersionOnStream</code>
1276      * is written.
1277      * @serial
1278      * @since 1.1.4
1279      */
1280     private int serialVersionOnStream = currentSerialVersion;
1281 
1282     // Maximum number of rules.
1283     private static final int MAX_RULE_NUM = 6;
1284 
1285     private synchronized void invalidateCache() {
1286         cacheYear = startYear - 1;
1287         cacheStart = cacheEnd = 0;
1288     }
1289 
1290     //----------------------------------------------------------------------
1291     // Rule representation
1292     //
1293     // We represent the following flavors of rules:
1294     //       5        the fifth of the month
1295     //       lastSun  the last Sunday in the month
1296     //       lastMon  the last Monday in the month
1297     //       Sun>=8   first Sunday on or after the eighth
1298     //       Sun<=25  last Sunday on or before the 25th
1299     // This is further complicated by the fact that we need to remain
1300     // backward compatible with the 1.1 FCS.  Finally, we need to minimize
1301     // API changes.  In order to satisfy these requirements, we support
1302     // three representation systems, and we translate between them.
1303     //
1304     // INTERNAL REPRESENTATION
1305     // This is the format SimpleTimeZone objects take after construction or
1306     // streaming in is complete.  Rules are represented directly, using an
1307     // unencoded format.  We will discuss the start rule only below; the end




 531      * the offset value is adjusted with the amount of daylight
 532      * saving.
 533      *
 534      * @param date the time at which the time zone offset is found
 535      * @return the amount of time in milliseconds to add to UTC to get
 536      * local time.
 537      * @since 1.4
 538      */
 539     public int getOffset(long date) {
 540         return getOffsets(date, null);
 541     }
 542 
 543     /**
 544      * @see TimeZone#getOffsets
 545      */
 546     int getOffsets(long date, int[] offsets) {
 547         int offset = rawOffset;
 548 
 549       computeOffset:
 550         if (useDaylight) {
 551             Cache cache = this.cache;
 552             if (cache != null) {
 553                 if (date >= cache.start && date < cache.end) {
 554                     offset += dstSavings;
 555                     break computeOffset;
 556                 }
 557             }

 558             BaseCalendar cal = date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ?
 559                 gcal : (BaseCalendar) CalendarSystem.forName("julian");
 560             BaseCalendar.Date cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
 561             // Get the year in local time
 562             cal.getCalendarDate(date + rawOffset, cdate);
 563             int year = cdate.getNormalizedYear();
 564             if (year >= startYear) {
 565                 // Clear time elements for the transition calculations
 566                 cdate.setTimeOfDay(0, 0, 0, 0);
 567                 offset = getOffset(cal, cdate, year, date);
 568             }
 569         }
 570 
 571         if (offsets != null) {
 572             offsets[0] = rawOffset;
 573             offsets[1] = offset - rawOffset;
 574         }
 575         return offset;
 576     }
 577 


 653 
 654         if ((cdate.getNormalizedYear() != y)
 655             || (cdate.getMonth() != m)
 656             || (cdate.getDayOfMonth() != day)
 657             // The validation should be cdate.getDayOfWeek() ==
 658             // dayOfWeek. However, we don't check dayOfWeek for
 659             // compatibility.
 660             || (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
 661             || (millis < 0 || millis >= (24*60*60*1000))) {
 662             throw new IllegalArgumentException();
 663         }
 664 
 665         if (!useDaylight || year < startYear || era != GregorianCalendar.CE) {
 666             return rawOffset;
 667         }
 668 
 669         return getOffset(cal, cdate, y, time);
 670     }
 671 
 672     private int getOffset(BaseCalendar cal, BaseCalendar.Date cdate, int year, long time) {
 673         Cache cache = this.cache;
 674         if (cache != null) {
 675             if (time >= cache.start && time < cache.end) {
 676                 return rawOffset + dstSavings;
 677             }
 678             if (year == cache.year) {
 679                 return rawOffset;
 680             }
 681         }

 682 
 683         long start = getStart(cal, cdate, year);
 684         long end = getEnd(cal, cdate, year);
 685         int offset = rawOffset;
 686         if (start <= end) {
 687             if (time >= start && time < end) {
 688                 offset += dstSavings;
 689             }
 690             this.cache = new Cache(year, start, end);




 691         } else {
 692             if (time < end) {
 693                 // TODO: support Gregorian cutover. The previous year
 694                 // may be in the other calendar system.
 695                 start = getStart(cal, cdate, year - 1);
 696                 if (time >= start) {
 697                     offset += dstSavings;
 698                 }
 699             } else if (time >= start) {
 700                 // TODO: support Gregorian cutover. The next year
 701                 // may be in the other calendar system.
 702                 end = getEnd(cal, cdate, year + 1);
 703                 if (time < end) {
 704                     offset += dstSavings;
 705                 }
 706             }
 707             if (start <= end) {
 708                 this.cache = new Cache((long) startYear - 1, start, end);





 709             }
 710         }
 711         return offset;
 712     }
 713 
 714     private long getStart(BaseCalendar cal, BaseCalendar.Date cdate, int year) {
 715         int time = startTime;
 716         if (startTimeMode != UTC_TIME) {
 717             time -= rawOffset;
 718         }
 719         return getTransition(cal, cdate, startMode, year, startMonth, startDay,
 720                              startDayOfWeek, time);
 721     }
 722 
 723     private long getEnd(BaseCalendar cal, BaseCalendar.Date cdate, int year) {
 724         int time = endTime;
 725         if (endTimeMode != UTC_TIME) {
 726             time -= rawOffset;
 727         }
 728         if (endTimeMode == WALL_TIME) {


 848      * given date; false otherwise.
 849      */
 850     public boolean inDaylightTime(Date date)
 851     {
 852         return (getOffset(date.getTime()) != rawOffset);
 853     }
 854 
 855     /**
 856      * Returns a clone of this <code>SimpleTimeZone</code> instance.
 857      * @return a clone of this instance.
 858      */
 859     public Object clone()
 860     {
 861         return super.clone();
 862     }
 863 
 864     /**
 865      * Generates the hash code for the SimpleDateFormat object.
 866      * @return the hash code for this object
 867      */
 868     public int hashCode()
 869     {
 870         return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
 871             endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
 872     }
 873 
 874     /**
 875      * Compares the equality of two <code>SimpleTimeZone</code> objects.
 876      *
 877      * @param obj  The <code>SimpleTimeZone</code> object to be compared with.
 878      * @return     True if the given <code>obj</code> is the same as this
 879      *             <code>SimpleTimeZone</code> object; false otherwise.
 880      */
 881     public boolean equals(Object obj)
 882     {
 883         if (this == obj) {
 884             return true;
 885         }
 886         if (!(obj instanceof SimpleTimeZone)) {
 887             return false;
 888         }


1173      * <p>If <code>useDaylight</code> is false, this value is ignored.
1174      * @serial
1175      * @since 1.1.4
1176      */
1177     private int endMode;
1178 
1179     /**
1180      * A positive value indicating the amount of time saved during DST in
1181      * milliseconds.
1182      * Typically one hour (3600000); sometimes 30 minutes (1800000).
1183      * <p>If <code>useDaylight</code> is false, this value is ignored.
1184      * @serial
1185      * @since 1.1.4
1186      */
1187     private int dstSavings;
1188 
1189     private static final Gregorian gcal = CalendarSystem.getGregorianCalendar();
1190 
1191     /**
1192      * Cache values representing a single period of daylight saving
1193      * time. Cache.start is the start time (inclusive) of daylight
1194      * saving time and Cache.end is the end time (exclusive).

1195      *
1196      * Cache.year has a year value if both Cache.start and Cache.end are
1197      * in the same year. Cache.year is set to startYear - 1 if
1198      * Cache.start and Cache.end are in different years.
1199      * Cache.year is a long to support Integer.MIN_VALUE - 1 (JCK requirement).
1200      */
1201     private static final class Cache {
1202         final long year;
1203         final long start;
1204         final long end;
1205 
1206         Cache(long year, long start, long end) {
1207             this.year = year;
1208             this.start = start;
1209             this.end = end;
1210         }
1211     }
1212 
1213     private transient volatile Cache cache;
1214 
1215     /**
1216      * Constants specifying values of startMode and endMode.
1217      */
1218     private static final int DOM_MODE          = 1; // Exact day of month, "Mar 1"
1219     private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun"
1220     private static final int DOW_GE_DOM_MODE   = 3; // Day of week after day of month, "Sun>=15"
1221     private static final int DOW_LE_DOM_MODE   = 4; // Day of week before day of month, "Sun<=21"
1222 
1223     /**
1224      * Constant for a mode of start or end time specified as wall clock
1225      * time.  Wall clock time is standard time for the onset rule, and
1226      * daylight time for the end rule.
1227      * @since 1.4
1228      */
1229     public static final int WALL_TIME = 0; // Zero for backward compatibility
1230 
1231     /**
1232      * Constant for a mode of start or end time specified as standard time.
1233      * @since 1.4


1262      * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
1263      * <code>endMode</code>, and <code>dstSavings</code>.
1264      * </dd>
1265      * <dt><b>2</b></dt>
1266      * <dd>
1267      * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
1268      * and <code>endTimeMode</code>.
1269      * </dd>
1270      * </dl>
1271      * When streaming out this class, the most recent format
1272      * and the highest allowable <code>serialVersionOnStream</code>
1273      * is written.
1274      * @serial
1275      * @since 1.1.4
1276      */
1277     private int serialVersionOnStream = currentSerialVersion;
1278 
1279     // Maximum number of rules.
1280     private static final int MAX_RULE_NUM = 6;
1281 
1282     private void invalidateCache() {
1283         cache = null;

1284     }
1285 
1286     //----------------------------------------------------------------------
1287     // Rule representation
1288     //
1289     // We represent the following flavors of rules:
1290     //       5        the fifth of the month
1291     //       lastSun  the last Sunday in the month
1292     //       lastMon  the last Monday in the month
1293     //       Sun>=8   first Sunday on or after the eighth
1294     //       Sun<=25  last Sunday on or before the 25th
1295     // This is further complicated by the fact that we need to remain
1296     // backward compatible with the 1.1 FCS.  Finally, we need to minimize
1297     // API changes.  In order to satisfy these requirements, we support
1298     // three representation systems, and we translate between them.
1299     //
1300     // INTERNAL REPRESENTATION
1301     // This is the format SimpleTimeZone objects take after construction or
1302     // streaming in is complete.  Rules are represented directly, using an
1303     // unencoded format.  We will discuss the start rule only below; the end


< prev index next >