/** Converts UTC as milliseconds to time field values. */ protected void computeFields() { int rawOffset = getTimeZone().getRawOffset(); long localMillis = time + rawOffset; // Check for very extreme values -- millis near Long.MIN_VALUE or // Long.MAX_VALUE. For these values, adding the zone offset can push // the millis past MAX_VALUE to MIN_VALUE, or vice versa. This produces // the undesirable effect that the time can wrap around at the ends, // yielding, for example, a Date(Long.MAX_VALUE) with a big BC year // (should be AD). Handle this by pinning such values to Long.MIN_VALUE // or Long.MAX_VALUE. - liu 8/11/98 CR 4149677 if (time > 0 && localMillis < 0 && rawOffset > 0) { localMillis = Long.MAX_VALUE; } else if (time < 0 && localMillis > 0 && rawOffset < 0) { localMillis = Long.MIN_VALUE; } // Time to fields takes the wall millis (Standard or DST). timeToFields(localMillis); long days = (long) (localMillis / ONE_DAY); int millisInDay = (int) (localMillis - (days * ONE_DAY)); if (millisInDay < 0) millisInDay += ONE_DAY; // Call getOffset() to get the TimeZone offset. // The millisInDay value must be standard local millis. int dstOffset = getTimeZone() .getOffset( AD, this.fields[YEAR], this.fields[MONTH], this.fields[DATE], this.fields[DAY_OF_WEEK], millisInDay) - rawOffset; // Adjust our millisInDay for DST, if necessary. millisInDay += dstOffset; // If DST has pushed us into the next day, // we must call timeToFields() again. // This happens in DST between 12:00 am and 1:00 am every day. // The call to timeToFields() will give the wrong day, // since the Standard time is in the previous day if (millisInDay >= ONE_DAY) { long dstMillis = localMillis + dstOffset; millisInDay -= ONE_DAY; // As above, check for and pin extreme values if (localMillis > 0 && dstMillis < 0 && dstOffset > 0) { dstMillis = Long.MAX_VALUE; } else if (localMillis < 0 && dstMillis > 0 && dstOffset < 0) { dstMillis = Long.MIN_VALUE; } timeToFields(dstMillis); } // Fill in all time-related fields based on millisInDay. // so as not to perturb flags. this.fields[MILLISECOND] = millisInDay % 1000; millisInDay /= 1000; this.fields[SECOND] = millisInDay % 60; millisInDay /= 60; this.fields[MINUTE] = millisInDay % 60; millisInDay /= 60; this.fields[HOUR_OF_DAY] = millisInDay; this.fields[AM_PM] = millisInDay / 12; this.fields[HOUR] = millisInDay % 12; }