程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中的Calendar日歷API用法完整解析

Java中的Calendar日歷API用法完整解析

編輯:關於JAVA

Java中的Calendar日歷API用法完整解析。本站提示廣大學習愛好者:(Java中的Calendar日歷API用法完整解析)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中的Calendar日歷API用法完整解析正文


第一部門 Calendar引見
Calendar 界說:

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {}

Calendar 可以看做是一個籠統類。
它的完成,采取了設計形式中的工場辦法。表示在:當我們獲得Calendar實例時,Calendar會依據傳入的參數來前往響應的Calendar對象。獲得Calendar實例,有以下兩種方法:
(1) 當我們經由過程 Calendar.getInstance() 獲得日用時,默許的是前往的一個GregorianCalendar對象。
     GregorianCalendar是Calendar的一個完成類,它供給了世界上年夜多半國度/地域應用的尺度日歷體系。
(2) 當我們經由過程 Calendar.getInstance(TimeZone timezone, Locale locale) 或 Calendar.getInstance(TimeZone timezone) 或 Calendar.getInstance(Locale locale)獲得日用時,是前往“對應時區(zone) 或 地域(local)等所應用的日歷”。
     例如,若是日本,則前往JapaneseImperialCalendar對象。
參考以下代碼:

public static Calendar getInstance()
{
 // 挪用createCalendar()創立日歷
 Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
 cal.sharedZone = true;
 return cal;
}


public static Calendar getInstance(TimeZone zone)
{
 // 挪用createCalendar()創立日歷
 return createCalendar(zone, Locale.getDefault());
}


public static Calendar getInstance(Locale aLocale) {
 // 挪用createCalendar()創立日歷
 Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale);
 cal.sharedZone = true;
 return cal;
}

public static Calendar getInstance(TimeZone zone,
   Locale aLocale)
{
 // 挪用createCalendar()創立日歷
 return createCalendar(zone, aLocale);
}

private static Calendar createCalendar(TimeZone zone,
   Locale aLocale)
{
 // (01) 若地域是“th”,則前往BuddhistCalendar對象
 // (02) 若地域是“JP”,則前往JapaneseImperialCalendar對象
 if ("th".equals(aLocale.getLanguage())
 && ("TH".equals(aLocale.getCountry()))) {
 return new sun.util.BuddhistCalendar(zone, aLocale);
 } else if ("JP".equals(aLocale.getVariant())
 && "JP".equals(aLocale.getCountry())
 && "ja".equals(aLocale.getLanguage())) {
 return new JapaneseImperialCalendar(zone, aLocale);
 } 

 // (03) 不然,前往GregorianCalendar對象
 return new GregorianCalendar(zone, aLocale); 
}

當我們獲得Calendar實例以後,便可以經由過程Calendar供給的一些列辦法來操作日歷。

第二部門 Calendar的道理和思惟
我們應用Calendar,不過是操作Calendar的“年、月、日、禮拜、時、分、秒”這些字段。上面,我們對這些字段的的起源、界說和盤算辦法停止進修。
1. Calendar 各個字段值的起源
我們應用Calendar,不過是應用“年、月、日、禮拜、時、分、秒”等信息。那末它是若何做到的呢? 實質上,Calendar就是保留了一個時光。以下界說:

// time 是以後時光,單元是毫秒。
// 它是以後時光間隔“January 1, 1970, 0:00:00 GMT”的差值。
protected long time;

Calendar就是依據 time 盤算出 “Calendar的年、月、日、禮拜、時、分、秒”等等信息。

2. Calendar 各個字段的界說和初始化
Calendar 的“年、月、日、禮拜、時、分、秒”這些信息,一共是17個字段。
我們應用Calendar,不過是就是應用這17個字段。它們的界說以下:
(字段0) public final static int ERA = 0;
解釋:紀元。
取值:只能為0 或 1。0表現BC(“before Christ”,即公元前),1表現AD(拉丁語“Anno Domini”,即公元)。
(字段1) public final static int YEAR = 1;
解釋:年。
(字段2) public final static int MONTH = 2;
解釋:月
取值:可認為,JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, UNDECIMBER。
     個中第一個月是 JANUARY,它為 0。
(字段3) public final static int WEEK_OF_YEAR = 3;
解釋:以後日期在今年中對應第幾個禮拜。一年中第一個禮拜的值為 1。
(字段4) public final static int WEEK_OF_MONTH = 4;
解釋:以後日期在本月中對應第幾個禮拜。一個月中第一個禮拜的值為 1。
(字段5) public final static int DATE = 5;
解釋:日。一個月中第一天的值為 1。
(字段5) public final static int DAY_OF_MONTH = 5;
解釋:同“DATE”,表現“日”。
(字段6) public final static int DAY_OF_YEAR = 6;
解釋:以後日期在今年中對應第幾天。一年中第一天的值為 1。
(字段7) public final static int DAY_OF_WEEK = 7;
解釋:禮拜幾。
取值:可認為,SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY 和 SATURDAY。
     個中,SUNDAY為1,MONDAY為2,順次類推。
(字段8) public final static int DAY_OF_WEEK_IN_MONTH = 8;
解釋:以後月中的第幾個禮拜。
取值:DAY_OF_MONTH 1 到 7 老是對應於 DAY_OF_WEEK_IN_MONTH 1;8 到 14 老是對應於 DAY_OF_WEEK_IN_MONTH 2,依此類推。
(字段9) public final static int AM_PM = 9;
解釋:上午 照樣 下晝
取值:可所以AM 或 PM。AM為0,表現上午;PM為1,表現下晝。
(字段10) public final static int HOUR = 10;
解釋:指導一天中的第幾小時。
     HOUR 用於 12 小時制時鐘 (0 - 11)。正午和午夜用 0 表現,不消 12 表現。
