6

我有一个表单,用户可以在其中输入日期,即<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;
});

但是鉴于构造函数的变体如此之多,并且它被 moment.js 调用的方式如此之多,这是非常不切实际的,并且让我陷入了无限循环。

4

1 回答 1

10

JavaScriptDate不能设置为特定的时区。它只知道 UTC 和运行环境的计算机本地时间。

javascript 的时区库,但我认为这对您没有帮助。

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

它是与 UTC 不同的概念,UTC 指的是通用协调时间。UTC 是我们都同步时钟的计时系统,它使用 GMT 作为其基础 - 即本初子午线的有效时间未针对夏令时进行调整。

总之,该Date.toISOString()方法将返回 ISO8601 格式时间戳的 UTC 形式,例如2013-09-20T01:23:45Z. Z末尾的 表示时间为 UTC 。

但是像这样的值2013-09-20仍然是 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"

该值已调整,因为我的时区偏移量为 -07:00。

您可以立即执行此操作,但您必须用斜杠替换破折号,否则原始值将被解释为好像它已经在 UTC 中一样。

new Date(s.replace('-','/')).toISOString()
于 2013-09-20T20:25:25.890 回答