Path: blob/master/src/java.base/share/classes/sun/util/calendar/CalendarDate.java
41159 views
/*1* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.util.calendar;2627import java.lang.Cloneable;28import java.util.Locale;29import java.util.TimeZone;3031/**32* The <code>CalendarDate</code> class represents a specific instant33* in time by calendar date and time fields that are multiple cycles34* in different time unites. The semantics of each calendar field is35* given by a concrete calendar system rather than this36* <code>CalendarDate</code> class that holds calendar field values37* without interpreting them. Therefore, this class can be used to38* represent an amount of time, such as 2 years and 3 months.39*40* <p>A <code>CalendarDate</code> instance can be created by calling41* the <code>newCalendarDate</code> or <code>getCalendarDate</code>42* methods in <code>CalendarSystem</code>. A43* <code>CalendarSystem</code> instance is obtained by calling one of44* the factory methods in <code>CalendarSystem</code>. Manipulations45* of calendar dates must be handled by the calendar system by which46* <code>CalendarDate</code> instances have been created.47*48* <p>Some calendar fields can be modified through method calls. Any49* modification of a calendar field brings the state of a50* <code>CalendarDate</code> to <I>not normalized</I>. The51* normalization must be performed to make all the calendar fields52* consistent with a calendar system.53*54* <p>The <code>protected</code> methods are intended to be used for55* implementing a concrete calendar system, not for general use as an56* API.57*58* @see CalendarSystem59* @author Masayoshi Okutsu60* @since 1.561*/62public abstract class CalendarDate implements Cloneable {63public static final int FIELD_UNDEFINED = Integer.MIN_VALUE;64public static final long TIME_UNDEFINED = Long.MIN_VALUE;6566private Era era;67private int year;68private int month;69private int dayOfMonth;70private int dayOfWeek = FIELD_UNDEFINED;71private boolean leapYear;7273private int hours;74private int minutes;75private int seconds;76private int millis; // fractional part of the second77private long fraction; // time of day value in millisecond7879private boolean normalized;8081private TimeZone zoneinfo;82private int zoneOffset;83private int daylightSaving;84private boolean forceStandardTime;8586private Locale locale;8788protected CalendarDate() {89this(TimeZone.getDefault());90}9192protected CalendarDate(TimeZone zone) {93zoneinfo = zone;94}9596public Era getEra() {97return era;98}99100/**101* Sets the era of the date to the specified era. The default102* implementation of this method accepts any Era value, including103* <code>null</code>.104*105* @exception NullPointerException if the calendar system for this106* <code>CalendarDate</code> requires eras and the specified era107* is null.108* @exception IllegalArgumentException if the specified109* <code>era</code> is unknown to the calendar110* system for this <code>CalendarDate</code>.111*/112public CalendarDate setEra(Era era) {113if (this.era == era) {114return this;115}116this.era = era;117normalized = false;118return this;119}120121public int getYear() {122return year;123}124125public CalendarDate setYear(int year) {126if (this.year != year) {127this.year = year;128normalized = false;129}130return this;131}132133public CalendarDate addYear(int n) {134if (n != 0) {135year += n;136normalized = false;137}138return this;139}140141/**142* Returns whether the year represented by this143* <code>CalendarDate</code> is a leap year. If leap years are144* not applicable to the calendar system, this method always145* returns <code>false</code>.146*147* <p>If this <code>CalendarDate</code> hasn't been normalized,148* <code>false</code> is returned. The normalization must be149* performed to retrieve the correct leap year information.150*151* @return <code>true</code> if this <code>CalendarDate</code> is152* normalized and the year of this <code>CalendarDate</code> is a153* leap year, or <code>false</code> otherwise.154* @see BaseCalendar#isGregorianLeapYear155*/156public boolean isLeapYear() {157return leapYear;158}159160void setLeapYear(boolean leapYear) {161this.leapYear = leapYear;162}163164public int getMonth() {165return month;166}167168public CalendarDate setMonth(int month) {169if (this.month != month) {170this.month = month;171normalized = false;172}173return this;174}175176public CalendarDate addMonth(int n) {177if (n != 0) {178month += n;179normalized = false;180}181return this;182}183184public int getDayOfMonth() {185return dayOfMonth;186}187188public CalendarDate setDayOfMonth(int date) {189if (dayOfMonth != date) {190dayOfMonth = date;191normalized = false;192}193return this;194}195196public CalendarDate addDayOfMonth(int n) {197if (n != 0) {198dayOfMonth += n;199normalized = false;200}201return this;202}203204/**205* Returns the day of week value. If this CalendarDate is not206* normalized, {@link #FIELD_UNDEFINED} is returned.207*208* @return day of week or {@link #FIELD_UNDEFINED}209*/210public int getDayOfWeek() {211if (!isNormalized()) {212dayOfWeek = FIELD_UNDEFINED;213}214return dayOfWeek;215}216217public int getHours() {218return hours;219}220221public CalendarDate setHours(int hours) {222if (this.hours != hours) {223this.hours = hours;224normalized = false;225}226return this;227}228229public CalendarDate addHours(int n) {230if (n != 0) {231hours += n;232normalized = false;233}234return this;235}236237public int getMinutes() {238return minutes;239}240241public CalendarDate setMinutes(int minutes) {242if (this.minutes != minutes) {243this.minutes = minutes;244normalized = false;245}246return this;247}248249public CalendarDate addMinutes(int n) {250if (n != 0) {251minutes += n;252normalized = false;253}254return this;255}256257public int getSeconds() {258return seconds;259}260261public CalendarDate setSeconds(int seconds) {262if (this.seconds != seconds) {263this.seconds = seconds;264normalized = false;265}266return this;267}268269public CalendarDate addSeconds(int n) {270if (n != 0) {271seconds += n;272normalized = false;273}274return this;275}276277public int getMillis() {278return millis;279}280281public CalendarDate setMillis(int millis) {282if (this.millis != millis) {283this.millis = millis;284normalized = false;285}286return this;287}288289public CalendarDate addMillis(int n) {290if (n != 0) {291millis += n;292normalized = false;293}294return this;295}296297public long getTimeOfDay() {298if (!isNormalized()) {299return fraction = TIME_UNDEFINED;300}301return fraction;302}303304public CalendarDate setDate(int year, int month, int dayOfMonth) {305setYear(year);306setMonth(month);307setDayOfMonth(dayOfMonth);308return this;309}310311public CalendarDate addDate(int year, int month, int dayOfMonth) {312addYear(year);313addMonth(month);314addDayOfMonth(dayOfMonth);315return this;316}317318public CalendarDate setTimeOfDay(int hours, int minutes, int seconds, int millis) {319setHours(hours);320setMinutes(minutes);321setSeconds(seconds);322setMillis(millis);323return this;324}325326public CalendarDate addTimeOfDay(int hours, int minutes, int seconds, int millis) {327addHours(hours);328addMinutes(minutes);329addSeconds(seconds);330addMillis(millis);331return this;332}333334protected void setTimeOfDay(long fraction) {335this.fraction = fraction;336}337338public boolean isNormalized() {339return normalized;340}341342343public boolean isStandardTime() {344return forceStandardTime;345}346347public void setStandardTime(boolean standardTime) {348forceStandardTime = standardTime;349}350351public boolean isDaylightTime() {352if (isStandardTime()) {353return false;354}355return daylightSaving != 0;356}357358protected void setLocale(Locale loc) {359locale = loc;360}361362public TimeZone getZone() {363return zoneinfo;364}365366public CalendarDate setZone(TimeZone zoneinfo) {367this.zoneinfo = zoneinfo;368return this;369}370371/**372* Returns whether the specified date is the same date of this373* <code>CalendarDate</code>. The time of the day fields are374* ignored for the comparison.375*/376public boolean isSameDate(CalendarDate date) {377return getDayOfWeek() == date.getDayOfWeek()378&& getMonth() == date.getMonth()379&& getYear() == date.getYear()380&& getEra() == date.getEra();381}382383public boolean equals(Object obj) {384if (!(obj instanceof CalendarDate)) {385return false;386}387CalendarDate that = (CalendarDate) obj;388if (isNormalized() != that.isNormalized()) {389return false;390}391boolean hasZone = zoneinfo != null;392boolean thatHasZone = that.zoneinfo != null;393if (hasZone != thatHasZone) {394return false;395}396if (hasZone && !zoneinfo.equals(that.zoneinfo)) {397return false;398}399return (getEra() == that.getEra()400&& year == that.year401&& month == that.month402&& dayOfMonth == that.dayOfMonth403&& hours == that.hours404&& minutes == that.minutes405&& seconds == that.seconds406&& millis == that.millis407&& zoneOffset == that.zoneOffset);408}409410public int hashCode() {411// a pseudo (local standard) time stamp value in milliseconds412// from the Epoch, assuming Gregorian calendar fields.413long hash = ((((((long)year - 1970) * 12) + (month - 1)) * 30) + dayOfMonth) * 24;414hash = ((((((hash + hours) * 60) + minutes) * 60) + seconds) * 1000) + millis;415hash -= zoneOffset;416int normalized = isNormalized() ? 1 : 0;417int era = 0;418Era e = getEra();419if (e != null) {420era = e.hashCode();421}422int zone = zoneinfo != null ? zoneinfo.hashCode() : 0;423return (int) hash * (int)(hash >> 32) ^ era ^ normalized ^ zone;424}425426/**427* Returns a copy of this <code>CalendarDate</code>. The428* <code>TimeZone</code> object, if any, is not cloned.429*430* @return a copy of this <code>CalendarDate</code>431*/432public Object clone() {433try {434return super.clone();435} catch (CloneNotSupportedException e) {436// this shouldn't happen437throw new InternalError(e);438}439}440441/**442* Converts calendar date values to a <code>String</code> in the443* following format.444* <pre>445* yyyy-MM-dd'T'HH:mm:ss.SSSz446* </pre>447*448* @see java.text.SimpleDateFormat449*/450public String toString() {451StringBuilder sb = new StringBuilder();452CalendarUtils.sprintf0d(sb, year, 4).append('-');453CalendarUtils.sprintf0d(sb, month, 2).append('-');454CalendarUtils.sprintf0d(sb, dayOfMonth, 2).append('T');455CalendarUtils.sprintf0d(sb, hours, 2).append(':');456CalendarUtils.sprintf0d(sb, minutes, 2).append(':');457CalendarUtils.sprintf0d(sb, seconds, 2).append('.');458CalendarUtils.sprintf0d(sb, millis, 3);459if (zoneOffset == 0) {460sb.append('Z');461} else if (zoneOffset != FIELD_UNDEFINED) {462int offset;463char sign;464if (zoneOffset > 0) {465offset = zoneOffset;466sign = '+';467} else {468offset = -zoneOffset;469sign = '-';470}471offset /= 60000;472sb.append(sign);473CalendarUtils.sprintf0d(sb, offset / 60, 2);474CalendarUtils.sprintf0d(sb, offset % 60, 2);475} else {476sb.append(" local time");477}478return sb.toString();479}480481protected void setDayOfWeek(int dayOfWeek) {482this.dayOfWeek = dayOfWeek;483}484485protected void setNormalized(boolean normalized) {486this.normalized = normalized;487}488489public int getZoneOffset() {490return zoneOffset;491}492493protected void setZoneOffset(int offset) {494zoneOffset = offset;495}496497public int getDaylightSaving() {498return daylightSaving;499}500501protected void setDaylightSaving(int daylightSaving) {502this.daylightSaving = daylightSaving;503}504}505506507