先上问题
public static void main(String[] args) {
//使用DateTimeFormatter获取当前周数
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("w");
//2018年第一天
System.out.println(LocalDateTime.of(2018, 1, 1, 0, 0, 0).format(dateTimeFormatter));
//2018年最后一天
System.out.println(LocalDateTime.of(2018, 12, 31, 0, 0, 0).format(dateTimeFormatter));
//2019年第一天
System.out.println(LocalDateTime.of(2019, 1, 1, 0, 0, 0).format(dateTimeFormatter));
//2019年最后一天
System.out.println(LocalDateTime.of(2019, 12, 31, 0, 0, 0).format(dateTimeFormatter));
//这天是星期六
System.out.println(LocalDateTime.of(2019, 4, 6, 0, 0, 0).format(dateTimeFormatter));
//这天是星期日
System.out.println(LocalDateTime.of(2019, 4, 7, 0, 0, 0).format(dateTimeFormatter));
//这天是星期一
System.out.println(LocalDateTime.of(2019, 4, 8, 0, 0, 0).format(dateTimeFormatter));
}
执行结果:
1
1
1
1
14
15
15
有没有发现很奇怪的一件事情,每年的最后1天和第1天居然都是第1周而且每周的第1天是周日!这明显不符合我们要获取的周数,正常的周数是每年最后1天是53周,第1天为第1周,每周从周一开始计算,那么为什么呢?
因为默认使用ISO8061 标准,该标准与我们所认知的周数计算并不一致所以导致了获取的周数不符合预期
ISO8061自然周
自然周的标准很多。其中以ISO8061 为准。
可以看到一年的第一个自然周应当满足:
1,有第一个星期四
2,包含1月4号
3,第一个自然周应当有4个或者4个以上的天数
4,这个星期开始的时间(即周一)在去年的12月29号(星期一)到今年的1月4号之间
所以如果1月1号是周一、周二、周三或者周四,它属于第一个自然周,如果不是,他属于去年的52周或者53周。
解决方案:
public static void main(String[] args) {
//使用DateTimeFormatter获取当前周数
WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY,1);
//2018年第一天
System.out.println(LocalDateTime.of(2018, 1, 1, 0, 0, 0).get(weekFields.weekOfYear()));
//2018年最后一天
System.out.println(LocalDateTime.of(2018, 12, 31, 0, 0, 0).get(weekFields.weekOfYear()));
//2019年第一天
System.out.println(LocalDateTime.of(2019, 1, 1, 0, 0, 0).get(weekFields.weekOfYear()));
//2019年最后一天
System.out.println(LocalDateTime.of(2019, 12, 31, 0, 0, 0).get(weekFields.weekOfYear()));
//这天是星期六
System.out.println(LocalDateTime.of(2019, 4, 6, 0, 0, 0).get(weekFields.weekOfYear()));
//这天是星期日
System.out.println(LocalDateTime.of(2019, 4, 7, 0, 0, 0).get(weekFields.weekOfYear()));
//这天是星期一
System.out.println(LocalDateTime.of(2019, 4, 8, 0, 0, 0).get(weekFields.weekOfYear()));
}
执行结果:
1
53
1
53
14
14
15
此时结果已经符合预期,每周从周一开始且每年的第一天为第一周
如果有更好的方案欢迎留言交流
其他方案
如果按照每年的第N周计算周数,在1月1日非周日的情况下必然会有一周中包含两个周数会导致数据错乱
建议使用指定周数,即为当前时间-某个周一的相差周数
public static void main(String[] args) {
LocalDateTime currentLocalDateTime = LocalDateTime.of(2019,12,16,0,0,0);
LocalDateTime staticLocalDateTime = LocalDateTime.of(1900,1,1,0,0,0);
//计算日期最佳方式
//以下两种计算方式等价
System.out.println(ChronoUnit.WEEKS.between(staticLocalDateTime,currentLocalDateTime)+1);
System.out.println(staticLocalDateTime.until(currentLocalDateTime,ChronoUnit.WEEKS)+1);
}
参考资料:java localdate获取自然周