为什么新的Date()。toISOString()正在失去时区?

时间:2017-06-24 06:51:59

标签: javascript

我不想使用像momentjs这样的外部库,我想自己创建一个格式化的日期字符串。我试图使用new Date().toISOString(),但它失去了时区。

此:

new Date()

给出:

  

Sat Jun 24 2017 09:32:10 GMT+0300 (RTZ 2 (winter))

new Date().toISOString();

给出:

  

2017-06-24T06:32:22.990Z

09:32:10是正确的时间,因此06:32:22会丢失时区信息。

要添加到此,看起来new Date().toLocaleString()几乎可以满足我的需要。在最后几个小时是正确的。结果:"24.06.2017, 11:37:05"

3 个答案:

答案 0 :(得分:1)

来自类似question

的回答
  

moment.js很棒,但有时你不想为简单的东西拉大量依赖。

     

以下也有效:

     

var tzoffset =(new Date())。getTimezoneOffset()* 60000; //以毫秒为单位的偏移量       var localISOTime =(new Date(Date.now() - tzoffset))。toISOString()。slice(0,-1);       // => '2015-01-26T06:40:36.181'

     

切片(0,-1)摆脱代表祖鲁时区的尾随Z,可以用你自己的代替。

答案 1 :(得分:0)

在更新的“问题”中,您建议使用toLocaleString(),是的,这会将日期添加到用户当前的语言环境中(相对于始终使用GMT的toISOString),但是您丢失了ISO 8601格式。

我使用的解决方案是将语言环境设置为使用8601的国家/地区,例如。

const d = new Date();
const dateStr = d.toLocaleString( 'sv' );
// locale 'sv' is Sweden so you get ISO 8601 format

结果将带有空格而不是'T',但这在标准中是合法的。

答案 2 :(得分:0)

JavaScript Date对象不存储时区信息。他们使用系统时区,仅此而已。因此,一旦拥有Date,您将丢失时区信息(当前系统的时区除外)。

您可以从Date获取当前时区偏移量,并可以使用该时区偏移量以ISO-8601格式形成字符串:

function pad(x, width = 2, char = "0") {
    return String(x).padStart(width, char);
}
function toLocalISOString(dt) {
    const offset = dt.getTimezoneOffset();
    const absOffset = Math.abs(offset);
    const offHours = Math.floor(absOffset / 60);
    const offStr = pad(offHours) + ":" + pad(absOffset - offHours * 60);
    return [
        String(dt.getFullYear()),
        "-",
        pad(dt.getMonth() + 1),
        "-",
        pad(dt.getDate()),
        "T",
        pad(dt.getHours()),
        ":",
        pad(dt.getMinutes()),
        ":",
        pad(dt.getSeconds()),
        ".",
        dt.getMilliseconds(),
        offset <= 0 ? "+" : "-",
        offStr
    ].join("");
}
console.log(toLocalISOString(new Date()));

...但是偏移量不是时区;偏移量仅告诉您日期/时间与UTC的时差是多少小时,而不是规则的规定。

在任何现代浏览器(不是IE11)中,您都可以从Intl.DateTimeFormat().resolvedOptions().timeZone获取实际时区,这将为您提供IANA字符串,例如"Europe/London"。您可以将其包含在自定义字符串中,也许有条件地基于获取它的方式:

function pad(x, width = 2, char = "0") {
    return String(x).padStart(width, char);
}
function toLocalISOString(dt) {
    const offset = dt.getTimezoneOffset();
    const absOffset = Math.abs(offset);
    const offHours = Math.floor(absOffset / 60);
    const offStr = pad(offHours) + ":" + pad(absOffset - offHours * 60);
    let parts = [
        String(dt.getFullYear()),
        "-",
        pad(dt.getMonth() + 1),
        "-",
        pad(dt.getDate()),
        "T",
        pad(dt.getHours()),
        ":",
        pad(dt.getMinutes()),
        ":",
        pad(dt.getSeconds()),
        ".",
        dt.getMilliseconds(),
        offset <= 0 ? "+" : "-",
        offStr
    ];
    if (typeof Intl === "object" && Intl.DateTimeFormat) {
        try {
            parts.push(
                " (",
                Intl.DateTimeFormat().resolvedOptions().timeZone,
                ")"
            );
        } catch (e) {
        }
    }
    return parts.join("");
}
console.log(toLocalISOString(new Date()));