jdk/src/share/classes/java/time/zone/ZoneRules.java
changeset 19841 15c8e97d6a14
parent 17474 8c100beabcc0
child 20873 e91d5b1cb8e6
equal deleted inserted replaced
19822:4e10a58fa28f 19841:15c8e97d6a14
    62 package java.time.zone;
    62 package java.time.zone;
    63 
    63 
    64 import java.io.DataInput;
    64 import java.io.DataInput;
    65 import java.io.DataOutput;
    65 import java.io.DataOutput;
    66 import java.io.IOException;
    66 import java.io.IOException;
       
    67 import java.io.InvalidObjectException;
    67 import java.io.Serializable;
    68 import java.io.Serializable;
    68 import java.time.Duration;
    69 import java.time.Duration;
    69 import java.time.Instant;
    70 import java.time.Instant;
    70 import java.time.LocalDate;
    71 import java.time.LocalDate;
    71 import java.time.LocalDateTime;
    72 import java.time.LocalDateTime;
   143      */
   144      */
   144     private final ZoneOffsetTransitionRule[] lastRules;
   145     private final ZoneOffsetTransitionRule[] lastRules;
   145     /**
   146     /**
   146      * The map of recent transitions.
   147      * The map of recent transitions.
   147      */
   148      */
   148     private final ConcurrentMap<Integer, ZoneOffsetTransition[]> lastRulesCache =
   149     private final transient ConcurrentMap<Integer, ZoneOffsetTransition[]> lastRulesCache =
   149                 new ConcurrentHashMap<Integer, ZoneOffsetTransition[]>();
   150                 new ConcurrentHashMap<Integer, ZoneOffsetTransition[]>();
   150     /**
   151     /**
   151      * The zero-length long array.
   152      * The zero-length long array.
   152      */
   153      */
   153     private static final long[] EMPTY_LONG_ARRAY = new long[0];
   154     private static final long[] EMPTY_LONG_ARRAY = new long[0];
   313         this.wallOffsets = standardOffsets;
   314         this.wallOffsets = standardOffsets;
   314         this.lastRules = EMPTY_LASTRULES;
   315         this.lastRules = EMPTY_LASTRULES;
   315     }
   316     }
   316 
   317 
   317     /**
   318     /**
   318      * Uses a serialization delegate.
   319      * Defend against malicious streams.
   319      *
   320      * @return never
       
   321      * @throws InvalidObjectException always
       
   322      */
       
   323     private Object readResolve() throws InvalidObjectException {
       
   324         throw new InvalidObjectException("Deserialization via serialization delegate");
       
   325     }
       
   326 
       
   327     /**
       
   328      * Writes the object using a
       
   329      * <a href="../../../serialized-form.html#java.time.zone.Ser">dedicated serialized form</a>.
       
   330      * @serialData
       
   331      * <pre style="font-size:1.0em">{@code
       
   332      *
       
   333      *   out.writeByte(1);  // identifies a ZoneRules
       
   334      *   out.writeInt(standardTransitions.length);
       
   335      *   for (long trans : standardTransitions) {
       
   336      *       Ser.writeEpochSec(trans, out);
       
   337      *   }
       
   338      *   for (ZoneOffset offset : standardOffsets) {
       
   339      *       Ser.writeOffset(offset, out);
       
   340      *   }
       
   341      *   out.writeInt(savingsInstantTransitions.length);
       
   342      *   for (long trans : savingsInstantTransitions) {
       
   343      *       Ser.writeEpochSec(trans, out);
       
   344      *   }
       
   345      *   for (ZoneOffset offset : wallOffsets) {
       
   346      *       Ser.writeOffset(offset, out);
       
   347      *   }
       
   348      *   out.writeByte(lastRules.length);
       
   349      *   for (ZoneOffsetTransitionRule rule : lastRules) {
       
   350      *       rule.writeExternal(out);
       
   351      *   }
       
   352      * }
       
   353      * </pre>
       
   354      * <p>
       
   355      * Epoch second values used for offsets are encoded in a variable
       
   356      * length form to make the common cases put fewer bytes in the stream.
       
   357      * <pre style="font-size:1.0em">{@code
       
   358      *
       
   359      *  static void writeEpochSec(long epochSec, DataOutput out) throws IOException {
       
   360      *     if (epochSec >= -4575744000L && epochSec < 10413792000L && epochSec % 900 == 0) {  // quarter hours between 1825 and 2300
       
   361      *         int store = (int) ((epochSec + 4575744000L) / 900);
       
   362      *         out.writeByte((store >>> 16) & 255);
       
   363      *         out.writeByte((store >>> 8) & 255);
       
   364      *         out.writeByte(store & 255);
       
   365      *      } else {
       
   366      *          out.writeByte(255);
       
   367      *          out.writeLong(epochSec);
       
   368      *      }
       
   369      *  }
       
   370      * }
       
   371      * </pre>
       
   372      * <p>
       
   373      * ZoneOffset values are encoded in a variable length form so the
       
   374      * common cases put fewer bytes in the stream.
       
   375      * <pre style="font-size:1.0em">{@code
       
   376      *
       
   377      *  static void writeOffset(ZoneOffset offset, DataOutput out) throws IOException {
       
   378      *     final int offsetSecs = offset.getTotalSeconds();
       
   379      *     int offsetByte = offsetSecs % 900 == 0 ? offsetSecs / 900 : 127;  // compress to -72 to +72
       
   380      *     out.writeByte(offsetByte);
       
   381      *     if (offsetByte == 127) {
       
   382      *         out.writeInt(offsetSecs);
       
   383      *     }
       
   384      * }
       
   385      *}
       
   386      * </pre>
   320      * @return the replacing object, not null
   387      * @return the replacing object, not null
   321      */
   388      */
   322     private Object writeReplace() {
   389     private Object writeReplace() {
   323         return new Ser(Ser.ZRULES, this);
   390         return new Ser(Ser.ZRULES, this);
   324     }
   391     }