simpletimezone.java
来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 739 行 · 第 1/3 页
JAVA
739 行
private int serialVersionOnStream = currentSerialVersion;
//----------------------------------------------------------------------
// Rule representation
//
// We represent the following flavors of rules:
// 5 the fifth of the month
// lastSun the last Sunday in the month
// lastMon the last Monday in the month
// Sun>=8 first Sunday on or after the eighth
// Sun<=25 last Sunday on or before the 25th
// This is further complicated by the fact that we need to remain
// backward compatible with the 1.1 FCS. Finally, we need to minimize
// API changes. In order to satisfy these requirements, we support
// three representation systems, and we translate between them.
//
// INTERNAL REPRESENTATION
// This is the format SimpleTimeZone objects take after construction or
// streaming in is complete. Rules are represented directly, using an
// unencoded format. We will discuss the start rule only below; the end
// rule is analogous.
// startMode Takes on enumerated values DAY_OF_MONTH,
// DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM.
// startDay The day of the month, or for DOW_IN_MONTH mode, a
// value indicating which DOW, such as +1 for first,
// +2 for second, -1 for last, etc.
// startDayOfWeek The day of the week. Ignored for DAY_OF_MONTH.
//
// ENCODED REPRESENTATION
// This is the format accepted by the constructor and by setStartRule()
// and setEndRule(). It uses various combinations of positive, negative,
// and zero values to encode the different rules. This representation
// allows us to specify all the different rule flavors without altering
// the API.
// MODE startMonth startDay startDayOfWeek
// DOW_IN_MONTH_MODE >=0 !=0 >0
// DOM_MODE >=0 >0 ==0
// DOW_GE_DOM_MODE >=0 >0 <0
// DOW_LE_DOM_MODE >=0 <0 <0
// (no DST) don't care ==0 don't care
//
// STREAMED REPRESENTATION
// We must retain binary compatibility with the 1.1 FCS. The 1.1 code only
// handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the
// flag useDaylight. When we stream an object out, we translate into an
// approximate DOW_IN_MONTH_MODE representation so the object can be parsed
// and used by 1.1 code. Following that, we write out the full
// representation separately so that contemporary code can recognize and
// parse it. The full representation is written in a "packed" format,
// consisting of a version number, a length, and an array of bytes. Future
// versions of this class may specify different versions. If they wish to
// include additional data, they should do so by storing them after the
// packed representation below.
//----------------------------------------------------------------------
/**
* Given a set of encoded rules in startDay and startDayOfMonth, decode
* them and set the startMode appropriately. Do the same for endDay and
* endDayOfMonth. Upon entry, the day of week variables may be zero or
* negative, in order to indicate special modes. The day of month
* variables may also be negative. Upon exit, the mode variables will be
* set, and the day of week and day of month variables will be positive.
* This method also recognizes a startDay or endDay of zero as indicating
* no DST.
*/
private void decodeRules()
{
useDaylight = (startDay != 0) && (endDay != 0);
if (startDayOfWeek == 0)
startMode = DOM_MODE;
else if (startDayOfWeek > 0)
startMode = DOW_IN_MONTH_MODE;
else
{
startDayOfWeek = -startDayOfWeek;
if (startDay > 0) startMode = DOW_GE_DOM_MODE;
else
{
startDay = -startDay;
startMode = DOW_LE_DOM_MODE;
}
}
if (endDayOfWeek == 0)
endMode = DOM_MODE;
else if (endDayOfWeek > 0)
endMode = DOW_IN_MONTH_MODE;
else
{
endDayOfWeek = -endDayOfWeek;
if (endDay > 0) endMode = DOW_GE_DOM_MODE;
else
{
endDay = -endDay;
endMode = DOW_LE_DOM_MODE;
}
}
}
/**
* Make rules compatible to 1.1 FCS code. Since 1.1 FCS code only understands
* day-of-week-in-month rules, we must modify other modes of rules to their
* approximate equivalent in 1.1 FCS terms. This method is used when streaming
* out objects of this class. After it is called, the rules will be modified,
* with a possible loss of information. startMode and endMode will NOT be
* altered, even though semantically they should be set to DOW_IN_MONTH_MODE,
* since the rule modification is only intended to be temporary.
*/
private void makeRulesCompatible()
{
switch (startMode)
{
case DOM_MODE:
startDay = 1 + (startDay / 7);
startDayOfWeek = Calendar.SUNDAY;
break;
case DOW_GE_DOM_MODE:
// A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
// that is, Sun>=1 == firstSun.
if (startDay != 1)
startDay = 1 + (startDay / 7);
break;
case DOW_LE_DOM_MODE:
if (startDay >= 30)
startDay = -1;
else
startDay = 1 + (startDay / 7);
break;
}
switch (endMode)
{
case DOM_MODE:
endDay = 1 + (endDay / 7);
endDayOfWeek = Calendar.SUNDAY;
break;
case DOW_GE_DOM_MODE:
// A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
// that is, Sun>=1 == firstSun.
if (endDay != 1)
endDay = 1 + (endDay / 7);
break;
case DOW_LE_DOM_MODE:
if (endDay >= 30)
endDay = -1;
else
endDay = 1 + (endDay / 7);
break;
}
}
/**
* Pack the start and end rules into an array of bytes. Only pack
* data which is not preserved by makeRulesCompatible.
*/
private byte[] packRules()
{
byte[] rules = new byte[4];
rules[0] = (byte)startDay;
rules[1] = (byte)startDayOfWeek;
rules[2] = (byte)endDay;
rules[3] = (byte)endDayOfWeek;
return rules;
}
/**
* Given an array of bytes produced by packRules, interpret them
* as the start and end rules.
*/
private void unpackRules(byte[] rules)
{
startDay = rules[0];
startDayOfWeek = rules[1];
endDay = rules[2];
endDayOfWeek = rules[3];
}
/**
* Write object out to a serialization stream. Note that we write out two
* formats, a 1.1 FCS-compatible format, using DOW_IN_MONTH_MODE rules,
* in the "required" section, followed by the full rules, in packed format,
* in the "optional" section. The optional section will be ignored by 1.1
* FCS code upon stream in.
*/
private void writeObject(ObjectOutputStream stream)
throws IOException
{
// Construct a binary rule
byte[] rules = packRules();
// Convert to 1.1 FCS rules. This step may cause us to lose information.
makeRulesCompatible();
// Write out the 1.1 FCS rules
stream.defaultWriteObject();
// Write out the binary rules in the optional data area of the stream.
stream.writeInt(rules.length);
stream.write(rules);
// Recover the original rules. This recovers the information lost
// by makeRulesCompatible.
unpackRules(rules);
}
/**
* Read this object out to a serialization stream. We handle both 1.1 FCS
* binary formats, and full formats with a packed byte array.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
if (serialVersionOnStream < 1)
{
// Fix a bug in the 1.1 SimpleTimeZone code -- namely,
// startDayOfWeek and endDayOfWeek were usually uninitialized. We can't do
// too much, so we assume SUNDAY, which actually works most of the time.
if (startDayOfWeek == 0) startDayOfWeek = Calendar.SUNDAY;
if (endDayOfWeek == 0) endDayOfWeek = Calendar.SUNDAY;
// The variables dstSavings, startMode, and endMode are post-1.1, so they
// won't be present if we're reading from a 1.1 stream. Fix them up.
startMode = endMode = DOW_IN_MONTH_MODE;
dstSavings = millisPerHour;
}
else
{
// For 1.1.4, in addition to the 3 new instance variables, we also
// store the actual rules (which have not be made compatible with 1.1)
// in the optional area. Read them in here and parse them.
int length = stream.readInt();
byte[] rules = new byte[length];
stream.readFully(rules);
unpackRules(rules);
}
serialVersionOnStream = currentSerialVersion;
}
}
//eof
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?