【Java】Calendar-Api的使用

在 Java 中,日期和时间的处理是常见的任务之一。为了更灵活地处理日期和时间,Java 提供了 java.util.Calendar 类,它提供了一种面向对象的方式来操作日期和时间。本篇博客将详细介绍 Calendar 类的使用方法,特别是面向基础小白的读者。

目录

什么是 Calendar 类?

常量字段

获取Calendar对象

常用方法

其他方法

Calendar对象与Date对象的相互转换

实例

根据参数获取时间范围

Calendar 类使用的注意事项

总结


什么是 Calendar 类?

Calendar 类是 Java 中用于处理日期和时间的抽象类。它提供了一种独立于特定日历系统的方式来处理日期和时间。通过 Calendar 类,你可以执行许多常见的日期和时间操作,如计算日期差异、添加或减去时间单位等。

常量字段

Calendar类的常量字段是非常重要的参数,在set()、add()、get()方法中都会用到。

Calendar类中常用的常量字段如下:

常量字段说明
Calendar.ERAERA表示纪元,只能为0或1。0表示BC(“before Christ”,即公元前);1表示AD(拉丁语“Anno Domini”,即公元)。
Calendar.YEAR表示年份
Calendar.MONTH表示月份,需要加1,因为0表示1月,1表示2月,以此类推
Calendar.HOUR小时(12小时制)
Calendar.HOUR_OF_DAY一天中第几个小时(24小时制)
Calendar.MINUTE分钟
Calendar.SECOND
Calendar.MILLISECOND毫秒
Calendar.DAY_OF_YEAR一年中第几天
DAY_OF_MONTH一月中第几天
DAY_OF_WEEK一周中第几天,注意,周日是1,周一是2,...
Calendar.DATE一月中第几天,同DAY_OF_MONTH的值是一样的
Calendar.DAY_OF_WEEK_IN_MONTH当月内一周中的某天的序号
Calendar.WEEK_OF_YEAR一年中的星期数,即本年中第几个星期
Calendar.WEEK_OF_MONTH当前月中的星期数,即本月中第几个星期
Calendar.DAY_OF_WEEK_IN_MONTH当前月中的第几个星期
Calendar.AM_PMAM_PM是在中午之前还是在中午之后,在中午12点之前返回0,在中午12点(包括12点)之后返回1
Calendar.JANUARY1月
Calendar.FEBRUARY2月
Calendar.MARCH3月
Calendar.APRIL4月
Calendar.MAY5月
Calendar.JUNE6月
Calendar.JULY7月
Calendar.AUGUST8月
Calendar.SEPTEMBER9月
Calendar.OCTOBER10月
Calendar.NOVEMBER11月
Calendar.DECEMBER12月

获取Calendar对象

不需要通过new来创建Calendar对象,而是通过Calendar类的getInstance()静态方法。代码如下:

// 获取日历对象
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());// 将Date对象设置到Calendar对象中

常用方法

常用方法就是get、set和add方法,它们的API说明如下:

方法说明
int get(int field)用于获取日历字段的值,返回值是int类型,其中field参数的值可以是Calendar.YEARCalendar.MONTH等常量字段。
void set(int field, int value)将给定的日历字段设置为指定的值。
void set(int year, int month, int date)设置Calendar中的年、月、日字段
void set(int year, int month, int date, int hourOfDay, int minute)设置Calendar中的年、月、日、时、分字段
void set(int year, int month, int date, int hourOfDay, int minute, int second)设置Calendar中的年、月、日、时、分、秒字段
void add(int field, int amount)可以对指定的一个日历字段进行整数的偏移,比如在今年的日期基础上加上一年,就是明年这个时候的日期。其中amount可以为负数,可以表示如去年、上个月等。

其他方法

方法说明
boolean after(Object when)使用例如:c4.after(c3),判断c4的日期是否在c3的日期之后。传入的参数必须是Calendar对象。
boolean before(Object when)使用例如:c3.before(c4),判断c3的日期是否在c4的日期之前。传入的参数必须是Calendar对象。
boolean equals(Object obj)使用例如:c3.equals(c4),判断c3的日期是否等于c4所表示的日期。传入的参数必须是Calendar对象。
int compareTo(Calendar anotherCalendar)使用例如:c3.compareTo(c4),如果比较c3和c4,如果c3<c4则返回-1,如果c3==c4则返回0,c3>c4则返回1。
int getActualMaximum(int field)返回指定日历字段可能具有的最大值,例如:c5.getActualMaximum(Calendar.DAY_OF_MONTH),获取本月最后一天的号数。
int getActualMinimum(int field)返回指定日历字段可能具有的最小值,例如:c5.getActualMinimum(Calendar.DAY_OF_MONTH),获取本月第一天的号数。
long getTimeInMillis()返回此日历对象所表示的毫秒值。
int getFirstDayOfWeek()获取一周的第一天是什么。
TimeZone getTimeZone()获取时区。

