YYYY引起的思考
Posted andong2015
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了YYYY引起的思考相关的知识,希望对你有一定的参考价值。
平时格式化时间的时候一般都是用的yyyy-MM-dd ,年份都是小写y。最近看很多技术公众号上在发YYYY和yyyy的区别,特此总结一下:
上代码,一目了然
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class TestDate { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); String []arr = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"}; calendar.set(2019, Calendar.AUGUST, 31); DateFormat formatUpperCase = new SimpleDateFormat("yyyy-MM-dd"); DateFormat formatUpperCase2 = new SimpleDateFormat("YYYY-MM-dd"); System.out.println("2019-08-31 to yyyy-MM-dd: " + formatUpperCase.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); System.out.println("2019-08-31 to YYYY-MM-dd: " + formatUpperCase2.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); calendar.set(2019, Calendar.DECEMBER, 31); System.out.println("2019-12-31 to yyyy-MM-dd: " + formatUpperCase.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); System.out.println("2019-12-31 to YYYY-MM-dd: " + formatUpperCase2.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); calendar.set(2019, Calendar.DECEMBER, 30); System.out.println("2019-12-30 to yyyy-MM-dd: " + formatUpperCase.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); System.out.println("2019-12-30 to YYYY-MM-dd: " + formatUpperCase2.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); calendar.set(2019, Calendar.DECEMBER, 29); System.out.println("2019-12-29 to yyyy-MM-dd: " + formatUpperCase.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); System.out.println("2019-12-29 to YYYY-MM-dd: " + formatUpperCase2.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); calendar.set(2019, Calendar.DECEMBER, 28); System.out.println("2019-12-28 to yyyy-MM-dd: " + formatUpperCase.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); System.out.println("2019-12-28 to YYYY-MM-dd: " + formatUpperCase2.format(calendar.getTime())+",今天是:"+arr[calendar.get(Calendar.DAY_OF_WEEK)-1]); } }
执行结果如下:
2019-08-31 to yyyy-MM-dd: 2019-08-31,今天是:星期六 2019-08-31 to YYYY-MM-dd: 2019-08-31,今天是:星期六 2019-12-31 to yyyy-MM-dd: 2019-12-31,今天是:星期二 2019-12-31 to YYYY-MM-dd: 2020-12-31,今天是:星期二 2019-12-30 to yyyy-MM-dd: 2019-12-30,今天是:星期一 2019-12-30 to YYYY-MM-dd: 2020-12-30,今天是:星期一 2019-12-29 to yyyy-MM-dd: 2019-12-29,今天是:星期日 2019-12-29 to YYYY-MM-dd: 2020-12-29,今天是:星期日 2019-12-28 to yyyy-MM-dd: 2019-12-28,今天是:星期六 2019-12-28 to YYYY-MM-dd: 2019-12-28,今天是:星期六
注意上面标出的部分,发现2019-12-31 转化之后竟然变为了 2020年。
查看SimpleDateFormat 的API,发现其实1.6版的并没有“Y” 这个参数,1.6版的参数如下:
The following pattern letters are defined (all other characters from ‘A‘
to ‘Z‘
and from ‘a‘
to ‘z‘
are reserved):
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
G |
Era designator | Text | AD |
y |
Year | Year | 1996 ; 96 |
M |
Month in year | Month | July ; Jul ; 07 |
w |
Week in year | Number | 27 |
W |
Week in month | Number | 2 |
D |
Day in year | Number | 189 |
d |
Day in month | Number | 10 |
F |
Day of week in month | Number | 2 |
E |
Day in week | Text | Tuesday ; Tue |
a |
Am/pm marker | Text | PM |
H |
Hour in day (0-23) | Number | 0 |
k |
Hour in day (1-24) | Number | 24 |
K |
Hour in am/pm (0-11) | Number | 0 |
h |
Hour in am/pm (1-12) | Number | 12 |
m |
Minute in hour | Number | 30 |
s |
Second in minute | Number | 55 |
S |
Millisecond | Number | 978 |
z |
Time zone | General time zone | Pacific Standard Time ; PST ; GMT-08:00 |
Z |
Time zone | RFC 822 time zone | -0800 |
注意表格上面那句话,并不是只有以上表格中的字母被用到,事实上,其他字母也被预留了。发现上面的表格中并没有对“Y” 做格式定义。查找1.7版本
The following pattern letters are defined (all other characters from ‘A‘
to ‘Z‘
and from ‘a‘
to ‘z‘
are reserved):
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
G |
Era designator | Text | AD |
y |
Year | Year | 1996 ; 96 |
Y |
Week year | Year | 2009 ; 09 |
M |
Month in year | Month | July ; Jul ; 07 |
w |
Week in year | Number | 27 |
W |
Week in month | Number | 2 |
D |
Day in year | Number | 189 |
d |
Day in month | Number | 10 |
F |
Day of week in month | Number | 2 |
E |
Day name in week | Text | Tuesday ; Tue |
u |
Day number of week (1 = Monday, ..., 7 = Sunday) | Number | 1 |
a |
Am/pm marker | Text | PM |
H |
Hour in day (0-23) | Number | 0 |
k |
Hour in day (1-24) | Number | 24 |
K |
Hour in am/pm (0-11) | Number | 0 |
h |
Hour in am/pm (1-12) | Number | 12 |
m |
Minute in hour | Number | 30 |
s |
Second in minute | Number | 55 |
S |
Millisecond | Number | 978 |
z |
Time zone | General time zone | Pacific Standard Time ; PST ; GMT-08:00 |
Z |
Time zone | RFC 822 time zone | -0800 |
X |
Time zone | ISO 8601 time zone | -08 ; -0800 ; -08:00 |
发现"Y"是1.7版本新加的。新加的还有u,x。
在测试纪元标志的过程中,发现了一个问题,然后又百度了一下定义,发现自己之前的认知是错误的。
先说结论:
1.世纪这个单位是从1开始,百结尾。比如一世纪,是公元1年~公元100年。再比如2000年是20世纪的最后一年,2001年是21世纪的第一年
2.公元元年,也就是公元1年,公元元年之前的都是公元前,也就是公元1年的前一年是公元前1年。如果说公元1年是0001的话,那么从数字上来看0000就是公元前1年。实际上,在calendar中,year的最小值是1,而不是0,更不是负数。
G的测试过程:
G 公元,AD(Anno Domini)是公元,BC(Before Christ)代表公元前。需要注意的是在日期格式化中,没有一个日期是 0000年,0000年实际上是公元前1年。引用官方文档的另一个例子:"01/02/-3" is parsed as Jan 2, 4 BC.
Calendar calendar = Calendar.getInstance(); DateFormat formatUpperCase = new SimpleDateFormat("Gyyyy"); calendar.set(Calendar.YEAR,2019); System.out.println(formatUpperCase.format(calendar.getTime()));
结果:
公元2019
这里发现打印的并不是“AD” 或 “BC” ,而是“公元”。SimpleDateFormat初始化时,如果没有指定Locale,则会默认使用本地设置。修改一下构造方法,打印英文:
Calendar calendar = Calendar.getInstance(); DateFormat formatUpperCase = new SimpleDateFormat("Gyyyy", Locale.ENGLISH); calendar.set(Calendar.YEAR,2019); System.out.println(formatUpperCase.format(calendar.getTime()));
结果:
AD2019
尝试一下公元前,发现如果只把年份设为负数,没有办法正确输出预想结果,单0可以
Calendar calendar = Calendar.getInstance(); DateFormat formatUpperCase = new SimpleDateFormat("Gyyyy"); calendar.set(Calendar.YEAR,-2019); System.out.println(formatUpperCase.format(calendar.getTime()));
结果:
公元2020
本来我们想打印公元前2020年,结果变成了公元2020年
这里需要注意一下,Calendar中,不能直接用负数年份代表公元前(原因可以看Canlendar每个域的范围),纪元标志需要单独设置。
Calendar calendar = Calendar.getInstance(); DateFormat formatUpperCase = new SimpleDateFormat("Gyyyy"); calendar.set(Calendar.YEAR,2019); calendar.set(Calendar.ERA,GregorianCalendar.BC); System.out.println(formatUpperCase.format(calendar.getTime()));
结果:
公元前2019
参考:https://mp.weixin.qq.com/s/LrtaTTz25NIV7EAr9q3BHQ
以上是关于YYYY引起的思考的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis如何传递多个参数——一个莫名空指针错误引起的思考
HTML代码中在两个匿名函数中使用同名变量出现bug而引起的变量作用域的思考
AngularJS track by $index引起的思考