8.算法竞赛中的常用JAVA API :Calendar日期类

摘要

在蓝桥杯中有关于日期计算的问题,正好java中的Date类和Calendar类提供了对日期处理的一些方法。Date类大部分方法已经废弃了,所以本文将详细介绍Calendar类。

Calendar类

Calendar 类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。

瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。

常用的日历字段

  • YEAR 指示年的 get 和 set 的字段数字。

  • MONTH 指示月份的 get 和 set 的字段数字。

  • DAY_OF_MONTH get 和 set 的字段数字, 指示一个月中的某天。

  • DAY_OF_WEEK get 和 set 的字段数字, 指示一个星期中的某天。

  • DAY_OF_YEAR get 和 set 的字段数字, 指示当前年中的天数。

  • DAY_OF_WEEK_IN_MONTH get 和 set 的字段数字, 指示当前月中的第几个星期。

  • HOUR get 和 set 的字段数字,指示当天中的某小时

  • MINUTE get 和 set 的字段数字,指示当前小时中的某分钟

  • SECOND get 和 set 的字段数字,指示当前分钟中的某秒

    time 以毫秒为单位,表示自格林威治标准时间 1970 年 1月 1 日 0:00:00 后经过的时间。

    (字段就是Calendar类的成员变量,用于存储当前日历的年月日等时间信息。

Calendar类的实例化

来看Calendar的声明:

  1. public abstract class Calendar
  2. extends Objectimplements Serializable, Cloneable, Comparable<Calendar>{}

该类被abstract所修饰,说明不能通过new的方式来获得实例,对此,Calendar提供了一个类方法getInstance,以获得此类型的一个通用的对象,getInstance方法返回一个Calendar对象(该对象为Calendar的子类对象),其日历字段已由当前日期和时间初始化:

getInstance();//返回一个默认时区和语言环境的日历

  1. Calendar calendar = Calendar.getInstance();//赋值给calendar

之所以说返回的是Calendar的子类对象,是因为每个国家地区都有自己的一套日历算法,比如西方国家的第一个星期大部分为星期日,而中国则为星期一。我们来看看getInstance方法获取实例的源码:

  1. public static Calendar getInstance(){
  2. Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
  3. cal.sharedZone = true;
  4. return cal;
  5. }

设置特定日期

set(int field, int value);//第一个参数是日期字段,诸如YEAR、MONTH 等将给定的日历字段设置为给定值。

set(int year, int month, int date)// 设置日历字段年月日的值

  1. Calendar calendar = Calendar.getInstance();//创建个实例
  2. int year = 2020;
  3. int month = 1;//1是二月 0是1月
  4. int day = 1;
  5. calendar.set(Calendar.YEAR, year);// 将year的值赋给calender的YEAR字段
  6. calendar.set(Calendar.MONTH, month);//将month的值赋给calender的MONTH字段
  7. calendar.set(Calendar.DAY_OF_MONTH, day);//将day的值赋值给calendder的DAT_OF_MONTH字段
  8. //以上就完成了对calender的字段设置。

获取当前Calender实例的字段信息

get(int field);// 获取给定字段的值

  1. Calendar calendar = Calendar.getInstance();
  2. // 设置日期为: 2020.1.21
  3. calendar.set(Calendar.YEAR, 2020);
  4. calendar.set(Calendar.MONTH, 0);//月份从0开始。
  5. calendar.set(Calendar.DAY_OF_MONTH, 21);
  6. // 获取2020.1.21是星期几
  7. System.out.print(calendar.get(Calendar.DAY_OF_WEEK));
  8. 输出:
  9. 3 // 3代表星期二

注意事项

  1. 在获取月份时,Calendar.MONTH + 1 的原因

Java中的月份遵循了罗马历中的规则:当时一年中的月份数量是不固定的,第一个月是JANUARY。而Java中Calendar.MONTH返回的数值其实是当前月距离第一个月有多少个月份的数值,所以月份为JANUARY在Java中返回“0”,依次类推也就是在取Calendar.MONTH的值时我们需要+1。

  1. 在获取星期几 Calendar.DAY_OF_WEEK – 1 的原因

Java中Calendar.DAY_OF_WEEK其实表示:一周中的第几天,所以他会受到 第一天是星期几 的影响。

有些地区以星期日作为一周的第一天,而有些地区以星期一作为一周的第一天,这2种情况是需要区分的。

看下表的返回值

所以Calendar.DAY_OF_WEEK需要根据本地化设置的不同而确定是否需要 “-1”

Java中设置不同地区的输出可以使用 Locale.setDefault(Locale.地区名) 来实现。

3. 获取日期时 Calendar.DAY_OF_MONTH 不需要特殊的操作,他直接返回一个月中的第几天


1.获取时间

  1. import java.text.SimpleDateFormat;
  2. import java.util.Calendar;
  3. public class CalenderTest {
  4. //获取时间:以目前系统时间 :2019:01:27 16:27:27 为例
  5. @Test
  6. public void testGetCalender() {
  7. Calendar cal = Calendar.getInstance(); //Calendar类的实例化
  8. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //时间的格式化
  9. //当前系统时间
  10. Date date = cal.getTime(); //date=Sun Jan 27 16:27:27 CST 2019
  11. String nowTime = sdf.format(cal.getTime()); //nowTime=2019-01-27 16:27:27
  12. //当前年
  13. int year = cal.get(Calendar.YEAR); //year=2019
  14. //当前月 Calendar.MONTH从0开始 ,使用时通常会+1
  15. int month = cal.get(Calendar.MONTH) + 1; //month=1
  16. //当前日:两种方法等价
  17. int day_of_month = cal.get(Calendar.DAY_OF_MONTH); //day_of_month=27
  18. int day = cal.get(Calendar.DATE); //day=27
  19. //获取当月day的最大值!!
  20. int max_day_of_month = cal.getActualMaximum(Calendar.DAY_OF_MONTH); //max_day_of_month=31
  21. //当前时钟:24小时制
  22. int hour24 = cal.get(Calendar.HOUR_OF_DAY); //hour24=16
  23. //当前时钟:12小时制
  24. int hour12 = cal.get(Calendar.HOUR); //hour12=4
  25. //当前:分钟
  26. int minute = cal.get(Calendar.MINUTE); //minute=27
  27. //当前秒
  28. int second = cal.get(Calendar.SECOND); //second=27
  29. //星期几:用数字(1~7)表示(星期日~星期六),使用时通常会-1
  30. int day_of_week = cal.get(Calendar.DAY_OF_WEEK) - 1; //day_of_week=0
  31. //上午-0;下午-1
  32. int amOrPm = cal.get(Calendar.AM_PM); //amOrPm=1
  33. //当前年的第几周
  34. int week_of_year = cal.get(Calendar.WEEK_OF_YEAR); //week_of_year=5
  35. //当前月的星期数
  36. int week_of_month = cal.get(Calendar.WEEK_OF_MONTH); //week_of_month=5
  37. //当前月中的第几个星期
  38. int day_of_week_in_month = cal.get(Calendar.DAY_OF_WEEK_IN_MONTH); //day_of_week_in_month=4
  39. //当前年的第几天
  40. int day_of_year = cal.get(Calendar.DAY_OF_YEAR); //day_of_year=27
  41. }
  42. }

2. 设置时间

  1. import java.text.SimpleDateFormat;
  2. import java.util.Calendar;
  3. public class CalenderTest {
  4. //设置时间:以目前系统时间 :2019:01:27 16:27:27 为例
  5. @Test
  6. public void testSetCalender() {
  7. Calendar cal = Calendar.getInstance(); //Calendar类的实例化
  8. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //时间的格式化
  9. //1.当前系统时间
  10. Date date = cal.getTime(); //data=Sun Jan 27 16:27:27 CST 2019
  11. String nowTime = sdf.format(cal.getTime()); //nowTime=2019-01-27 16:27:27
  12. //2.设置时间:不设置项,默认Calendar已经存在日期
  13. cal.set(Calendar.HOUR_OF_DAY, 11);
  14. cal.set(Calendar.MINUTE, 30);
  15. cal.set(Calendar.SECOND, 30);
  16. String date1 = sdf.format(cal.getTime()); //time=2019-01-27 11:30:30
  17. //3.设置时间:全部设置,则输出自定义时间
  18. cal.set(Calendar.YEAR, 2018);
  19. cal.set(Calendar.MARCH, 7);
  20. cal.set(Calendar.DATE, 21);
  21. String date2 = sdf.format(cal.getTime()); //time=2018-08-21 11:30:30
  22. //4.时间重置:Date date = new date();
  23. String newDate1 = sdf.format(cal.getTime()); //newDate1=2018-08-21 11:30:30
  24. String newDate2 = sdf.format(new Date()); //newDate2=2019:01:27 16:27:27
  25. }
  26. }

3. 时间运算

  1. import java.text.SimpleDateFormat;
  2. import java.util.Calendar;
  3. public class CalenderTest {
  4. //时间运算:以目前系统时间 :2019:01:27 16:27:27 为例
  5. @Test
  6. public void testAddCalender() {
  7. Calendar cal = Calendar.getInstance(); //Calendar类的实例化
  8. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //时间的格式化
  9. String nowTime = sdf.format(cal.getTime()); //nowTime=2019-01-27 16:27:27
  10. cal.add(Calendar.YEAR, 1);
  11. String time1 = sdf.format(cal.getTime()); //年:2020-01-27 16:27:27
  12. cal.add(Calendar.MONTH, 2);
  13. String time2 = sdf.format(cal.getTime()); //月:2020-03-27 16:27:27
  14. cal.add(Calendar.DATE, 5);
  15. String time3 = sdf.format(cal.getTime()); //日:2020-04-01 16:27:27
  16. cal.add(Calendar.HOUR_OF_DAY, -1);
  17. String time4 = sdf.format(cal.getTime()); //时:2020-04-01 15:27:27
  18. cal.add(Calendar.MINUTE, 1);
  19. String time5 = sdf.format(cal.getTime()); //分:2020-04-01 15:28:27
  20. cal.add(Calendar.SECOND, 1);
  21. String time6 = sdf.format(cal.getTime()); //秒:2020-04-01 15:27:28
  22. }
  23. }

注意事项

1. Calendar的容错性

我们直接举例说明:

调用Calendar对象的set()方法改变指定时间字段的值时,有可能传入一个不合法的参数,例如:为MONTH字段设置13,这将会导致什么结果呢?

  1. //Calendar:容错性测试
  2. @Test
  3. public void testCalender() {
  4. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  5. Calendar calendar = Calendar.getInstance();
  6. // Calendar容错性:true-打开;false-关闭
  7. calendar.setLenient(false);
  8. calendar.set(Calendar.MONTH, 13);
  9. System.out.println("A="+simpleDateFormat.format(calendar.getTime())); // A标记
  10. }

当打开calendar.setLenient(true)时(默认):

A处代码可以正常运行,因为将MONTH字段设置为13,将会使YEAR字段计算加1;

输出结果:A=2020-02-12 13:59:33。

当关闭calendar.setLenient(false)时:

A处将会导致运行异常,因为设置的MONTH字段超出了所允许的范围。

关键在于程序中注释有“容错性”的代码行:

Calendar提供一个setLenient用于设置它的容错性,Calendar默认支持比较好的容错性,通过setLenient(false)关闭Calendar的容错性,让它进行严格的参数检查。

Calendar有两种解释日历字段的模式:lenient模式,non-lenient模式

当处于lenient模式时,每个字段都可接受超出范围的值;

当处于non-lenient模式时,每个字段都进行严格的参数检查,不接收超出字段的值。

2.set()的延迟性

set(int field, int value)方法日历的某个字段修改为value值,此外它还设置了一个内部成员变量,以指示日历字段field已经被更改。尽管日历字段field是立即更改的,但该Calendar所代表的事件却不会立即修改,直到下次调用get()、getTime()、getTimeInMillis()、add()或roll()时才会重新计算日历的时间。

这被称为set()方法的延迟修改,采用延迟修改的优势是多次调用set()不会触发多次不必要的运算,下面来看一个例子:

  1. // set():延迟修改性
  2. @Test
  3. public void testCalender1() {
  4. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  5. Calendar calendar = Calendar.getInstance();
  6. calendar.set(2019, 2, 31);
  7. calendar.set(Calendar.MONTH, 8);
  8. //包含getTime()方法,注释掉此行代码,运行结果截然不同
  9. System.out.println("A="+simpleDateFormat.format(calendar.getTime())); // A标记
  10. calendar.set(Calendar.DATE, 5);
  11. System.out.println("B="+simpleDateFormat.format(calendar.getTime())); // B标记
  12. }

打印结果:

  • 注释掉 A行 之前:(set一次,get一次,一步一运算)

    A=2019-10-01 13:27:55

    B=2019-10-05 13:27:55
  • 注释掉 A行 之后:(set两次,get一次,最后再运算)

    B=2019-09-05 13:33:21

小结

  1. Calendar 类区分不同的时区输出时间格式;

  2. Calendar 类的计算优势非常明显,不需要考虑每个月有多少天,非常便利。举个例子:如果要计算昨天的日期,你要考虑昨天是不是某月的最后一天,某年的最后一天,要考虑平年、闰年,考虑上个月是31天,30天,29天还是28天…但是Calendar类省去了你所有的顾虑,直接减1天就可以输出正确的日期了;

  3. Calendar 类使用时要注意它的容错性和延迟性。

注: 转载于 https://blog.csdn.net/GD_ONE/article/details/104061292

https://blog.csdn.net/weixin_44259720/article/details/86669177

8.算法竞赛中的常用JAVA API :Calendar日期类的更多相关文章

  1. 6.算法竞赛中的常用JAVA API :Math类(转载)

    6.算法竞赛中的常用JAVA API :Math类 求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double ...

  2. 算法竞赛中的常用JAVA API :大数类(转载)

    5.算法竞赛中的常用JAVA API :大数类 摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1 对应的十进制数是9223372036854775807(long类型的最大 ...

  3. 算法竞赛中的常用JAVA API:PriorityQueue(优先队列)(转载)

    算法竞赛中的常用JAVA API:PriorityQueue(优先队列) PriorityQueue 翻译过来就是优先队列,本质是一个堆, 默认情况下堆顶每次都保留最小值,每插入一个元素,仍动态维护堆 ...

  4. 算法竞赛中的常用JAVA API :HashSet 和 TreeSet(转载)

    算法竞赛中的常用JAVA API :HashSet 和 TreeSet set set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E ...

  5. 算法竞赛中的常用JAVA API :HashMap 和 TreeMap(转载)

    算法竞赛中的常用JAVA API :HashMap 和 TreeMap 摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实 ...

  6. 7.算法竞赛中的常用JAVA API :String 、StringBuilder、StringBuffer常用方法和区别(转载)

    7.算法竞赛中的常用JAVA API :String .StringBuilder.StringBuffer常用方法和区别 摘要 本文将介绍String.StringBuilder类的常用方法. 在j ...

  7. 常用Java API:大数类

    摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1, 对应的十进制数是9223372036854775807,也就是说只要运算过程中会超过这个数,就会造成数据溢出,从而造成错 ...

  8. 常用Java API:Math类

    求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double a, doubleb) Math.min(long ...

  9. 常用JAVA API :String 、StringBuilder、StringBuffer的常用方法和区别

    摘要 本文将介绍String.StringBuilder类的常用方法. 在java中String类不可变的,创建一个String对象后不能更改它的值.所以如果需要对原字符串进行一些改动操作,就需要用S ...

随机推荐

  1. angular组件间的通信(父子、不同组件的数据、方法的传递和调用)

    angular组件间的通信(父子.不同组件的数据.方法的传递和调用) 一.不同组件的传值(使用服务解决) 1.创建服务组件 不同组件相互传递,使用服务组件,比较方便,简单,容易.先将公共组件写在服务的 ...

  2. CRM企业管理系统一年多少钱?

    CRM系统一年多少钱?这是很多企业管理者比较关心的问题.目前市面上的CRM系统分为本地部署型和云部署型.云部署型CRM费用相对较低,只需要按需购买账号,连接网络即可使用:本地部署型CRM费用较高,企业 ...

  3. SpringCloud的Ribbon自定义负载均衡算法

    1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...

  4. 在一个py脚本中调用另外一个py脚本中的类或函数

    1.两个文件在同一目录,直接import即可 2.两个文件在不同目录 在导入文件的时候,Python只搜索当前脚本所在的目录,加载(entry-point)入口脚本运行目录和sys.path中包含的路 ...

  5. CentOS查看和修改PATH环境变量的方法 (转)

      查看PATH:echo $PATH以添加mongodb server为列修改方法一:export PATH=/usr/local/mongodb/bin:$PATH//配置完后可以通过echo $ ...

  6. mysql中,一个数字加上null,结果为null

    在mysql中,一个数字加上null,结果为null. 这个问题是我用update语句时遇见的,就像下边的例子 update tableName set number = number + x 这里的 ...

  7. Kotlin Coroutine(协程): 一、样例

    @ 目录 前言 一.直接上例子 1.延时任务. 2.异步任务 3.并行任务: 4.定时任务: 总结 前言 你还在用 Hanlder + Message? 或者 AsyncTask? 你还在用 Rxja ...

  8. Java on Visual Studio Code的更新 – 2021年6月

    Nick Zhu from Microsoft VS Code Java Team 大家好,欢迎来到 Visual Studio Code Java 更新的特别年中版.作为这篇文章的重点,我们将看看接 ...

  9. 将make的输出(标准输出/标准错误输出)重定向到文件

    方式 描述符 含义 stdin 0 标准输入 stdout 1 标准输出 stderr 2 标准错误输出 1.想要把make输出的全部信息,输出到某个文件中 最常见的办法就是:make xxx > ...

  10. python使用笔记11--时间模块

    1.时间模块常用方法 1 import time,datetime 2 #格式化好的时间2020-05-16 18:30:52 3 #时间戳1589616753 从unix元年(计算机发明的时间)到现 ...