Calendar对象与Date对象的相互转换

  • Date对象转换成Calendar对象
// Date对象转换成Calendar对象
Calendar c2 = Calendar.getInstance();
c2.setTime(new Date());
  • Calendar对象转换成Date对象
Calendar c2 = Calendar.getInstance();
// Calendar对象转换成Date对象
Date c2Date = c2.getTime();// 类似于new Date()

实例

Calendar类的实例代码如下:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @描述: Calendar 测试
 * @Author: Duys
 **/
@RunWith(SpringRunner.class)
@SpringBootTest
public class CalendarTest {


    @Test
    public void test01() {

        // 获取日历对象
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        // 获取日期字段值
        System.out.println("纪元,公元前还是公元 >>> " + calendar.get(Calendar.ERA));// 纪元,公元前还是公元
        System.out.println("年份 >>> " + calendar.get(Calendar.YEAR));// 年份
        System.out.println("月份,需要加1,因为0表示1月,1表示2月,以此类推 >>> " + calendar.get(Calendar.MONTH));// 月份,需要加1,因为0表示1月,1表示2月,以此类推
        System.out.println("小时(12小时制) >>> " + calendar.get(Calendar.HOUR));// 小时(12小时制)
        System.out.println("一天中第几个小时(24小时制) >>> " + calendar.get(Calendar.HOUR_OF_DAY));// 一天中第几个小时(24小时制)
        System.out.println("分钟 >>> " + calendar.get(Calendar.MINUTE));// 分钟
        System.out.println("秒 >>> " + calendar.get(Calendar.SECOND));// 秒
        System.out.println("毫秒 >>> " + calendar.get(Calendar.MILLISECOND));// 毫秒
        System.out.println("一年中第几天 >>> " + calendar.get(Calendar.DAY_OF_YEAR));// 一年中第几天
        System.out.println("一月中第几天 >>> " + calendar.get(Calendar.DAY_OF_MONTH));// 一月中第几天
        System.out.println("一周中第几天,注意,周日是1,周一是2,... >>> " + calendar.get(Calendar.DAY_OF_WEEK));// 一周中第几天,注意,周日是1,周一是2,...
        System.out.println("一月中第几天,同DAY_OF_MONTH的值是一样的 >>> " + calendar.get(Calendar.DATE));// 一月中第几天,同DAY_OF_MONTH的值是一样的
        System.out.println("当月内一周中的某天的序号 >>> " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));// 当月内一周中的某天的序号
        System.out.println("Calendar.WEEK_OF_YEAR=" + calendar.get(Calendar.WEEK_OF_YEAR));// 一年中的星期数,即本年中第几个星期
        System.out.println("Calendar.WEEK_OF_MONTH=" + calendar.get(Calendar.WEEK_OF_MONTH));// 当前月中的星期数,即本月中第几个星期
        System.out.println("当前月中的第几个星期 >>> " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));// 当前月中的第几个星期
        System.out.println("Calendar.AM_PM=" + calendar.get(Calendar.AM_PM));// AM_PM是在中午之前还是在中午之后,在中午12点之前返回0,在中午12点(包括12点)之后返回1
        System.out.println("1月 >>> " + Calendar.JANUARY);// 1月
        System.out.println("2月 >>> " + Calendar.FEBRUARY);// 2月
        System.out.println("3月 >>> " + Calendar.MARCH);// 3月
        System.out.println("4月 >>> " + Calendar.APRIL);// 4月
        System.out.println("5月 >>> " + Calendar.MAY);// 5月
        System.out.println("6月 >>> " + Calendar.JUNE);// 6月
        System.out.println("7月 >>> " + Calendar.JULY);// 7月
        System.out.println("8月 >>> " + Calendar.AUGUST);// 8月
        System.out.println("9月 >>> " + Calendar.SEPTEMBER);// 9月
        System.out.println("10月 >>> " + Calendar.OCTOBER);// 10月
        System.out.println("11月 >>> " + Calendar.NOVEMBER);// 11月
        System.out.println("12月 >>> " + Calendar.DECEMBER);// 12月

        // 设置日期字段值
        calendar.set(2021, Calendar.JUNE, 3);// 设定指定年月日,其中Calendar.JUNE为5实际上是六月,所以0表示1月,1表示2月,以此类推
        System.out.println("设定指定年月日 >>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));
        calendar.set(2021, Calendar.FEBRUARY, 3, 23, 55);// 设置年月日时分
        System.out.println("设置年月日时分 >>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));
        calendar.set(2021, Calendar.MARCH, 3, 23, 55, 30);// 设置年月日时分秒
        calendar.set(Calendar.YEAR, 2005);// 单独设置日历字段,设置年份
        calendar.set(Calendar.MONTH, 7);// 单独设置日历字段,设置月份,注意0代表1月
        calendar.set(Calendar.DATE, 11);// 单独设置日历字段,设置天数
        calendar.set(Calendar.HOUR_OF_DAY, 22);// 单独设置日历字段,设置小时
        calendar.set(Calendar.MINUTE, 45);// 单独设置日历字段,设置分钟
        calendar.set(Calendar.SECOND, 30);// 单独设置日历字段,设置秒
        calendar.set(Calendar.MILLISECOND, 235);// 单独设置日历字段,设置毫秒
        System.out.println("单独设置日历字段 >>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));

        // 计算日期字段值,既可以为正数,又可以为负数
        calendar.add(Calendar.YEAR, 2);// 在当前日期的基础上添加年份,后年
        System.out.println("在当前日期的基础上添加年份,后年 >>>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));
        calendar.add(Calendar.YEAR, -1);// 在当前日期的基础上减去年份,昨年
        System.out.println("在当前日期的基础上减去年份,昨年 >>>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));
        calendar.add(Calendar.MONTH, 1);// 添加月份,下个月
        calendar.add(Calendar.MONTH, -1);// 添加月份,上个月
        calendar.add(Calendar.DATE, 2);// 添加天数,后天
        calendar.add(Calendar.DATE, -1);// 添加天数,昨天
        calendar.add(Calendar.HOUR_OF_DAY, 1);// 添加小时,下一个小时
        calendar.add(Calendar.HOUR_OF_DAY, -1);// 添加小时,上一个小时
        calendar.add(Calendar.MINUTE, 20);// 添加分钟,下20分钟
        calendar.add(Calendar.MINUTE, -20);// 添加分钟,上20分钟
        calendar.add(Calendar.SECOND, 30);// 添加秒数,下30秒
        calendar.add(Calendar.SECOND, -30);// 添加秒数,上30秒
        calendar.add(Calendar.DATE, 7);// 添加周数,即添加7天,下一周
        calendar.add(Calendar.DATE, -7);// 添加周数,上一周
        System.out.println("添加 >>>> " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(calendar.getTime()));

        // Calendar对象与Date对象的相互转换
        // Date对象转换成Calendar对象
        Calendar c2 = Calendar.getInstance();
        c2.setTime(new Date());
        // Calendar对象转换成Date对象
        Date c2Date = c2.getTime();// 类似于new Date()

        // 其他方法,如after、before
        Calendar c3 = Calendar.getInstance();
        c3.set(Calendar.YEAR, 2005);
        Calendar c4 = Calendar.getInstance();
        boolean after = c4.after(c3);// 判断c4的日期是否在c3之后
        System.out.println(after);
        boolean before = c3.before(c4);
        System.out.println(before);// 判断c3的日期是否在c4之前
        boolean equals = c3.equals(c4);// 判断c3的日期是否等于c4
        System.out.println(equals);
        int result = c3.compareTo(c4);// 如果比较c3和c4,如果c3<c4则返回-1,如果c3==c4则返回0,c3>c4则返回1
        System.out.println(result);

        Calendar c5 = Calendar.getInstance();
        c5.clear();
        c5.set(Calendar.YEAR, 2017);
        c5.set(Calendar.MONTH, 1);
        c5.set(Calendar.DAY_OF_MONTH, 30);
        System.out.println(c5.getTime());
        int lastDay = c5.getActualMaximum(Calendar.DAY_OF_MONTH);// 获取本月最后一天的号数
        int firstDay = c5.getActualMinimum(Calendar.DAY_OF_MONTH);// 获取本月第一天的号数
        System.out.println("本月最后一天:" + lastDay + ", 本月第一天:" + firstDay);

        // 获取毫秒数
        long timeInMillis = calendar.getTimeInMillis();// 返回此Calendar的时间值,以毫秒为单位
        int firstDayOfWeek = calendar.getFirstDayOfWeek();// 获取一个星期中的第一天
        System.out.println("获取一个星期中的第一天 >>> " + firstDayOfWeek);
        TimeZone timeZone = calendar.getTimeZone();// 获取时区
        System.out.println("获取时区 >>> " + timeZone.getDisplayName());

    }


}



日志输出:
纪元,公元前还是公元 >>> 1
年份 >>> 2023
月份,需要加1,因为0表示1月,1表示2月,以此类推 >>> 10
小时(12小时制) >>> 11
一天中第几个小时(24小时制) >>> 11
分钟 >>> 29
秒 >>> 8
毫秒 >>> 512
一年中第几天 >>> 332
一月中第几天 >>> 28
一周中第几天,注意,周日是1,周一是2,... >>> 3
一月中第几天,同DAY_OF_MONTH的值是一样的 >>> 28
当月内一周中的某天的序号 >>> 4
Calendar.WEEK_OF_YEAR=48
Calendar.WEEK_OF_MONTH=5
当前月中的第几个星期 >>> 4
Calendar.AM_PM=0
1月 >>> 0
2月 >>> 1
3月 >>> 2
4月 >>> 3
5月 >>> 4
6月 >>> 5
7月 >>> 6
8月 >>> 7
9月 >>> 8
10月 >>> 9
11月 >>> 10
12月 >>> 11
设定指定年月日 >>> 2021-06-03 11:29:08
设置年月日时分 >>> 2021-02-03 11:55:08
单独设置日历字段 >>> 2005-08-11 10:45:30
在当前日期的基础上添加年份,后年 >>>> 2007-08-11 10:45:30
在当前日期的基础上减去年份,昨年 >>>> 2006-08-11 10:45:30
添加 >>>> 2006-08-12 10:45:30
true
true
false
-1
Thu Mar 02 00:00:00 CST 2017
本月最后一天:31, 本月第一天:1
获取一个星期中的第一天 >>> 1
获取时区 >>> 中国标准时间

根据参数获取时间范围

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @描述:
 * @Author: Duys
 **/
@Slf4j
@Component
public class ReqParamUtil {


    /**
     * @描述: 根据day, hour, min获取时间段
     **/
    public static Map<String, String> requestTime(int day, int hour, int min) {
        /**请求时间**/
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, -day);
        /* HOUR_OF_DAY 指示一天中小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - hour);
        /* MINUTE 指示一天中的某分 */
        calendar.set(Calendar.MINUTE, (calendar.get(Calendar.MINUTE) - min));
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.info("beginTime: " + df.format(calendar.getTime()));
        log.info("endTime: " + df.format(new Date()));
        Map<String, String> map = new HashMap<>(2);
        map.put("beginTime", df.format(calendar.getTime()));
        map.put("endTime", df.format(new Date()));

        return map;
    }

}

Calendar 类使用的注意事项

在使用 Calendar 类时,需要注意以下一些使用注意事项,以确保日期和时间的操作正确、安全,避免潜在的问题:

  1. 月份从0开始:Calendar 类中的月份是从0开始的,即0表示一月,1表示二月,以此类推,11表示十二月。这与人们通常的月份表示方式不同,要格外注意月份的设置和获取。
  2. 时区和区域设置:Calendar 类的行为受到默认时区和区域设置的影响。在涉及跨时区操作时,应该特别注意时区的设置,以避免出现意外的偏移。
  3. 线程安全性:Calendar 类不是线程安全的,因此在多线程环境下使用时需要额外小心。通常情况下,最好将 Calendar 对象限定在单个线程内,或使用线程安全的日期和时间库,如 java.time(Java 8及更高版本引入)。
  4. 日期和时间范围:Calendar 类的日期和时间范围受到系统实现的限制。例如,一些操作系统可能无法表示某些日期(特别是在1970年之前或2038年之后),因此在处理非常早期或非常晚期的日期时要格外小心。
  5. 月份的天数:要谨慎处理月份的天数,不同月份的天数是不同的,如果不考虑这一点可能会导致日期计算的错误。
  6. 避免魔法数值:在代码中避免硬编码日期和时间的数值,而是使用 Calendar 常量和方法来表示日期和时间部分,以提高可读性和可维护性。
  7. 异常处理:在进行日期和时间计算时,要格外小心异常情况,如日期不存在、时间超出范围等。在必要的情况下,要使用异常处理机制来处理这些情况,以确保程序的稳定性。
  8. 不建议使用:Java 8 引入了新的日期和时间 API(java.time 包),如 LocalDate、LocalTime 和 ZonedDateTime 等类,这些类更简单、更安全,推荐在新项目中使用。Calendar 类在新 API 出现后逐渐被淘汰,不建议在新项目中使用。

总结

Calendar 类是 Java 中用于处理日期和时间的重要工具之一。通过创建 Calendar 对象,你可以获取和设置日期和时间的各个部分,执行日期和时间的计算,以及计算日期差异。然而,需要注意的是,Calendar 类的使用可能较为繁琐,而且并不是线程安全的。在 Java 8 之后,引入了新的日期和时间 API(java.time 包),提供了更好的日期和时间处理方式,推荐在新项目中使用。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值