无论时区如何,都在JavaScript中对日期输入进行单元测试处理

Rob*_*her 4 javascript unit-testing jasmine momentjs

我有一个表单,用户可以输入日期,即<input type="date">yyyy-MM-dd格式提交值.当我使用字符串创建Date对象时,它假设时区是用户浏览器设置的时区 - 这我想要的行为.

然后我使用日期值来对需要ISO日期/时间字符串的REST API进行查询.这没有问题,因为Date对象toISOString上的函数正确处理所有内容.

但是,当我单元测试此代码时 - 将输入设置为yyyy-MM-dd字符串然后断言输出是预期的ISO时间戳字符串,测试只能在特定时区中工作.有没有办法可以强制测试时区?

我尝试过使用Jasmine间谍做类似的事情:

var fixedTime = moment().zone(60).toDate()
spyOn(window, 'Date').andCallFake(function() {
    return fixedTime;
});
Run Code Online (Sandbox Code Playgroud)

但是鉴于构造函数有很多变体,并且很多方法被moment.js调用,这是非常不切实际的,并且让我进入无限循环.

Mat*_*int 9

JavaScript Date无法设置为特定时区.它只从运行环境中了解UTC和计算机的本地时间.

javascript的时区库,但我认为这不会对你有所帮助.

首先,要了解"ISO"是指ISO8601,它是一个定义相关格式集合的规范,例如YYYY-MM-DDTHH:MM:SS.

它是与UTC不同的概念,它指的是通用协调时间.UTC是我们所有时钟同步的计时系统,它使用GMT作为基础 - 也就是说,未经夏令时调整的本初子午线的生效时间.

放在一起,该Date.toISOString()方法将返回ISO8601格式的时间戳的UTC格式,例如2013-09-20T01:23:45Z.将Z在年底表示时间是UTC.

但是像2013-09-20ISO 这样的值仍然是ISO格式化的 - 它只是一整天都有精度,这意味着它不能携带任何时区信息.

当您使用<input type="date">时,产生的价值是不是Date类.它是一个包含ISO格式的字符串YYYY-MM-DD.您应该直接将它传递给您的应用程序.

现在,如果你要找的是完整的日期和时间,在当地时区的午夜,选择的日期,并调整到UTC,这是一个不同的故事.它肯定是可行的,但你必须明白它与传递日历日期不同.

最简单的方法是使用moment.js,如下所示:

var s = "2013-09-20";  // from your input's value property
var m = moment(s);
var result = m.toISOString();  // "2013-09-20T07:00:00.000Z"
Run Code Online (Sandbox Code Playgroud)

由于我的时区偏移为-07:00,因此调整了该值.

您可以毫不费力地执行此操作,但必须使用斜杠替换短划线,否则原始值将被解释为已经是UTC.

new Date(s.replace('-','/')).toISOString()
Run Code Online (Sandbox Code Playgroud)