日期类选择
这里推荐使用Java 8 的 LocalDate 和 LocalDateTime 类,原因后面讲。
场景:根据当天时间算出本周是今年的第几周
- 我们先看看源码有什么类,在根据注释去使用。基本都在time包里
- 通过源码,找到WeekFields类,看名字就知道它是周规则的类,并且还提供关于周和周内日期的TemporalField接口和方法。找到了方法,下面就做测试。
一 测试(1)
LocalDate date = LocalDate.of(2023, 8, 21);
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int week = date.get(weekFields.weekOfYear());
//结果为34
以上结果是34,明显不对。21号是周一。结果应该是35周才对。在测试21号到27号每天的情况,发现只有27号才显示35周。所以可以肯定,当前日期是以周日作为起点开始,周六作为结束,那就是时间转换的周数计数有问题。所以把默认的 WeekFields.of(Locale.getDefault()) 转换换成使用中国周计数的。
二 测试(2)
LocalDate date = LocalDate.of(2023, 8, 21);
//使用中国周计数
WeekFields weekFields = WeekFields.of(Locale.CHINA);
int week = date.get(weekFields.weekOfYear());
//结果还是34
- 运行后,发现结果还是34,这是什么原因?观察源码调用发现:在初始化时,这个它使用的还是周日做为一周的开始时间。
- 所以使用这个初始化的类还是有问题?这感觉是Calendar的一个bug,它没有正确尊重Locale所对应的公历,直接将周起始日硬编码为周日,导致结果与中国的惯例不符
- 既然API封装的类不好用,那我们就使用自定义的
三 测试(3)
LocalDate date = LocalDate.of(2023, 8, 21);
//使用自定义的,选择周一作为一周的开始时间,后面的1表示,只要今天是新的一周并且只要有1天,就会统计为最新的周期。
//(有点拗口,换个说法,就是如果你写7,就是要到周日,计算时才会统计为35周,还是不理解的,大家可以通过自己测试就知道了)
WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 1);
int week = date.get(weekFields.weekOfYear());
//结果为35
结果为35,拿到了我们想要的值,所以这个方法满足要求。
上面说到要 LocalDate 和 LocalDateTime 类,原因是:
- 易用性好有丰富的API和大量的时间规则类,基本可以满足所有时间类的需求。
- 最重要的一点他们是不可变类,线程安全,这点很重要。
总结
- 在使用一些陌生的方法时,可以通过查看基础包的注释去了解怎么用。
- 有时候JAVA自己封装的类也会不满足自己的需求,这时候就需要自己自定义了。
- 时间区间的选择推荐使用jdk8以后的类,问就是线程安全,而且好用。