(字段11) public final static int HOUR_OF_DAY = 11;
解釋:指導一天中的第幾小時。
     HOUR_OF_DAY 用於 24 小時制時鐘。例如,在 10:04:15.250 PM 這一時辰,HOUR_OF_DAY 為 22。
(字段12) public final static int MINUTE = 12;
解釋:一小時中的第幾分鐘。
例如,在 10:04:15.250 PM這一時辰,MINUTE 為 4。
(字段13) public final static int SECOND = 13;
解釋:一分鐘中的第幾秒。
例如,在 10:04:15.250 PM 這一時辰,SECOND 為 15。
(字段14) public final static int MILLISECOND = 14;
解釋:一秒中的第幾毫秒。
例如,在 10:04:15.250 PM 這一時辰,MILLISECOND 為 250。
(字段15) public final static int ZONE_OFFSET = 15;
解釋:毫秒為單元指導距 GMT 的年夜致偏移量。
(字段16) public final static int DST_OFFSET = 16;
解釋:毫秒為單元指導夏令時的偏移量。
public final static int FIELD_COUNT = 17;
這17個字段是保留在int數組中。界說以下:

// 保留這17個字段的數組
protected int  fields[];
// 數組的界說函數
protected Calendar(TimeZone zone, Locale aLocale)
{
 // 初始化“fields數組”
 fields = new int[FIELD_COUNT];
 isSet = new boolean[FIELD_COUNT];
 stamp = new int[FIELD_COUNT];

 this.zone = zone;
 setWeekCountData(aLocale);
}

protected Calendar(TimeZone zone, Locale aLocale) 這是Calendar的結構函數。它會被它的子類的結構函數挪用到,從而新建“保留Calendar的17個字段數據”的數組。

3. Calendar 各個字段值的盤算
上面以get(int field)為例,扼要的解釋Calendar的17個字段的盤算和操作。 get(int field)是獲得“field”字段的值。它的界說以下:

public int get(int field) {
 // 盤算各個字段的值
 complete();
 // 前往field字段的值
 return internalGet(field);
}

解釋:get(int field)的代碼很簡略。先經由過程 complete() 盤算各個字段的值,然後在經由過程 internalGet(field) 前往“field字段的值”。
complete() 的感化就是盤算Calendar各個字段的值。它界說在Calendar.java中,代碼以下:

protected void complete()
{
 if (!isTimeSet)
 updateTime();
 if (!areFieldsSet || !areAllFieldsSet) {
 computeFields(); // fills in unset fields
 areAllFieldsSet = areFieldsSet = true;
 }
}
private void updateTime() {
 computeTime();
 isTimeSet = true;
}
updateTime() 挪用到的 computeTime() 界說在 Calendar.java的完成類中。上面,我列出GregorianCalendar.java中computeTime()的完成:
protected void computeTime() {
 // In non-lenient mode, perform brief checking of calendar
 // fields which have been set externally. Through this
 // checking, the field values are stored in originalFields[]
 // to see if any of them are normalized later.
 if (!isLenient()) {
 if (originalFields == null) {
  originalFields = new int[FIELD_COUNT];
 }
 for (int field = 0; field < FIELD_COUNT; field++) {
  int value = internalGet(field);
  if (isExternallySet(field)) {
  // Quick validation for any out of range values
  if (value < getMinimum(field) || value > getMaximum(field)) {
   throw new IllegalArgumentException(getFieldName(field));
  }
  }
  originalFields[field] = value;
 }
 }

 // Let the super class determine which calendar fields to be
 // used to calculate the time.
 int fieldMask = selectFields();

 // The year defaults to the epoch start. We don't check
 // fieldMask for YEAR because YEAR is a mandatory field to
 // determine the date.
 int year = isSet(YEAR) ? internalGet(YEAR) : EPOCH_YEAR;

 int era = internalGetEra();
 if (era == BCE) {
 year = 1 - year;
 } else if (era != CE) {
 // Even in lenient mode we disallow ERA values other than CE & BCE.
 // (The same normalization rule as add()/roll() could be
 // applied here in lenient mode. But this checking is kept
 // unchanged for compatibility as of 1.5.)
 throw new IllegalArgumentException("Invalid era");
 }

 // If year is 0 or negative, we need to set the ERA value later.
 if (year <= 0 && !isSet(ERA)) {
 fieldMask |= ERA_MASK;
 setFieldsComputed(ERA_MASK);
 }

 // Calculate the time of day. We rely on the convention that
 // an UNSET field has 0.
 long timeOfDay = 0;
 if (isFieldSet(fieldMask, HOUR_OF_DAY)) {
 timeOfDay += (long) internalGet(HOUR_OF_DAY);
 } else {
 timeOfDay += internalGet(HOUR);
 // The default value of AM_PM is 0 which designates AM.
 if (isFieldSet(fieldMask, AM_PM)) {
  timeOfDay += 12 * internalGet(AM_PM);
 }
 }
 timeOfDay *= 60;
 timeOfDay += internalGet(MINUTE);
 timeOfDay *= 60;
 timeOfDay += internalGet(SECOND);
 timeOfDay *= 1000;
 timeOfDay += internalGet(MILLISECOND);

 // Convert the time of day to the number of days and the
 // millisecond offset from midnight.
 long fixedDate = timeOfDay / ONE_DAY;
 timeOfDay %= ONE_DAY;
 while (timeOfDay < 0) {
 timeOfDay += ONE_DAY;
 --fixedDate;
 }

 // Calculate the fixed date since January 1, 1 (Gregorian).
 calculateFixedDate: {
 long gfd, jfd;
 if (year > gregorianCutoverYear && year > gregorianCutoverYearJulian) {
  gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
  if (gfd >= gregorianCutoverDate) {
  fixedDate = gfd;
  break calculateFixedDate;
  }
  jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
 } else if (year < gregorianCutoverYear && year < gregorianCutoverYearJulian) {
  jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
  if (jfd < gregorianCutoverDate) {
  fixedDate = jfd;
  break calculateFixedDate;
  }
  gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
 } else {
  gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
  jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
 }
 // Now we have to determine which calendar date it is.
 if (gfd >= gregorianCutoverDate) {
  if (jfd >= gregorianCutoverDate) {
  fixedDate = gfd;
  } else {
  // The date is in an "overlapping" period. No way
  // to disambiguate it. Determine it using the
  // previous date calculation.
  if (calsys == gcal || calsys == null) {
   fixedDate = gfd;
  } else {
   fixedDate = jfd;
  }
  }
 } else {
  if (jfd < gregorianCutoverDate) {
  fixedDate = jfd;
  } else {
  // The date is in a "missing" period.
  if (!isLenient()) {
   throw new IllegalArgumentException("the specified date doesn't exist");
  }
  // Take the Julian date for compatibility, which
  // will produce a Gregorian date.
  fixedDate = jfd;
  }
 }
 }

 // millis represents local wall-clock time in milliseconds.
 long millis = (fixedDate - EPOCH_OFFSET) * ONE_DAY + timeOfDay;

 // Compute the time zone offset and DST offset. There are two potential
 // ambiguities here. We'll assume a 2:00 am (wall time) switchover time
 // for discussion purposes here.
 // 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
 // can be in standard or in DST depending. However, 2:00 am is an invalid
 // representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
 // We assume standard time.
 // 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
 // can be in standard or DST. Both are valid representations (the rep
 // jumps from 1:59:59 DST to 1:00:00 Std).
 // Again, we assume standard time.
 // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
 // or DST_OFFSET fields; then we use those fields.
 TimeZone zone = getZone();
 if (zoneOffsets == null) {
 zoneOffsets = new int[2];
 }
 int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
 if (zone instanceof ZoneInfo) {
  ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets);
 } else {
  int gmtOffset = isFieldSet(fieldMask, ZONE_OFFSET) ?
  internalGet(ZONE_OFFSET) : zone.getRawOffset();
  zone.getOffsets(millis - gmtOffset, zoneOffsets);
 }
 }
 if (tzMask != 0) {
 if (isFieldSet(tzMask, ZONE_OFFSET)) {
  zoneOffsets[0] = internalGet(ZONE_OFFSET);
 }
 if (isFieldSet(tzMask, DST_OFFSET)) {
  zoneOffsets[1] = internalGet(DST_OFFSET);
 }
 }

 // Adjust the time zone offset values to get the UTC time.
 millis -= zoneOffsets[0] + zoneOffsets[1];

 // Set this calendar's time in milliseconds
 time = millis;

 int mask = computeFields(fieldMask | getSetStateFields(), tzMask);

 if (!isLenient()) {
 for (int field = 0; field < FIELD_COUNT; field++) {
  if (!isExternallySet(field)) {
  continue;
  }
  if (originalFields[field] != internalGet(field)) {
  // Restore the original field values
  System.arraycopy(originalFields, 0, fields, 0, fields.length);
  throw new IllegalArgumentException(getFieldName(field));
  }
 }
 }
 setFieldsNormalized(mask);
}

上面,我們看看internalGet(field)的界說。以下:

protected final int internalGet(int field) {
 return fields[field];
}

從中,我們就看出,get(int field) 終究是經由過程 internalGet(int field)來前往值的。
而 internalGet(int field) ,現實上前往的是field數組中的第field個元素。這就正好和Calendar的17個元素所對應了!
總之,我們須要懂得的就是:Calendar就是以一個time(毫秒)為基數,而盤算出“年代日時分秒”等,從而便利我們對“年代日時分秒”等停止操作。上面,引見以下Calendar供給的相干操作函數。

第三部門 Calendar函數接口
1. Calendar的17個字段的公共接口
Calendar的這17個字段,都支撐上面的公共函數接口。 這些公共接口的應用示例,請參考CalendarTest.java 示例中的 testAllCalendarSections() 函數。
(1) getMaximum(int field)
感化:獲得“字段的最年夜值”。留意“比較它和 getActualMaximum() 的差別”。 示例:以“MONTH”字段來講。應用辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 獲得MONTH的最年夜值
int max = cal.getMaximum(Calendar.MONTH);

若要獲得其它字段的最年夜值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(2) getActualMaximum(int field)
感化:獲得“以後日期下,該字段的最年夜值”。 示例:以“MONTH”字段來講。應用辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 獲得以後MONTH的最年夜值
int max = cal.getActualMaximum(Calendar.MONTH);

若要獲得其它字段的最年夜值,只須要將示例中的MONTH響應的調換成其它字段名便可。
留意:比較getActualMaximum() 和 getMaximum() 的差別。參考上面的比較示例,
A、 getMaximum() 獲得的“字段最年夜值”,是指在綜合一切的日期,在一切這些日期中得出的“字段最年夜值”。
     例如,getMaximum(Calendar.DATE)的目標是“獲得‘日的最年夜值'”。綜合一切的日期,得出一個月最多有31天。是以,getMaximum(Calendar.DATE)的前往值是“31”!
B、 getActualMaximum() 獲得的“以後日期時,該字段的最年夜值”。
     例如,當日期為2013-09-01時,getActualMaximum(Calendar.DATE)是獲得“日的最年夜值”是“30”。以後日期是9月份,而9月只要30天。是以,getActualMaximum(Calendar.DATE)的前往值是“30”!
