JDK源码(二十三):Calendar

java.util.Calendar类是一个抽象类,它提供了在特定的时间戳和一组Calendar字段之间进行转换的方法,例如年,月,日,小时等等,以及用于操作日历字段的方法,比如下星期的日期。时间的戳可以用毫秒值表示,该值是从1970年1月1日格林尼治标准时间00:00:00.000(公历)开始的偏移量。该类还提供了用于在包外实现具体日历系统的其他字段和方法。这些字段和方法被定义为protected。

Calendar对象可以生成实现特定语言和日历样式的日期时间格式所需的所有日历字段值。Calendar定义某些日历字段返回的值的范围及其含义。例如,对于所有日历,日历系统的第一个月都有值month==JANUARY。其他值由具体的子类定义。可以通过调用set方法设置日历字段值。在需要计算其时间值(从纪元开始的毫秒数)或日历字段的值之前,在日历中设置的任何字段值都不会被解释。

Calendar有两种解释日历字段的模式,容错和非容错。当日历处于容错模式时,它接受的日历字段值范围比它产生的值范围更广。当日历重新计算日历字段值以通过get()返回时,所有日历字段都将规范化。例如,容错的GregorianCalendar将MONTH=一月,DAY=32解释为二月一日。

当日历处于非容错模式时,如果日历字段中存在任何不一致,它将引发异常。例如,GregorianCalendar总是生成介于1和月长之间的DAY_OF_MONTH。如果设置了任何超出范围的字段值,则非容错的GregorianCalendar在计算其时间或日历字段值时引发异常。

类名

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

变量

/**
     * 此日历当前设置时间的日历字段值.
     */
    @SuppressWarnings("ProtectedField")
    protected int           fields[];

    /**
     * 指示是否设置了日历的指定日历字段的标志。
	 * 新对象没有设置字段。在第一次调用生成字段的方法之后,
	 * 这些字段都保持设置不变
     */
    @SuppressWarnings("ProtectedField")
    protected boolean       isSet[];

    /**
     * 指定每个字段设置时间的伪时间戳。
	 * 有两个特殊值,UNSET和COMPUTED。
	 * 从MINIMUM_USER_SET到Integer.MAX_VALUE的值是合法的用户设置值。
     */
    transient private int   stamp[];

    /**
     * 此日历的当前设置时间,
	 * 以1970年1月1日0:00:00 GMT之后的毫秒为单位。
     */
    @SuppressWarnings("ProtectedField")
    protected long          time;

    /**
     * 如果time的值有效,则为True
     */
    @SuppressWarnings("ProtectedField")
    protected boolean       isTimeSet;

    /**
     * 如果fields[]与当前设置的时间同步,则为True。
	 * 如果为false,则下一次尝试获取字段值时将强制从当前值time重新计算所有字段。
     */
    @SuppressWarnings("ProtectedField")
    protected boolean       areFieldsSet;

    /**
     * 如果已设置所有fields,则为True。
     */
    transient boolean       areAllFieldsSet;

    /**
     * 如果此日历允许在从fields[]计算时间期间字段值超出范围,则为True。
     */
    private boolean         lenient = true;

除了上面这些变量,Calendar还提供了很多时间相关的静态变量,如YEAR、MONTH、WEEK_OF_YEAR ...

实例

Calendar calendar = Calendar.getInstance();

由于Calendar是抽象类,不能使用new关键字。在getInstance()方法中会根据TimeZone时区类型和Locale地区类型创建Calendar对象。

getInstance()

public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), 
            Locale.getDefault(Locale.Category.FORMAT));
}

createCalendar(TimeZone zone, Locale aLocale)

private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
				//使用Builder创建Calendar
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
				//佛历
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
				//日本历
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
				//公历
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // 如果没有显式指定已知的日历类型,请执行创建日历的传统方法
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

获取日期

set(int field, int value)

