记得以前参加校招的时候,总是有日期相关的面试题,比如计算两个日期之间的间隔天数。以前还觉得这种题就是为了纯粹为了面试的,但工作了之后,还就碰到了跟日期相关的bug。下面是一段js代码,是要把字符串描述的日期转换为Date类型的函数。其中,字符串的格式为年占用4个字符,月份2个字符,天数2个字符,小时2个字符,分钟2个字符,秒数2个字符。

 function str2Date(str) {
var year = parseInt(str.substr(0, 4));
// Month value range is [0, 11]
var month = parseInt(str.substr(4, 2)) - 1;
var day = parseInt(str.substr(6, 2));
var hour = parseInt(str.substr(8, 2));
var minute = parseInt(str.substr(10, 2));
var second = parseInt(str.substr(12, 2)); var date = new Date();
date.setYear(year);
date.setMonth(month);
date.setDate(day);
date.setHours(hour);
date.setMinutes(minute);
date.setSeconds(second);
return date;
} console.log(str2Date('20150515180000').toString());
console.log(str2Date('20160229235959').toString());
console.log(str2Date('20171231235959').toString());
console.log(str2Date('20181101000000').toString());

今天的日期是2019年3月20日,以上代码的测试用例运行结果全部正常。输出结果如下

1
2
3
4
Fri May 15 2015 18:00:00 GMT+0800 (CST)
Mon Feb 29 2016 23:59:59 GMT+0800 (CST)
Sun Dec 31 2017 23:59:59 GMT+0800 (CST)
Thu Nov 01 2018 00:00:00 GMT+0800 (CST)

但是在某个特定日期(月末),就发现这段代码的运行结果出错了。原来,new Date()生成的值是运行时的时间,在不同的时间,运行的结果是不同的。下面来看一个特定日期的运行结果。把第10行代码中的new Date的初始化,设置日期为2019年3月31日。

var date = new Date('2019-03-31 00:00:00');

修改之后的运行结果如下,有两个用例的运行结果是不符合预期的。

1
2
3
4
Fri May 15 2015 18:00:00 GMT+0800 (CST)
Tue Mar 29 2016 23:59:59 GMT+0800 (CST)
Sun Dec 31 2017 23:59:59 GMT+0800 (CST)
Sat Dec 01 2018 00:00:00 GMT+0800 (CST)

那究竟是怎么回事呢?只能逐步调试来看下哪一步出了问题。因为是日期错了,我这里通过日志把改变日期值的中间过程都打印出来。下面以第2个用例(2016年2月29日)调试看下。

function str2Date(str) {
var year = parseInt(str.substr(0, 4));
// Month value range is [0, 11]
var month = parseInt(str.substr(4, 2)) - 1;
var day = parseInt(str.substr(6, 2));
var hour = parseInt(str.substr(8, 2));
var minute = parseInt(str.substr(10, 2));
var second = parseInt(str.substr(12, 2)); var date = new Date('2019-03-31 00:00:00');
date.setYear(year);
console.log(date.toString());
date.setMonth(month);
console.log(date.toString());
date.setDate(day);
console.log(date.toString());
date.setHours(hour);
date.setMinutes(minute);
date.setSeconds(second);
return date;
}

输出的结果如下:

1
2
3
4
Thu Mar 31 2016 00:00:00 GMT+0800 (CST)
Wed Mar 02 2016 00:00:00 GMT+0800 (CST)
Tue Mar 29 2016 00:00:00 GMT+0800 (CST)
Tue Mar 29 2016 23:59:59 GMT+0800 (CST)

从输出结果来看SetMonth这一步就出错了。原来在当前场景下,调用SetMonth设置的月份,会导致预期时间是一个不合法的时间,而Date类进行了自动的纠正,也就改变了月份的值。后面又重新设置了天数,是合法值,Date不再对日期进行改变,最终就导致月份是错误的。
通过查询MDN文档,发现setFullYear函数是可以把年月日都作为参数输入,这样就能保证日期的完整性,特殊日期也不会出错。修改后的代码如下:

function str2Date(str) {
var year = parseInt(str.substr(0, 4));
// Month value range is [0, 11]
var month = parseInt(str.substr(4, 2)) - 1;
var day = parseInt(str.substr(6, 2));
var hour = parseInt(str.substr(8, 2));
var minute = parseInt(str.substr(10, 2));
var second = parseInt(str.substr(12, 2)); var date = new Date('2019-03-31 00:00:00');
date.setFullYear(year, month, day);
date.setHours(hour, minute, second);
return date;
} console.log(str2Date('20150515180000').toString());
console.log(str2Date('20160229235959').toString());
console.log(str2Date('20171231235959').toString());
console.log(str2Date('20181101000000').toString());