(3) getMinimum(int field)
感化:獲得“字段的最小值”。留意“比較它和 getActualMinimum() 的差別”。 示例:以“MONTH”字段來講。應用辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 獲得MONTH的最小值
int min = cal.getMinimum(Calendar.MONTH);

若要獲得其它字段的最小值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(4) getActualMinimum(int field)

感化:獲得“以後日期下,該字段的最小值”。 示例:以“MONTH”字段來講。應用辦法為:
// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 獲得MONTH的最小值
int min = cal.getMinimum(Calendar.MONTH);

若要獲得其它字段的最小值,只須要將示例中的MONTH響應的調換成其它字段名便可。
留意:在Java默許的Calendar中,固然 getMinimum() 和 getActualMinimum() 的寄義分歧;然則,它們的前往值是一樣的。由於Calendar的默許是前往GregorianCalendar對象,而在GregorianCalendar.java中,getMinimum() 和 getActualMinimum() 前往值一樣。
(5) get(int field)
感化:獲得“字段確當前值”。獲得field字段確當前值。 示例:以“MONTH”字段來講。“獲得MONTH確當前值”的辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 獲得“cal日歷”確當前MONTH值
int MONTH = cal.get(Calendar.MONTH);

若要獲得其它字段確當前值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(6) set(int field, int value)
感化:設置“字段確當前值”。設置field字段確當前值為value 示例:以“MONTH”字段來講。“設置MONTH確當前值”的辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 設置“cal日歷”確當前MONTH值為 1988年
cal.set(Calendar.MONTH, 1988);

解釋:
A、1988 是想要設置的MONTH確當前值。這個設置值必需是整數。
B、若要設置其它字段確當前值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(7) add(int field, int value)
感化:給“字段確當前值”添加值。給field字段確當前值添加value。 示例:以“MONTH”字段來講。辦法以下:

// 獲得Calendar實例,並設置日期為“2013-09-01”
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2013);
cal.set(Calendar.MONTH, 8);
cal.set(Calendar.DATE, 1);
// 給“cal日歷”確當前MONTH值 “添加-10”
cal.add(Calendar.MONTH, -10);

解釋:
A、 -10 是添加值。
     添加值可認為負數,也能夠是正數。
     負數表現將日期增長,正數表現將日期削減。
     假定:如今cal的值是“2013-09-01”,如今我們將MONTH字段值增長-10。獲得的成果是:“2012-10-01”。
     為何會如許呢?“2013-09-01”增長-10,也就是將日期向前削減10個月;獲得的成果就是“2012-10-01”。
B、 Calendar的17個字段中:除回滾Calendar.ZONE_OFFSET時,會拋出IllegalArgumentException異常;其它的字段都支撐該操作。
C、 若要設置其它字段確當前值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(8) roll(int field, int value)
感化:回滾“字段確當前值” 示例:以“MONTH”字段來講。“回滾MONTH確當前值”的辦法為:

// 獲得Calendar實例,並設置日期為“2013-09-01”
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2013);
cal.set(Calendar.MONTH, 8);
cal.set(Calendar.DATE, 1);
// 將“cal日歷”確當前MONTH值 “向前轉動10”
cal.roll(Calendar.MONTH, -10);

解釋:
A、 -10 是回滾值。
     當回滾值是正數時,表現將以後字段向前滾;
     當回滾值是負數時,表現將以後字段向後滾。
     回滾Calendar中某一字段時,不更改更年夜的字段!
     這是roll()與add()的依據差別!add()能夠會更改更年夜字段,好比“應用add()修正‘MONTH'字段,能夠會惹起‘YEAR'字段的轉變”;然則roll()不會更改更年夜的字段,例如“應用roll()修正‘MONTH'字段,不回惹起‘YEAR'字段的轉變。”
     假定:如今cal的值是“2013-09-01”,如今我們將MONTH字段值增長-10。獲得的成果是:“2013-10-01”。
     為何會如許呢?這就是由於“回滾”就是“在最小值和最年夜值之間往返轉動”。本例中,MONTH是9月,前回滾10,獲得的值是10月,然則roll()不會轉變“比MONTH”更年夜的字段,所以YEAR字段不會轉變。所以成果是“2013-10-01”。
B、 Calendar的17個字段中:除回滾Calendar.ZONE_OFFSET時,會拋出IllegalArgumentException異常;其它的字段都支撐該操作。
C、 若要設置其它字段確當前值,只須要將示例中的MONTH響應的調換成其它字段名便可。
(9) clear(int field)
感化:清空“字段確當前值”。所謂清空,現實上是將“field”的值設置為0;若field最小值為1,則設置為1。 示例:以“MONTH”字段來講。“清空MONTH”的辦法為:

// 獲得Calendar實例,並設置日期為“9月”
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 9);
// 清空MONTH
cal.clear(Calendar.MONTH);

若要清空其它字段,只須要將示例中的MONTH響應的調換成其它字段名便可。
(10) isSet(int field)
感化:斷定“字段field”能否被設置。若挪用clear()清空以後,則field變成“沒有設置狀況”。 示例:以“MONTH”字段來講。“斷定MONTH能否被設置”的辦法為:

// 獲得Calendar實例
Calendar cal = Calendar.getInstance();
// 斷定MONTH能否被設置
boolean bset = cal.isSet(Calendar.MONTH);

若要斷定其它字段,只須要將示例中的MONTH響應的調換成其它字段名便可。

2. Calendar的其它函數
(1) 日期比擬函數
Calendar的比擬函數,重要有以下幾個:

