Java Calendar以及使用总结

本文回顾了LeetCode 177周赛首题挑战经历,深入解析两日期间天数计算问题,分享Java Calendar类使用技巧及注意事项,探讨Calendar set方法前需先clear的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写这篇博客来纪念一下leetcode177周赛翻车的第一题。第一部分是该题的分析,第二部分是Java Calendar使用以及注意点。

1. 题目分析

1.1 题目

请你编写一个程序来计算两个日期之间隔了多少天。
日期以字符串形式给出,格式为 YYYY-MM-DD

1.2 思路

将日期的每一项转化为int后设置Calendar, 然后使用getTimeInMillis方法获取从1970.01.01到该时间的毫秒值,然后相减再换算成天数

1.3 代码
public int daysBetweenDates(String date1, String date2) {
         String[] s1=date1.split("-");
         String[] s2=date2.split("-");
         java.util.Calendar c1=java.util.Calendar.getInstance();
         java.util.Calendar c2=java.util.Calendar.getInstance();
         //1 之前提交的错误版本没有下面这2句
         c1.clear();
         c2.clear();
         //2 之前提交的错误版本c1.set后面的第二项没有-1
         c1.set(Integer.parseInt(s1[0]),Integer.parseInt(s1[1])-1,Integer.parseInt(s1[2]));
         c2.set(Integer.parseInt(s2[0]),Integer.parseInt(s2[1])-1,Integer.parseInt(s2[2]));
        long temp=Math.abs(c1.getTimeInMillis()-c2.getTimeInMillis());
        long ans=temp/(24*60*60*1000);
        return ((int)ans);
    }
1.4 分析
  1. 也是最重要的一点,没有在对Calendar使用set方法之前clear,导致系统时间会影响calendar的值(比如当前时分秒)。测试成功然后提交,奇幻的情况发生了!相同的样例,在测试和提交的时候跑出不同的结果。造成这个情况的原因是:1. 统时间会影响calendar的值 2.long的除法将计算的小数部分舍去 3.计算出来的结果在不同的运行时间是随机的。
    PS:中途曾经试过c1.set(Integer.parseInt(s1[0]),Integer.parseInt(s1[1])-1,Integer.parseInt(s1[2]),0,0,0),仍然提交错误,推测是因为这种方法只能设置到秒,毫秒也会影响结果。
  2. Calendar的月份是0-11,存入的时候要减去1以获得正确结果

2. Calendar使用总结

2.0 简介

Calendar是一个抽象类,GregorianCalendar 是它的一个具体实现。Calendar.getInstance()获得一个以当前时间为初始化的calendar对象。(GregorianCalendar的实例)

2.1 获取时间

注意Calendar.DATE和Calendar.DAY_OF_MONTH相同,而Calendar.HOUR(12小时制)和Calendar.HOUR_OF_DAY不相同

Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        //比当前月份少1
        int month = cal.get(Calendar.MONTH);
        //date与day_of_month相同
        int date = cal.get(Calendar.DATE);
        int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
        //表示本周的第几天,从周日开始计算
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
        //12小时制
        int hour = cal.get(Calendar.HOUR);
        //24小时制
        int hourOfDay = cal.get(Calendar.HOUR_OF_DAY);
        int minute = cal.get(Calendar.MINUTE);
        int second = cal.get(Calendar.SECOND);
        int millisecond = cal.get(Calendar.MILLISECOND);
        //获取本月的最后一天,getMaximum是获取日的最大值,一定是31
        int maxDate = cal.getActualMaximum(Calendar.DATE);
2.2设置时间
set

set(int field, int value)
field 可以用来设置年/月/日/小时/分钟/秒/微秒等值,例如取值Calendar.MONTH

set(int year, int month, int day, int hour, int minute, int second)
注意:没有set(int year, int month, int day, int hour, int minute, int second,int millsecond)函数,并且上面设置到秒的这个函数,并不会把millsecond清零

Calendar 为了性能原因对 set() 方法采取延缓计算的方法,即多次set不多次计算,在调用get(), getTime(), getTimeInMillis(), add(), or roll() 这些函数时才计算。java document上的栗子:

Calendar c = Calendar.getInstance();
c.set(2000, 7, 31, 0, 0 , 0); //2000-8-31
c.set(Calendar.MONTH, Calendar.SEPTEMBER); //应该是 2000-9-31,也就是 2000-10-1
c.set(Calendar.DAY_OF_MONTH, 30); //如果 Calendar 转化到 2000-10-1,那么现在的结果就该是 2000-10-30
cal1.getTime(); //2000-9-30,说明调用get这类函数后才计算
add
  1. 当被修改的字段超出它可以的范围时,那么比它大的字段会自动修正(比如下面例子的第2,3行,修改月份年份修正)
  2. 当被修改的字段导致比它小的字段的范围改变时,比它小的字段调整为尽可能接近其期望值(如下面例子的3,4行)
Calendar cal1 = Calendar.getInstance();
cal1.set(1999, 7, 31, 0, 0 , 0); //1999-8-31
cal1.add(Calendar.MONTH, 13); //2000-9-31
System.out.println(cal1.getTime()); //结果是2000-9-31
roll

当被修改的字段超出它可以的范围时,那么比它大的字段不会被修正

2.3 容错性设置

当一个用户给出错误的日期时,自动计算,但如果Lenient==false,Calendar 报错

Calendar cal1 = Calendar.getInstance();
cal1.set(2000, 1, 32, 0, 0, 0);
System.out.println(cal1.getTime());//显示为Tue Feb 01 00:00:00 PST 2000
cal1.setLenient(false);
cal1.set(2000, 1, 32, 0, 0, 0);
System.out.println(cal1.getTime());//报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值