当前位置:天才代写 > tutorial > JAVA 教程 > Java时间相关内容进修(1) Calendar

Java时间相关内容进修(1) Calendar

2017-11-02 08:00 星期四 所属: JAVA 教程 浏览:62

副标题#e#

Java 操纵日期/时间,往往会涉及到Calendar,Date,DateFormat这些类。

最近抉择把这些内容系统的整理一下,这样今后利用的时候,会更驾轻就熟。本章的内容是主要讲授“Java时间框架”以及“类Calendar”。

在进修Calendar类时,我们先对它有个整体认识,心中成立一个框架,然后再通过示例进修如何利用它。

Java 时间架构图

Java 的Calendar, Date和DateFormat的干系图如下:

Java时间相关内容学习(1) Calendar

说明:

(01) milliseconds 暗示毫秒。

milliseconds = “实际时间” – “1970-01-01 00:00:00”。Calendar 和 Date依赖于 milliseconds,从而暗示时间。

(02) Calendar暗示日期/时间。

它是一个抽象类,依赖于milliseconds。GregorianCalendar是Calendar的子类,凡是我们通过Calendar.getInstance() 获取Calendar实例时,实际上返回的是 GregorianCalendar 工具。

Calendar和Locale关联,而Locale代表区域;Locale的值差异时,Calendar的日期/时间也差异。

Calendar和TimeZone关联,而TimeZone代表时区;差异的时区,Calendar的日期/时间也差异。

(03) Date 暗示日期/时间。

它也依赖于 milliseconds实现。

在 JDK 1.1 之前,凡是是通过Data操纵“年代日时分秒”。不外,由于Date的相关 API 不易于实现国际化。从 JDK 1.1 开始,应该利用 Calendar 类来操纵“年代日时分秒”,同时可以通过 DateFormat 类来名目化息争析日期字符串。Date 中的相应要领已废弃。

(04) DateFormat是名目化/理会“日期/时间”的东西类。

它是Date的名目化东西,它能辅佐我们名目化Date,进而将Date转换成我们想要的String字符串供我们利用。

它是一个抽象类。凡是,我们通过getInstance(), getDateInstance()和getDateTimeInstance() 等获取DateFormat实例时;实际上是返回的SimpleDateFormat工具。

Calendar 先容

Calendar 界说

publicabstractclass 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提供的一些列要领来操纵日历。


#p#副标题#e#

Calendar 道理和思想

我们利用Calendar,无非是操纵Calendar的“年、月、日、礼拜、时、分、秒”这些字段。下面,我们对这些字段的的来历、界说以及计较要领举办进修。

1. Calendar 各个字段值的来历

#p#分页标题#e#

我们利用Calendar,无非是利用“年、月、日、礼拜、时、分、秒”等信息。那么它是如何做到的呢? 本质上,Calendar就是生存了一个时间。如下界说:

// time 是当前时间,单元是毫秒。
// 它是当前时间间隔“January 1, 1970, 0:00:00 GMT”的差值。
protectedlong 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个字段数据”的数组。

#p#副标题#e#

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字段的值”。

#p#分页标题#e#

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);
}

#p#副标题#e#

下面,我们看看internalGet(field)的界说。如下:

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

#p#分页标题#e#

从中,我们就看出,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() 的区别。参考下面的比拟示例,

#p#分页标题#e#

(01) getMaximum() 获取的“字段最大值”,是指在综合所有的日期,在所有这些日期中得出的“字段最大值”。譬喻,getMaximum(Calendar.DATE)的目标是“获取‘日的最大值’”。综合所有的日期,得出一个月最多有31天。因此,getMaximum(Calendar.DATE)的返回值是“31”! (02) 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);

说明: (01) 1988 是想要配置的MONTH的当前值。这个配置值必需是整数。 (02) 若要配置其它字段的当前值,只需要将示例中的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);

说明: (01) -10 是添加值。      添加值可觉得正数,也可以是负数。      正数暗示将日期增加,负数暗示将日期淘汰。

    假设:此刻cal的值是“2013-09-01”,此刻我们将MONTH字段值增加-10。获得的功效是:“2012-10-01”。             为什么会这样呢?“2013-09-01”增加-10,也就是将日期向前淘汰10个月;获得的功效就是“2012-10-01”。 (02) Calendar的17个字段中:除了回滚Calendar.ZONE_OFFSET时,会抛出IllegalArgumentException异常;其它的字段都支持该操纵。 (03) 若要配置其它字段的当前值,只需要将示例中的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);

说明: (01) -10 是回滚值。     当回滚值是负数时,暗示将当前字段向前滚;     当回滚值是正数时,暗示将当前字段向后滚。

#p#分页标题#e#

    回滚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”。 (02) Calendar的17个字段中:除了回滚Calendar.ZONE_OFFSET时,会抛出IllegalArgumentException异常;其它的字段都支持该操纵。 (03) 若要配置其它字段的当前值,只需要将示例中的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相应的替换成其它字段名即可。

#p#副标题#e#

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。 (01) 当 Calendar 处于 lenient 模式时,它可接管比它所生成的日历字段范畴更大范畴内的值。当 Calendar 从头计较日历字段值,以便由 get() 返回这些值时,所有日历字段都被尺度化。      譬喻,lenient 模式下的 GregorianCalendar 将 MONTH == JANUARY、DAY_OF_MONTH == 32 表明为 February 1。 (02) 当 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() 函数。

#p#分页标题#e#

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;
     
/**
 * Calendar的API测试措施
 *
 * @author skywang 
 * @email [email protected]
 */
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 -- 标题
     * @author skywang ([email protected])
     */
    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 {
            // 增加“字段的当前值” ,并获取“新的当前字段值”
			// 来自http://www.bianceng.cn
            // 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个字段的民众函数接口”
     *
     * @author skywang ([email protected])
     */
    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的“较量接口”
     *
     * @author skywang ([email protected])
     */
    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的“较量接口”
     *
     * @author skywang ([email protected])
     */
    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等相关函数
     *
     * @author skywang ([email protected])
     */
    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()等接口
     *
     * @author skywang ([email protected])
     */
    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());
    }
}

 

    关键字:


天才代写-代写联系方式