// 比擬“以後Calendar對象”和“calendar” 的日期、時區等外容能否相等。
boolean equals(Object object)
// 以後Calendar對象 能否 早於calendar
boolean before(Object calendar)
// 以後Calendar對象 能否 晚於calendar
boolean after(Object calendar)
// 比擬“以後Calendar對象”和“calendar”。
// 若 早於 “calendar” 則,前往-1
// 若 相等, 則,前往0
// 若 晚於 “calendar” 則,前往1
int compareTo(Calendar anotherCalendar) 

這些函數的應用示例,請參考CalendarTest.java示例中的 testComparatorAPIs() 函數。
示例:假定cal1 和 cal2 都是Calendar的兩個對象。

// 它們的應用辦法以下
boolean isEqual = cal1.equals(cal2);
boolean isBefore = cal1.before(cal2);
boolean isAfter = cal1.after(cal2);
int icompare = cal1.compareTo(cal2);

(2) “寬容”函數

// 設置“Calendar的寬容度”
void setLenient(boolean value)
// 獲得“Calendar的寬容度”
boolean isLenient()

這些函數的應用示例,請參考CalendarTest.java示例中的 testLenientAPIs() 函數。
解釋:
Calendar 有兩種說明日歷字段的形式,即 lenient 和 non-lenient。
A、 當 Calendar 處於 lenient 形式時,它可接收比它所生成的日歷字段規模更年夜規模內的值。當 Calendar 從新盤算日歷字段值,以便由 get() 前往這些值時,一切日歷字段都被尺度化。
     例如,lenient 形式下的 GregorianCalendar 將 MONTH == JANUARY、DAY_OF_MONTH == 32 說明為 February 1。
B、 當 Calendar 處於 non-lenient 形式時,假如其日歷字段中存在任何紛歧致性,它都邑拋出一個異常。
     例如,GregorianCalendar 老是在 1 與月份的長度之間生成 DAY_OF_MONTH 值。假如曾經設置了任何超越規模的字段值,那末在盤算時光或日歷字段值時,處於 non-lenient 形式下的 GregorianCalendar 會拋出一個異常。
留意:在(02)步調中的異常,在應用set()時不會拋出,而須要在應用get()、getTimeInMillis()、getTime()、add() 和 roll() 等函數中才拋出。由於set()只是設置了一個修正標記,而get()等辦法才會惹起時光的從新盤算,此時才會拋出異常!
(3) "年代日(時分秒)"、Date、TimeZone、MilliSecond函數

// 設置“年代日”
final void set(int year, int month, int day)
// 設置“年代日時分”
final void set(int year, int month, int day, int hourOfDay, int minute, int second)
// 設置“年代日時分秒”
final void set(int year, int month, int day, int hourOfDay, int minute)
// 獲得Calendar對應的日期
final Date getTime()
// 設置Calendar為date
final void setTime(Date date)
// 獲得Calendar對應的時區
TimeZone getTimeZone()
// 設置Calendar對應的時區
void setTimeZone(TimeZone timezone)
// 獲得Calendar對應的milliscondes值,就是“Calendar以後日期”間隔“1970-01-01 0:00:00 GMT”的毫秒數
long getTimeInMillis()
// 設置Calendar對應的milliscondes值
void setTimeInMillis(long milliseconds)

這些函數的應用示例,請參考CalendarTest.java示例中的 testTimeAPIs() 函數。
(4) 其它操作

// 克隆Calendar
Object clone()
// 獲得“每周的第一天是禮拜幾”。例如,在美國,這一天是 SUNDAY,而在法國,這一天是 MONDAY。
int getFirstDayOfWeek()
// 設置“每周的第一天是禮拜幾”。例如,在美國,這一天是 SUNDAY,而在法國,這一天是 MONDAY。
void setFirstDayOfWeek(int value)
// 獲得一年中第一個禮拜所需的起碼天數,例如,假如界說第一個禮拜包括一年第一個月的第一天,則此辦法將前往 1。假如起碼天數必需是一全部禮拜,則此辦法將前往 7。
int getMinimalDaysInFirstWeek()
// 設置一年中第一個禮拜所需的起碼天數,例如,假如界說第一個禮拜包括一年第一個月的第一天,則應用值 1 挪用此辦法。假如起碼天數必需是一全部禮拜,則應用值 7 挪用此辦法。
void setMinimalDaysInFirstWeek(int value)

這些函數的應用示例,請參考CalendarTest.java示例中的 testOtherAPIs() 函數。

第四部門 Calendar應用示例
上面,我們經由過程示例進修應用Calendar的API。CalendarTest.java的源碼以下:

import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Random;

public class CalendarTest {

 public static void main(String[] args) {

 // 測試Calendar的“17個字段的公共函數接口”
 testAllCalendarSections() ;

 // 測試Calendar的“比擬接口”
 testComparatorAPIs() ;

 // 測試Calendar的“比擬接口”
 testLenientAPIs() ;

 // 測試Calendar的Date、TimeZone、MilliSecond等相干函數
 testTimeAPIs() ;

 // 測試Calendar的clone(),getFirstDayOfWeek()等接口
 testOtherAPIs() ;

 }