通过这个例子说明,每个函数的异常处理都有可能导致最终的结果出错,如果使用了系统函数或者其他库的函数,都需要对每个函数的异常处理有足够的了解,才能保证结果符合预期。

关于作者

bingoli

原文地址:https://www.cnblogs.com/bingoli/p/10574465.html

JavaScript的Date类的函数特殊处理导致的问题的更多相关文章

  1. JavaScript Date对象和函数 (一)

    JavaScript_Date对象说明  Date中文为"日期"的意思,Date继承自Object对象,此对象提供操作,显示日期与时间的函数 Date对象构造函数 Date对象具有 ...

  2. 前端(十四)—— JavaScript常用类:Number、Date类、字符串、数组、Math类、正则

    JS常用类:Number类.Date类.Math类.字符串.数组.正则 一.Number 1.常用数字 整数:10 小数:3.14 科学计数法:1e5 | 1e-5 正负无穷:Infinity | - ...

  3. js之序列化、eval和Date类用法

    序列化 JSON.stringify() 将对象转换为字符串 JSON.parse() 将字符串转换为对象类型 示例 var jsonStr = '{"name":"le ...

  4. Javascript学习6 - 类、对象、继承

    原文:Javascript学习6 - 类.对象.继承 Javasciprt并不像C++一样支持真正的类,也不是用class关键字来定义类.Javascript定义类也是使用function关键字来完成 ...

  5. PHP类和函数注释大全

    每次要用PHP的某个功能的时候,都要去查一下,于是决定将PHP所有类和函数都整理出来,加上注释 大致实现 将php.jar文件解压,取出目录stubs 将stubs中的所有php文件中的注释去掉,并做 ...

  6. javascript常用工具类整理(copy)

    JavaScript常用工具类 类型 日期 数组 字符串 数字 网络请求 节点 存储 其他 1.类型 isString (o) { //是否字符串 return Object.prototype.to ...

  7. JavaScript权威指南--类和模块

    知识要点 每个javascript对象都是一个属性集合,相互之间没有任何联系.在javascript中也可以定义对象的类,让每个对象都共享某些属性,这种“共享”的特性是非常有用的.类的成员或实例都包含 ...

  8. 你可能不知道的 Date 类

    Date 是 JS 中的重要的一个内置对象,其实例主要用于处理时间和日期,其时间基于 1970-1-1 (世界标准时间)起的毫秒数,时间戳长度为 13 位(不同于 Unix 时间戳的长度 10 位). ...

  9. JavaScript 中对变量和函数声明的“提前”

    变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或 ...

随机推荐

  1. 服务器解析慢,可以安装nscd解决

    针对服务器解析慢,可以在服务器上安装nscd,就可以把解析缓存起来,不用每次都解析 安装nscd: yum -y install nscd chkconfig nscd on service nscd ...

  2. Python中的线程详解

    线程 常用的方法 import threading import time def hello(name): print('Hello %s' % name) # 阻塞 time.sleep(5) p ...

  3. Javascript的算法题目

    用js实现单链表的增删,直接上代码 const linkList=new LinkList() function LinkList(){ var Node=function(element){ thi ...

  4. js正则积累

    判断是否为数字 function isNumber(val){ var regPos = /^\d+(\.\d+)?$/; //非负浮点数 var regNeg = /^(-(([0-9]+\.[0- ...

  5. wampserver安装

    WampServer的下载地址:https://sourceforge.net/projects/wampserver 安装教程:https://jingyan.baidu.com/article/4 ...

  6. FloatingActionButton FAB 悬浮按钮

    FloatingActionButton简称FAB,这是一种比较美观的按钮: 1.使用前: FAB代表一个App或一个页面中最主要的操作,如果一个App的每个页面都有FAB,则通常表示该App最主要的 ...

  7. Codeforces Round #508 (Div. 2)

    Codeforces Round #508 (Div. 2) http://codeforces.com/contest/1038 A #include<bits/stdc++.h> us ...

  8. FortiGate下用户访问特定网址不通

    1.现状: 如图,上网行为管理和防火墙控制用户的数据访问,到外网的出口链路有2条:联通的和电信的,其中联通的优先级较高. 2.现象: 用户访问www.xxxxbbs.com不通 3.分析 在上网行为管 ...

  9. 698. Partition to K Equal Sum Subsets 数组分成和相同的k组

    [抄题]: Given an array of integers nums and a positive integer k, find whether it's possible to divide ...

  10. Yii2增删改查

    Controller <?php namespace frontend\controllers; use frontend\models\User; use yii\data\Paginatio ...