今天在改一个以前同事留下的功能时,发现比较日期字符串写得很复杂。主要是判断两个日期字符串的范围是否超过1年。
因为是JS比较字符串,所以是先截取出年月日,然后依次比较年月日。写得很复杂,先判断后者年份是否大于前者,是否小于前者,是否相等,如果年份相等,则满足条件;如果大于,是否刚好差距为1,不为1则不满足条件,如果刚好为1,则一次判断月份值和日期值。代码逻辑理解起来很绕,而且还出错了。

于是自己简单总结一下两种方法和可能出现的问题:

转成标准日期再进行比较

先将字符串转换成标准日期,再比较两者大小。Java API比较多,就不再赘述。
其中js 使用 var date = new Date(dateString); 的方式进行转换,
其中要注意的是 dateString的格式必须是 yyyy/MM/dd 的格式。

直接将字符串的年月份拼接比较

直接将字符串的年月日进行拼接,如 2021-06-07 拼成 20210607 这样进行比较,这种方式初步看来是没有问题的,但实际上 2021-6-7 这种格式也是存在的,那么拼接出来就是 202167 ,这样去比较的话肯定是有问题的。我们只需要使用

int date = yyyy * 1000 + MM * 100 +dd;
	这样不管是 2021-06-07 还是 2021-6-7 拼接出来的都是 20210607
  • [ ? ] 我们现在思考下为什么会有这样的问题:
    比较字符串最开始想到的是直接将各个位数相加起来,比如 yyyy + MM + dd
    ,那么 2021-06-07 相加就是 2021 + 6 +7 = 2034 ,很明显这样是不行的,年月日在日期中的权重值是不一样的,直接相加就把三个时间单位的权重值算成相同的了,这样时间单位小的数值会影响时间单位大的数值。比如2020 - 6 -7 和 2019 - 6 -8 后面的日期明显比前面的小,如果直接相加反而后面的更大。所以我们要给年月日分别设置合理的权重值。
  • [ ? ] 如何设置权重值
    年月之间的换算倍数是 12 ,月和日之间的换算倍数是28到31 ,我们可以勉强认为是 30 。
    那么如果设置不同单位之间的权重值大于实际情况的权重值,那么是不是就符合实际情况?
    比如年月之间的换算单位是 12 ,如果我设置年月的权重分别为 100 和 1 ,那么是不是就是 不管这个月份再怎么差距大,都影响不了年份的比较结果。 比如年份相差 2 ,那就是相差 200 ,月份即使相差11,也只弥补了 11 ,依然远小于 200 。也就是说 两个日期比较大小的最终结果还是由年份决定的。 那么依旧这个道理:日和月之间的换算单位也算做 100 ,那么是不是就是日值之间的差距永远无法影响到月的值差距上?
    所以最后我们约定三个时间单位的权重分别是年月日:10000 100 1 刚好相邻两个单位之间的权重差是100 ,远大于实际中的权重差,所以算出来的值的比较结果是符合要求的。
    结果没想到本来是为了方便计算,却刚好算出来的值是 三个时间单位的字符串拼接结果,而且是那种不用考虑值小于10时 有没有带0 的情况(比如7月 07 和7)。
    这种就是巧合吧,不过从这里也发现很多时候还是要多思考,很多东西都是相通的。
String beginDate = "2021-1-12";
		String endDate = "2020-12-12";
		String[] begin = beginDate.split("-");
		String[] end = endDate.split("-");
		int beginTotal = Integer.parseInt(begin[0]) * 10000 + Integer.parseInt(begin[1]) *100
				+ Integer.parseInt(begin[2]);
		int endTotal = Integer.parseInt(end[0]) *10000 + Integer.parseInt(end[1])*100
				+ Integer.parseInt(end[2]);
		System.out.println(beginTotal);
		System.out.println(endTotal);
		if (beginTotal >= endTotal) {
			System.out.println(beginDate + "大于或等于" + endDate);
		} else {
			System.out.println(beginDate + "大于或者" + endDate);
		}