 /**
 * 測試“Calendar的字段”
 *
 * @param cal -- Calendar對象
 * @param field -- 要測試的“Calendar字段”。可認為以下值:
 * Calendar.YEAR, Calendar.MONTH, Calendar.DATE, ... 等等
 * @param title -- 題目
 */
 private static void testSection(Calendar cal, int field, String title) {
 final Random random = new Random();
 final Date date = cal.getTime();

 final int min = cal.getMinimum(field); // 獲得"字段最小值"
 final int max = cal.getMaximum(field); // 獲得“字段最年夜值”

 final int actualMin = cal.getActualMinimum(field); // 獲得"以後日期下,該字段最小值"
 final int actualMax = cal.getActualMaximum(field); // 獲得“以後日期下,該字段的最年夜值”

 // 獲得“字段確當前值”
 final int ori = cal.get(field);  

 // 設置“字段確當前值”, 並獲得“設置以後的值”
 final int r1 = random.nextInt(max);
 cal.set(field, r1);  
 final int set = cal.get(field);  
 try {
  // 回滾“字段確當前值”:在“字段最小值”和“字段最年夜值”之間回滾。
  // “回滾值”可認為正,也能夠為負。
  cal.roll(field, -max);  
 } catch (IllegalArgumentException e) {
  // 當field == Calendar.ZONE_OFFSET時,會拋出該異常!
  e.printStackTrace();
 }
 final int roll = cal.get(field);  

 // 獲得一個隨機值
 final int sign = ( random.nextInt(2) == 1) ? 1 : -1;
 final int r2 = sign * random.nextInt(max);
 try {
  // 增長“字段確當前值” ,並獲得“新確當前字段值”
  // add的“參數值”可認為正,也能夠為負。
  cal.add(field, r2);  
 } catch (IllegalArgumentException e) {
  // 當field == Calendar.ZONE_OFFSET時,會拋出該異常!
  e.printStackTrace();
 }
 final int add = cal.get(field);



 // 打印字段信息
 System.out.printf("%s:\n\trange is [%d - %d] actualRange is [%d - %d]. original=%d, set(%d)=%d, roll(%d)=%d, add(%d)=%d\n",
  title, min, max, actualMin, actualMax, ori, r1, set, -max, roll, r2, add);
 }

 /**
 * 測試Calendar的“17個字段的公共函數接口”
 */
 private static void testAllCalendarSections() {
 // 00. ERA 字段
 testSection(Calendar.getInstance(), Calendar.ERA, "Calendar.ERA");
 // 01. YEAR 字段
 testSection(Calendar.getInstance(), Calendar.YEAR, "Calendar.YEAR");
 // 02. MONTH 字段
 testSection(Calendar.getInstance(), Calendar.MONTH, "Calendar.MONTH");
 // 03. WEEK_OF_YEAR 字段
 testSection(Calendar.getInstance(), Calendar.WEEK_OF_YEAR, "Calendar.WEEK_OF_YEAR");
 // 04. WEEK_OF_MONTH 字段
 testSection(Calendar.getInstance(), Calendar.WEEK_OF_MONTH, "Calendar.WEEK_OF_MONTH");
 // 05. DATE 字段
 testSection(Calendar.getInstance(), Calendar.DATE, "Calendar.DATE");
 // 06. DAY_OF_MONTH 字段
 testSection(Calendar.getInstance(), Calendar.DAY_OF_MONTH, "Calendar.DAY_OF_MONTH");
 // 07. DAY_OF_YEAR 字段
 testSection(Calendar.getInstance(), Calendar.DAY_OF_YEAR, "Calendar.DAY_OF_YEAR");
 // 08. DAY_OF_WEEK 字段
 testSection(Calendar.getInstance(), Calendar.DAY_OF_WEEK, "Calendar.DAY_OF_WEEK");
 // 09. DAY_OF_WEEK_IN_MONTH 字段
 testSection(Calendar.getInstance(), Calendar.DAY_OF_WEEK_IN_MONTH, "Calendar.DAY_OF_WEEK_IN_MONTH");
 // 10. AM_PM 字段
 testSection(Calendar.getInstance(), Calendar.AM_PM, "Calendar.AM_PM");
 // 11. HOUR 字段
 testSection(Calendar.getInstance(), Calendar.HOUR, "Calendar.HOUR");
 // 12. HOUR_OF_DAY 字段
 testSection(Calendar.getInstance(), Calendar.HOUR_OF_DAY, "Calendar.HOUR_OF_DAY");
 // 13. MINUTE 字段
 testSection(Calendar.getInstance(), Calendar.MINUTE, "Calendar.MINUTE");
 // 14. SECOND 字段
 testSection(Calendar.getInstance(), Calendar.SECOND, "Calendar.SECOND");
 // 15. MILLISECOND 字段
 testSection(Calendar.getInstance(), Calendar.MILLISECOND, "Calendar.MILLISECOND");
 // 16. ZONE_OFFSET 字段
 testSection(Calendar.getInstance(), Calendar.ZONE_OFFSET, "Calendar.ZONE_OFFSET");
 }

 /**
 * 測試Calendar的“比擬接口”
 */
 private static void testComparatorAPIs() {
 // 新建cal1 ,且時光為1988年
 Calendar cal1 = Calendar.getInstance();
 cal1.set(Calendar.YEAR, 1988);
 // 新建cal2 ,且時光為2000年
 Calendar cal2 = Calendar.getInstance();
 cal2.set(Calendar.YEAR, 2000);
 // 新建cal3, 為cal1的克隆對象
 Calendar cal3 = (Calendar)cal1.clone();

 // equals 斷定 cal1和cal2的“時光、時區等”內容能否相等
 boolean isEqual12 = cal1.equals(cal2);
 // equals 斷定 cal1和cal3的“時光、時區等”內容能否相等
 boolean isEqual13 = cal1.equals(cal3);
 // cal1能否比cal2早
 boolean isBefore = cal1.before(cal2);
 // cal1能否比cal2晚
 boolean isAfter = cal1.after(cal2);
 // 比擬cal1和cal2
 // (01) 若cal1 早於 cal2,前往-1
 // (02) 若cal1 等於 cal2,前往0
 // (03) 若cal1 晚於 cal2,前往1
 int icompare = cal1.compareTo(cal2);

 System.out.printf("\ntestComparatorAPIs: isEuqal12=%s, isEqual13=%s, isBefore=%s, isAfter=%s, icompare=%s\n",
  isEqual12, isEqual13, isBefore, isAfter, icompare);
 }

