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月。参考下表:
代码示例:
2.1.1.2Java的日期对象
Java中提供了丰富的类,可以直接校验日期,如果不能使用java的类库校验自定义的一些日期,也可以自己编写规则进行校验,参考javascript的方法。
更多参考java.util.Date的API
代码示例:
2.2 拆分年月日校验
山寨做法,不推荐使用。
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
3.对日期自动升级的说明
通过Date(年,月,日)创建对象,会自动转换非法日期,比如:传入1月和32号的日期,会自动升级为2月1日,比较年月日不一致说明日期非法。
3.1Javascript的转换
代码,参考Javascript的Date API
结果:
3.2Java的转换
代码,参考Java的Date对象API
结果:
2100-3-2
4.开发注意事项
1.系统对于标准的日期输入,尽量使用日期控件,只能选择,不能修改;对于可以手工输入和修改的日期,需要增加校验。
2.有些业务规则跟闰年有关,开发过程中一定要跟业务确认清楚,比如:有效期天数,碰到闰年的情况,每年的天数可能就有一天的差别。