JavaScript的Date类的函数特殊处理导致的问题
记得以前参加校招的时候,总是有日期相关的面试题,比如计算两个日期之间的间隔天数。以前还觉得这种题就是为了纯粹为了面试的,但工作了之后,还就碰到了跟日期相关的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 |
Fri May 15 2015 18:00:00 GMT+0800 (CST) |
但是在某个特定日期(月末),就发现这段代码的运行结果出错了。原来,new Date()生成的值是运行时的时间,在不同的时间,运行的结果是不同的。下面来看一个特定日期的运行结果。把第10行代码中的new Date的初始化,设置日期为2019年3月31日。
var date = new Date('2019-03-31 00:00:00');
修改之后的运行结果如下,有两个用例的运行结果是不符合预期的。
1 |
Fri May 15 2015 18: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 |
Thu Mar 31 2016 00:00:00 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类的函数特殊处理导致的问题的更多相关文章
- JavaScript Date对象和函数 (一)
JavaScript_Date对象说明 Date中文为"日期"的意思,Date继承自Object对象,此对象提供操作,显示日期与时间的函数 Date对象构造函数 Date对象具有 ...
- 前端(十四)—— JavaScript常用类:Number、Date类、字符串、数组、Math类、正则
JS常用类:Number类.Date类.Math类.字符串.数组.正则 一.Number 1.常用数字 整数:10 小数:3.14 科学计数法:1e5 | 1e-5 正负无穷:Infinity | - ...
- js之序列化、eval和Date类用法
序列化 JSON.stringify() 将对象转换为字符串 JSON.parse() 将字符串转换为对象类型 示例 var jsonStr = '{"name":"le ...
- Javascript学习6 - 类、对象、继承
原文:Javascript学习6 - 类.对象.继承 Javasciprt并不像C++一样支持真正的类,也不是用class关键字来定义类.Javascript定义类也是使用function关键字来完成 ...
- PHP类和函数注释大全
每次要用PHP的某个功能的时候,都要去查一下,于是决定将PHP所有类和函数都整理出来,加上注释 大致实现 将php.jar文件解压,取出目录stubs 将stubs中的所有php文件中的注释去掉,并做 ...
- javascript常用工具类整理(copy)
JavaScript常用工具类 类型 日期 数组 字符串 数字 网络请求 节点 存储 其他 1.类型 isString (o) { //是否字符串 return Object.prototype.to ...
- JavaScript权威指南--类和模块
知识要点 每个javascript对象都是一个属性集合,相互之间没有任何联系.在javascript中也可以定义对象的类,让每个对象都共享某些属性,这种“共享”的特性是非常有用的.类的成员或实例都包含 ...
- 你可能不知道的 Date 类
Date 是 JS 中的重要的一个内置对象,其实例主要用于处理时间和日期,其时间基于 1970-1-1 (世界标准时间)起的毫秒数,时间戳长度为 13 位(不同于 Unix 时间戳的长度 10 位). ...
- JavaScript 中对变量和函数声明的“提前”
变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或 ...
随机推荐
- Selenium Webdriver元素定位的八种常用方式(转载)
转载自 https://www.cnblogs.com/qingchunjun/p/4208159.html 在使用selenium webdriver进行元素定位时,通常使用findElement或 ...
- spring mvc重定向
spring mvc重定向有三种方法. 1.return new ModelAndView("redirect:/toUrl"); 其中/toUrlt是你要重定向的url. 2.r ...
- python的基本用法(三)字符串常用函数
字符串常用函数 # s='.abcd.'# new_s=s.strip('.')#默认去掉字符串两边的空格和换行符,想去掉什么括号中就写什么# print('s',s)# print('new_s', ...
- mybatis pagehelper分页插件使用
使用过mybatis的人都知道,mybatis本身就很小且简单,sql写在xml里,统一管理和优化.缺点当然也有,比如我们使用过程中,要使用到分页,如果用最原始的方式的话,1.查询分页数据,2.获取分 ...
- JVM总括四-类加载过程、双亲委派模型、对象实例化过程
JVM总括四-类加载过程.双亲委派模型.对象实例化过程 目录:JVM总括:目录 一. 类加载过程 类加载过程就是将.class文件转化为Class对象,类实例化的过程,(User user = new ...
- MySQL优化(五) SQL 语句的优化 索引、explain
一.索引 1.分类 (1)主键索引:当一张表的某个字段设置为主键时,该字段就是主键索引: (2)唯一索引:索引列中的值必须是唯一的,但是允许为空值(可以存在多个null): (3)普通索引:基本索引类 ...
- python基础之Day11
一.函数是对象 函数是第一类对象的含义是函数可以被当作数据处理 二.函数的嵌套定义 def f1(): def f2(): print('from f2') f2()f1() 三.名称空间与作用域 1 ...
- CDH 安装
CDH 安装 市场上免费大数据框架主要有三个版本,原生的 Apache 版本,Cloudera(https://www.cloudera.com/) 公司研发的(Cloudera Distributi ...
- Spring 添加属性集中常见方法
//创建容器,索要对象, package cn.lijun.Test; import org.junit.Test;import org.springframework.context.Applica ...
- 如何查出sqlserver 性能瓶颈
转载地址:https://www.cnblogs.com/yanwenbink05/p/4047374.html