 /**
 * 測試Calendar的“比擬接口”
 */
 private static void testLenientAPIs() {
  Calendar cal = Calendar.getInstance();

  // 獲得默許的“寬容度”。前往true
  boolean oriLenient = cal.isLenient();
  // MONTH值只能是“0-11”,這裡越界。然則因為以後cal是寬容的,所以不會拋出異常
  cal.set(Calendar.MONTH, 50); 

  // 設置“寬容度”為false。
  cal.setLenient(false);
  // 獲得設置後的“寬容度”
  boolean curLenient = cal.isLenient();
  try {
  // MONTH值只能是“0-11”,這裡越界。並且以後cal是不寬容的,所以會發生異常。
  // 然則,異常到下次盤算日期時才會拋出。即,set()中不回拋出異常,而要比及get()中才會拋出異常
  cal.set(Calendar.MONTH, 50);
  // 此時,對cal停止讀取。讀取會招致從新盤算cal的值,所以此時拋出異常!
  int m2 = cal.get(Calendar.MONTH); 
 } catch (IllegalArgumentException e) {
  e.printStackTrace();
 }

 System.out.printf("\ntestLenientAPIs: oriLenient=%s, curLenient=%s\n",
  oriLenient, curLenient);
 }

 /**
 * 測試Calendar的Date、TimeZone、MilliSecond等相干函數
 */
 private static void testTimeAPIs() {
 Calendar cal = Calendar.getInstance();

 // 設置cal的時區為“GMT+8”
 cal.setTimeZone(TimeZone.getTimeZone("GMT+8"));
 // 獲得以後的cal時區
 TimeZone timezone = cal.getTimeZone();

 // 設置 milliseconds
 cal.setTimeInMillis(1279419645742l);
 // 獲得 milliseconds
 long millis = cal.getTimeInMillis();
 // 設置 milliseconds以後,時光也轉變了。
 // 獲得cal對應的日期
 Date date = cal.getTime();

 // 設置時光為“1988-08-08”
 cal.set(1988, 08, 08);
 // 設置時光為“1999-09-09 09:09”
 cal.set(1999, 09, 09, 9, 9);
 // 設置時光為“2000-10-10 10:10:10”
 cal.set(2000, 10, 10, 10, 10, 10);

 System.out.printf("\ntestTimeAPIs: date=%s, timezone=%s, millis=%s\n",
  date, timezone, millis);
 }

 /**
 * 測試Calendar的clone(),getFirstDayOfWeek()等接口
 */
 private static void testOtherAPIs() {
 Calendar cal = Calendar.getInstance();
 // 克隆cal
 Calendar clone = (Calendar)cal.clone();

 // 設置 為 2013-01-10。 
 // 注:2013-01-01 為“禮拜二”,2013-01-06為“禮拜天”,
 clone.set(Calendar.YEAR, 2013);
 clone.set(Calendar.MONTH, 0);
 clone.set(Calendar.DATE, 10);
 // 設置“今年的第一個禮拜起碼包括1天”。
 // 則2013-01-10屬於第2個禮拜
 clone.setMinimalDaysInFirstWeek(1);
 int m1 = clone.getMinimalDaysInFirstWeek();
 int index1 = clone.get(Calendar.WEEK_OF_YEAR);

 // 設置“今年的第一個禮拜起碼包括7天”。
 // 則2013-01-10屬於第1個禮拜
 clone.setMinimalDaysInFirstWeek(7);
 int m2 = clone.getMinimalDaysInFirstWeek();
 int index2 = clone.get(Calendar.WEEK_OF_YEAR);

 // 設置“每周的第一天是禮拜幾”。
 clone.setFirstDayOfWeek(Calendar.WEDNESDAY);
 // 獲得“每周的第一天是禮拜幾”。
 int firstdayOfWeek = clone.getFirstDayOfWeek();

 System.out.printf("\ntestOtherAPIs: firstdayOfWeek=%s, [minimalDay, WeekOfYear]={(%s, %s), (%s, %s)} %s\n",
  firstdayOfWeek, m1, index1, m2, index2, clone.getTime());
 }
}

第五部門 自界說的Calendar接口示例
這些接口在寫日過程序時能夠會用到。
源代碼以下(CalendarSelfDefineTest.java):

import java.util.Calendar;

/**
 * 依據Calendar的API封裝的一些經常使用函數
 */
public class CalendarSelfDefineTest {

 public static void main(String[] args) {
 Calendar cal = Calendar.getInstance();

 // 設置日期為“2013-09-18”
 cal.set(2013, Calendar.SEPTEMBER, 18);

 // 獲得“年”
 System.out.printf("year: %s\n", getYear(cal) );
 // 獲得“月”
 System.out.printf("month: %s\n", getMonth(cal) );
 // 獲得“上月”
 System.out.printf("previcou month: %s\n", getLastMonth(cal) );
 // 獲得“下月”
 System.out.printf("next month: %s\n", getNextMonth(cal) );
 // 獲得“日”
 System.out.printf("day: %s\n", getDay(cal) );
 // 獲得Cal對應禮拜幾
 System.out.printf("weekday: %s\n", getWeekDay(cal) );
 // 本月天數
 System.out.printf("Current Month days: %s\n", getMonthDays(cal) );
 // 上月天數
 System.out.printf("Previcous Month days: %s\n", getPrevMonthDays(cal) );
 // 下月天數
 System.out.printf("Next Month days: %s\n", getNextMonthDays(cal) );
 // 獲得當月第一天的禮拜幾
 System.out.printf("First day' weekday : %s\n", getFirstDayWeekday(cal) );
 // 獲得以後月最初一天的禮拜幾
 System.out.printf("Last day' weekday : %s\n", getLastDayWeekday(cal) );
 // 獲得上月最初一天的禮拜幾
 System.out.printf("PrevMonth Last day' weekday: %s\n", getLastDayWeekdayOfPrevMonth(cal) );
 // 獲得下月第一天的禮拜幾
 System.out.printf("NextMonth First day' weekday: %s\n", getFirstDayWeekdayOfNextMonth(cal) );
 }

