java和javascript日期校验和闰年问题分析和解决方案

1.闰年的介绍

地球绕太阳运行周期为365天5小时48分46秒(合365.24219天)即一回归年。公历的平年只有365日,比回归年短约0.2422 日,所余下的时间约为四年累计一天,故四年于2月加1天,使当年的历年长度为366日,这一年就为闰年。

现行公历中每400年有97个闰年。按照每四年一个闰年计算,平均每年就要多算出0.0078天,这样经过四百年就会多算出大约3天来,因此,每四百年中要减少三个闰年。所以规定,公历年份是整百数的,必须是400的倍数的才是闰年,不是400的倍数的,虽然是4的倍数,也是平年,这就是通常所说的:四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,1900年则是平年。

由于地球的自转速度逐渐降低,而公转速度则相对更加稳定,所以上述的系统经过更长的周期也会发生微小的误差。在长远的将来,针对闰年的微小调整应该不是由预定的系统决定,而是随时不定性的。

既然是这样,在系统开发过程中,是否需要判断几百年后的事情呢?没有太大必要,如果一个系统能够使用几百年,也该寿终正寝了。

2.如何进行日期校验

系统中常有三种做法,第一种是使用语言自身的日期对象特性,第二种就是将日期转换为某一个特定的格式,然后拆分出来年月日,判断年份、月份、日期。两种方法在javascript和java中都适用,第二种方法不推荐。

另外一种,使用正则表达式来校验,正则表达式通常非常复杂,难以理解,这种方法对100倍数闰年校验存在隐患。

2.1  使用日期对象校验

2.1.1.1Javascript的日期对象

将指定的格式日期字符串转换成标准的格式(比如yyyy-mm-dd),对年月日进行拆解,通过年月日参数生产Date(年,月,日)对象,再得到Date对象的年月日,和拆解之后的年月日进行比较,看结果是否一致。

通过Date(年,月,日)创建对象,会自动转换非法日期,比如:传入1月和32号的日期,会自动升级为2月1日,比较年月日不一致说明日期非法。

Date对象的构造方法,月份是从0开始的,0表示1月。参考下表:

代码示例:

java和javascript日期校验和闰年问题分析和解决方案

2.1.1.2Java的日期对象

Java中提供了丰富的类,可以直接校验日期,如果不能使用java的类库校验自定义的一些日期,也可以自己编写规则进行校验,参考javascript的方法。

更多参考java.util.Date的API

java和javascript日期校验和闰年问题分析和解决方案

代码示例:

java和javascript日期校验和闰年问题分析和解决方案

2.2  拆分年月日校验

    山寨做法,不推荐使用。

java和javascript日期校验和闰年问题分析和解决方案

2.3  正则表达式校验

下面这个是摘录自某系统中的正则表达式,格式化之后也很难理解。这个正则表达式只考虑年数是4的倍数的年份,对于100的倍数的则存在问题,比如1900年、2100年就不是闰年,也会校验通过,不能在系统中使用。

支持的格式为:

1)0012/02/29

2)2012/2/29

3)2012 02 29

4)2012 2 01

5)2100 2 1

java和javascript日期校验和闰年问题分析和解决方案

3.对日期自动升级的说明

通过Date(年,月,日)创建对象,会自动转换非法日期,比如:传入1月和32号的日期,会自动升级为2月1日,比较年月日不一致说明日期非法。

3.1Javascript的转换

代码,参考Javascript的Date API

java和javascript日期校验和闰年问题分析和解决方案

结果:

java和javascript日期校验和闰年问题分析和解决方案

3.2Java的转换

代码,参考Java的Date对象API

java和javascript日期校验和闰年问题分析和解决方案

结果:

2100-3-2

4.开发注意事项

1.系统对于标准的日期输入,尽量使用日期控件,只能选择,不能修改;对于可以手工输入和修改的日期,需要增加校验。

2.有些业务规则跟闰年有关,开发过程中一定要跟业务确认清楚,比如:有效期天数,碰到闰年的情况,每年的天数可能就有一天的差别。