Java中的Calendar日历API用法完全解析
第一部分 Calendar介绍 public abstract class Calendar implements Serializable,Cloneable,Comparable<Calendar> {} Calendar 可以看作是一个抽象类。 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的原理和思想 // time 是当前时间,单位是毫秒。 // 它是当前时间距离“January 1,1970,0:00:00 GMT”的差值。 protected long time; Calendar就是根据 time 计算出 “Calendar的年、月、日、星期、时、分、秒”等等信息。 2. Calendar 各个字段的定义和初始化 // 保存这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 各个字段值的计算 public int get(int field) { // 计算各个字段的值 complete(); // 返回field字段的值 return internalGet(field); } 说明:get(int field)的代码很简单。先通过 complete() 计算各个字段的值,然后在通过 internalGet(field) 返回“field字段的值”。 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(),fieldMask); } else if (year < gregorianCutoverYear && year < gregorianCutoverYearJulian) { jfd = fixedDate + getFixedDate(getJulianCalendarSystem(),fieldMask); if (jfd < gregorianCutoverDate) { fixedDate = jfd; break calculateFixedDate; } gfd = fixedDate + getFixedDate(gcal,fieldMask); } else { gfd = fixedDate + getFixedDate(gcal,fieldMask); jfd = fixedDate + getFixedDate(getJulianCalendarSystem(),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,fields,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)来返回值的。 第三部分 Calendar函数接口 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 获取MONTH的最大值 int max = cal.getMaximum(Calendar.MONTH); 若要获取其它字段的最大值,只需要将示例中的MONTH相应的替换成其它字段名即可。 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 获取当前MONTH的最大值 int max = cal.getActualMaximum(Calendar.MONTH); 若要获取其它字段的最大值,只需要将示例中的MONTH相应的替换成其它字段名即可。 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 获取MONTH的最小值 int min = cal.getMinimum(Calendar.MONTH); 若要获取其它字段的最小值,只需要将示例中的MONTH相应的替换成其它字段名即可。 作用:获取“当前日期下,该字段的最小值”。 示例:以“MONTH”字段来说。使用方法为: // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 获取MONTH的最小值 int min = cal.getMinimum(Calendar.MONTH); 若要获取其它字段的最小值,只需要将示例中的MONTH相应的替换成其它字段名即可。 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 获取“cal日历”的当前MONTH值 int MONTH = cal.get(Calendar.MONTH); 若要获取其它字段的当前值,只需要将示例中的MONTH相应的替换成其它字段名即可。 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 设置“cal日历”的当前MONTH值为 1988年 cal.set(Calendar.MONTH,1988); 说明: // 获取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); 说明: // 获取Calendar实例,并设置日期为“2013-09-01” Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR,1); // 将“cal日历”的当前MONTH值 “向前滚动10” cal.roll(Calendar.MONTH,-10); 说明: // 获取Calendar实例,并设置日期为“9月” Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH,9); // 清空MONTH cal.clear(Calendar.MONTH); 若要清空其它字段,只需要将示例中的MONTH相应的替换成其它字段名即可。 // 获取Calendar实例 Calendar cal = Calendar.getInstance(); // 判断MONTH是否被设置 boolean bset = cal.isSet(Calendar.MONTH); 若要判断其它字段,只需要将示例中的MONTH相应的替换成其它字段名即可。 2. 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() 函数。 // 它们的使用方法如下 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() 函数。 // 设置“年月日” final void set(int year,int month,int day) // 设置“年月日时分” final void set(int year,int day,int hourOfDay,int minute,int second) // 设置“年月日时分秒” final void set(int year,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() 函数。 // 克隆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使用示例 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:ntrange is [%d - %d] actualRange is [%d - %d]. original=%d,set(%d)=%d,roll(%d)=%d,add(%d)=%dn",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"); // 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"); // 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=%sn",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=%sn",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,9,9); // 设置时间为“2000-10-10 10:10:10” cal.set(2000,10,10); System.out.printf("ntestTimeAPIs: date=%s,timezone=%s,millis=%sn",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)} %sn",firstdayOfWeek,m1,index1,m2,index2,clone.getTime()); } } 第五部分 自定义的Calendar接口示例 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: %sn",getYear(cal) ); // 获取“月” System.out.printf("month: %sn",getMonth(cal) ); // 获取“上月” System.out.printf("previcou month: %sn",getLastMonth(cal) ); // 获取“下月” System.out.printf("next month: %sn",getNextMonth(cal) ); // 获取“日” System.out.printf("day: %sn",getDay(cal) ); // 获取Cal对应星期几 System.out.printf("weekday: %sn",getWeekDay(cal) ); // 本月天数 System.out.printf("Current Month days: %sn",getMonthDays(cal) ); // 上月天数 System.out.printf("Previcous Month days: %sn",getPrevMonthDays(cal) ); // 下月天数 System.out.printf("Next Month days: %sn",getNextMonthDays(cal) ); // 获取当月第一天的星期几 System.out.printf("First day' weekday : %sn",getFirstDayWeekday(cal) ); // 获取当前月最后一天的星期几 System.out.printf("Last day' weekday : %sn",getLastDayWeekday(cal) ); // 获取上月最后一天的星期几 System.out.printf("PrevMonth Last day' weekday: %sn",getLastDayWeekdayOfPrevMonth(cal) ); // 获取下月第一天的星期几 System.out.printf("NextMonth First day' weekday: %sn",getFirstDayWeekdayOfNextMonth(cal) ); } /** * 获取“年” * * @return 例如,2013-09-18,则返回2013 */ public static int getYear(Calendar cal) { return cal.get(Calendar.YEAR); } /** * 获取“月” * * @return 返回值可以为以下值: * JANUARY,UNDECIMBER。 * 其中第一个月是 JANUARY,它为 0。 * * 例如,2013-09-18,则返回8 */ public static int getMonth(Calendar cal) { return cal.get(Calendar.MONTH); } /** * 获取“上一个月” * * @return 返回值可以为以下值: * JANUARY,UNDECIMBER。 * 其中第一个月是 JANUARY,它为 0。 * * 例如,2012-01-12的上一个月是“11”(即DECEMBER)。 */ public static int getLastMonth(Calendar cal) { return (cal.get(Calendar.MONTH) + 11) % 12; } /** * 获取“下一个月” * * @return 返回值可以为以下值: * JANUARY,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); } } 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- data-annotations – 为什么AutoFixture不使用StringLength
- java – Eclipse中“链接到编辑器”功能是什么?
- 重构此Java代码,检查String是否包含任何这些可能性?
- SpringBoot与velocity的结合的示例代码
- java – 简单的方法来启动一个独立的JNDI服务器(并注册一些
- java创建简易视频播放器
- java – 密码保护的应用程序在tomcat中
- 深入探索Spring Data JPA, 从Repository 到 Specificatio
- java – 如何使用Json-Simple从JSON解析为Map并保留键顺序
- java设计模式学习之装饰模式