 /**
 * 獲得“年”
 * 
 * @return 例如,2013-09-18,則前往2013
 */
 public static int getYear(Calendar cal) {
 return cal.get(Calendar.YEAR);
 } 

 /**
 * 獲得“月”
 * 
 * @return 前往值可認為以下值:
 * JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, UNDECIMBER。
 * 個中第一個月是 JANUARY,它為 0。
 *
 * 例如,2013-09-18,則前往8
 */
 public static int getMonth(Calendar cal) {
 return cal.get(Calendar.MONTH);
 } 

 /**
 * 獲得“上一個月”
 * 
 * @return 前往值可認為以下值:
 * JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, UNDECIMBER。
 * 個中第一個月是 JANUARY,它為 0。
 *
 * 例如,2012-01-12的上一個月是“11”(即DECEMBER)。
 */
 public static int getLastMonth(Calendar cal) {
 return (cal.get(Calendar.MONTH) + 11) % 12;
 } 

 /**
 * 獲得“下一個月”
 * 
 * @return 前往值可認為以下值:
 * JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, UNDECIMBER。
 * 個中第一個月是 JANUARY,它為 0。
 *
 * 例如,2013-12-12的下一個月是“1”(即DECEMBER)。
 */
 public static int getNextMonth(Calendar cal) {
 return (cal.get(Calendar.MONTH) + 13) % 12;
 } 

 /**
 * 獲得“日”
 *
 * @return 例如,2013-09-18,則前往18
 *
 */
 public static int getDay(Calendar cal) {
 return cal.get(Calendar.DATE);
 } 

 /**
 * 獲得“本月的天數”
 *
 * @return 例如,2013-09-18,則前往30
 *
 */
 public static int getMonthDays(Calendar cal) {
 return cal.getActualMaximum(Calendar.DATE); 
 } 

 /**
 * 獲得“上一個月的天數”
 *
 * @return 例如,2013-01-18,則前往31 (由於2012-12有31天)
 *
 */
 public static int getPrevMonthDays(Calendar cal) {
 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.add(Calendar.MONTH, -1);   // 設為“上一個月”
 return tmpCal.getActualMaximum(Calendar.DATE); 
 } 

 /**
 * 獲得“下一個月的天數”
 *
 * @return 例如,2013-12-18,則前往31 (由於2014-01有31天)
 *
 */
 public static int getNextMonthDays(Calendar cal) {
 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.add(Calendar.MONTH, 1);   // 設為“下一個月”
 return tmpCal.getActualMaximum(Calendar.DATE); 
 } 

 /**
 * 獲得Cal對應禮拜幾
 *
 * @return 前往“禮拜幾”,可認為以下值:
 * SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY 和 SATURDAY。
 * SUNDAY為1,MONDAY為2,順次類推。
 * 例如,2013-09-18(禮拜三),則前往4
 */
 public static int getWeekDay(Calendar cal) {
 return cal.get(Calendar.DAY_OF_WEEK);
 } 


 /**
 * 獲得當月第一天對應禮拜幾
 *
 * @return SUNDAY為1,MONDAY為2,順次類推。
 */
 public static int getFirstDayWeekday(Calendar cal) {

 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.set(Calendar.DATE, 1);   // 把日期設置為當月第一天 
 return tmpCal.get(Calendar.DAY_OF_WEEK);
 } 

 /**
 * 獲得以後月最初一天對應禮拜幾
 * 
 * @return SUNDAY為1,MONDAY為2,順次類推。
 */
 public static int getLastDayWeekday(Calendar cal) {
 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.set(Calendar.DATE, 1);   // 把日期設置為當月第一天 
 tmpCal.roll(Calendar.DATE, -1);   // 把日期設置為當月最初一天 
 return tmpCal.get(Calendar.DAY_OF_WEEK);
 } 


 /**
 * 獲得上月最初一天的禮拜幾
 * 
 * @return SUNDAY為1,MONDAY為2,順次類推。
 */
 public static int getLastDayWeekdayOfPrevMonth(Calendar cal) {

 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.set(Calendar.DATE, 1);   // 把日期設置為當月第一天 
 tmpCal.add(Calendar.DATE, -1);   // 把日期設置為上一個月最初一天 
 return tmpCal.get(Calendar.DAY_OF_WEEK);
 } 

 /**
 * 獲得下月第一天的禮拜偏移
 * 
 * @return SUNDAY為1,MONDAY為2,順次類推。
 */
 public static int getFirstDayWeekdayOfNextMonth(Calendar cal) {

 Calendar tmpCal = (Calendar)cal.clone(); // 克隆cal。前面對tmpCal操作,就不會轉變cal
 tmpCal.add(Calendar.MONTH, 1);   // 設為“下一個月”
 tmpCal.set(Calendar.DATE, 1);   // 設為“第一天” 
 return tmpCal.get(Calendar.DAY_OF_WEEK);
 } 
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved