更多问答 >>
-
每日一问 系统帮我们做了网络安全校验,那么还需要我们手动去做吗?
2020-01-14 20:33 -
每日一问 “别慌,你 post 一个 Runnable ,在下一帧就可以拿到了。”这种说法对吗?
2020-01-20 01:05 -
每日一问 “你这个布局可以在进入这个页面之前预加载,这样页面渲染就快了”可能有什么潜在的问题吗?
2020-01-20 01:05 -
2020-02-02 17:17
-
每日一问 很多时候我们说单例实现方式会提到「枚举实现」,那么枚举底层是如何实现的呢?
2020-02-23 22:18 -
每日一问 为什么 Dialog 默认弹出后 Activity 就无法响应用户事件了?
2020-01-15 19:24 -
每日一问 很多书籍上写:“事件分发只有一次 ACTION_DOWN,一次 ACTION_UP”严谨吗?
2020-01-07 00:08 -
每日一问 ViewPager 嵌套,“老子”怎么就没拦住你?
2019-12-29 23:52 -
每日一问 Activity 都重建了,你 Fragment凭什么活着?
2019-12-23 23:19 -
2019-12-20 00:08

根据JDK文档关于日期的定义 ,
y表示的是我们日常使用的年份,而Y表示的是Week year。先了解2个知识点:
Week year
Week year表示的是这个周所属的年份。每年最开始的几天和最后的几天的Week year不一定是当年的值,而是受到每年的第一周的影响。第01周
又有根据这份JDK文档,JAVA判断周日期的标准与ISO_8601兼容:
问题分析
有了以上知识,我们再看看
2019-12-30以YYYY格式化为什么会出现问题:先看一下这些日期对应的星期:
首先根据
第01周的定义,2020-01-04所在的周为2020的第一周,所以2019-12-30到2020-01-05都属于是2020年的第01周。再根据
YYYY表示的是Week year的结论,可以知道,当使用YYYY格式化时,2019-12-30到2020-01-05都会得到2020。睡了一觉起来,看到这个文章,发现我之前理解的有些问题。有重新梳理了一下,下面是对之前答案的修订:
上一个答案所述的前提是JAVA判断周日期的标准与ISO_8601兼容,但是这个前提又有个必要条件:The week determination is compatible with the ISO 8601 standard when getFirstDayOfWeek() is MONDAY and getMinimalDaysInFirstWeek() is 4.
重新整理了一下关于YYYY的知识:
YYYY获取的是Week year而不是我们常用的年份。
每年最开始的几天和最后的几天的Week year不一定是当年的值,而是受到每年的第一周的影响。
判断当年第一周的主要有两个因素:
1) minimalDaysInFirstWeek 一年第一周所需最小的天数。比如1表示只要包含第一天就算该年的第一周,而7表示只有完整的一周都在该年才算该年的第一周
2) firstDayOfWeek 指定一周的第一天,周日。需要注意两个地方:
1)这两个值都是本地化的值,不同地方不一样。在JDK1.7国内默认值分别是1,Calendar.SUNDAY(1),也就是说只要跨年周包含次年的1月1日,那么这一周7个日期的Week year就都是次年的年份。
2)上述这两个值,都指的是SimpleDateFormat对象中的calendar对象对应的值,之前的答案就是踩了这个坑。
根据JAVA文档的说明,对于同一个日期,如果我们修改了minimalDaysInFirstWeek和firstDayOfWeek,其实是可以人为修改YYYY获取到的值的。
比如:2019-12-30,按照JDK1.7默认规则,我们计算出他是属于2020年的第一周,week year是2020。 但如果我们规定一周从周二开始,那么可以看到:2019年12月30日成为了2019年最后一周第52周的最后一天,他的week year变成了2019.
2019年12月31日成为了2020年第一周的第一天,他的week year是2020.如果使用YYYY来显示日期的话就会出现问题。
结论
在JDK1.7国内,只要跨年周包含次年的1月1日,那么这一周7个日期的Week year就都是次年的年份。
我们可以通过修改minimalDaysInFirstWeek和firstDayOfWeek,修改YYYY格式化后的值(即week year)
yyyy-MM-dd HH🇲🇲ss 我们一般都是用的这个格式化的时间
小写的h是12小时制,大写的H是24小时制。
所以我们可以猜测yyyy与YYYY只是标准不同。
yyyy的日期和时间的表示方法使用的国际化的标准(ISO 8601:2004)
在2019年的最后一周出现了日期上的bug,应该就是YYYY导致的,我查看了维基百科,感觉发现有个显示标准很能说明这个BUG,但是我的猜测。(ISO 8601)其中的星期日历的表示法。
其中有一段话:
“第一个日历星期有以下四种等效说法:
1,本年度第一个星期四所在的星期;
2,1月4日所在的星期;
3,本年度第一个至少有4天在同一星期内的星期;
4,星期一在去年12月29日至今年1月4日以内的星期;
推理可得,如果1月1日是星期一、星期二、星期三或者星期四,它所在的星期就是第一个日历星期;如果1月1日是星期五、星期六或者星期日,它所在的星期就是上一年第52或者53个日历星期;12月28日总是在一年最后一个日历星期。”
之前回答的有点问题,删了重答一遍
大写的Y是java7中新加入的日期格式,表示的是week year(ISO周日历),比如2019年一共52周,所以以这种计时方式,2019年12月28日为2019年的最后一天,2019年12月29日为2020年的第一天(周日为一周的第一天)
yyyy-MM-dd 与 YYYY-MM-dd 如果用于Date转String的情况YYYY会被转换成按周日历所在的年份,下面代码的运行结果:
2019-12-292020-12-29用于String转Date的情况,YYYY-MM-dd只能解析YYYY无法解析MM-dd,所以不管MM-dd怎么填,都只会转换为指定年份的周日历第一天,比如下面的代码会得到:
Tue Jan 07 00:00:00 CST 2020Sun Dec 29 00:00:00 CST 2019在官方文档找到了YYYY的一个用法:"YYYY-'W'ww-u",表示xxxx年 - 第x周 - 周几(注意这个不是这周的第几天,而是周几,7表示周日),下面的代码会输出:
2020-01-072020-W02-2