public void set(int field, int value)
    {
        // 如果字段部分规范化,请在更改任何字段之前计算所有字段.
        if (areFieldsSet && !areAllFieldsSet) {
            computeFields();
        }
		//设置时间属性值
        internalSet(field, value);
        isTimeSet = false;
        areFieldsSet = false;
        isSet[field] = true;
		//指定每个字段设置时间的伪时间戳
        stamp[field] = nextStamp++;
        if (nextStamp == Integer.MAX_VALUE) {
			//在nextStamp溢出之前调整stamp[]值。
            adjustStamp();
        }
    }

set方法是将给定的日历字段设置为给定值,internalSet方法中只有一句,fields[field] = value;将value值赋值到fields[]属性中。例如set(Calendar.YEAR, 2019)则表示将年份设置成2019年。

get(int field)

public int get(int field)
    {
		//填写日历字段中任何未设置的字段
        complete();
		//返回field数组中的值
        return internalGet(field);
    }

get方法用来获取实例化的Calendar对象储存的年月日时分秒星期等等信息,complete方法主要是对所有日期字段的值进行计算并赋值给相应变量。方法的参数通过Calendar.XXXX的形式填写,比如要想获取年份信息就用Calendar.YEAR、月份Calendar.MONTH、日期Calendar.Date、时Calendar.HOUR、分Calendar.MINUTE、秒Calendar.SECOND等等。

add(int field, int amount)

abstract public void add(int field, int amount);

add方法根据日历的规则,向给定日历字段添加或减去指定的时间量。此方法是抽象方法,调用的时候根据生成的Calendar对象调用对应的add方法。

前一天

        Calendar calendar = Calendar.getInstance();
        Date time = calendar.getTime();
        System.out.println(time);// Fri Feb 28 20:39:10 CST 2020
        //昨天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        System.out.println(calendar.getTime());

更多精彩内容请关注微信公众号:

package com.hexiang.utils; import java.text.SimpleDateFormat; import java.util.*; public class CalendarUtil { public static void main(String args[]) { System.out.println("First day of week is : " + new SimpleDateFormat("yyyy-MM-dd") .format(getFirstDateByWeek(new Date()))); System.out.println("Last day of week is : " + new SimpleDateFormat("yyyy-MM-dd") .format(getLastDateByWeek(new Date()))); System.out.println("First day of month is : " + new SimpleDateFormat("yyyy-MM-dd") .format(getFirstDateByMonth(new Date()))); System.out.println("Last day of month is : " + new SimpleDateFormat("yyyy-MM-dd") .format(getLastDateByMonth(new Date()))); } /** * 获得所在星期的第一天 */ public static Date getFirstDateByWeek(Date date) { Calendar now = Calendar.getInstance(); now.setTime(date); int today = now.get(Calendar.DAY_OF_WEEK); int first_day_of_week = now.get(Calendar.DATE) + 2 - today; // 星期一 now.set(Calendar.DATE, first_day_of_week); return now.getTime(); } /** * 获得所在星期的最后一天 */ public static Date getLastDateByWeek(Date date) { Calendar now = Calendar.getInstance(); now.setTime(date); int today = now.get(Calendar.DAY_OF_WEEK); int first_day_of_week = now.get(Calendar.DATE) + 2 - today; // 星期一 int last_day_of_week = first_day_of_week + 6; // 星期日 now.set(Calendar.DATE, last_day_of_week); return now.getTime(); } /** * 获得所在月份的最后一天 * @param 当前月份所在的时间 * @return 月份的最后一天 */ public static Date getLastDateByMonth(Date date) { Calendar now = Calendar.getInstance(); now.setTime(date); now.set(Calendar.MONTH, now.get(Calendar.MONTH) + 1); now.set(Calendar.DATE, 1); now.set(Calendar.DATE, now.get(Calendar.DATE) - 1); now.set(Calendar.HOUR, 11); now.set(Calendar.MINUTE, 59); now.set(Calendar.SECOND, 59); return now.getTime(); } /** * 获得所在月份的第一天 * @param 当前月份所在的时间 * @return 月份的第一天 */ public static Date getFirstDateByMonth(Date date) { Calendar now = Calendar.getInstance(); now.setTime(date); now.set(Calendar.DATE, 0); now.set(Calendar.HOUR, 12); now.set(Calendar.MINUTE, 0); now.set(Calendar.SECOND, 0); return now.getTime(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐楠_01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值