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):

LetterDate or Time ComponentPresentationExamples
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):

LetterDate or Time ComponentPresentationExamples
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引起的思考

let块级引起的闭包思考

如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?

记录C#常用的代码片段