如何在JavaScript中使用ISO 8601格式化带有时区偏移的日期?

如何在JavaScript中使用ISO 8601格式化带有时区偏移的日期?,javascript,timezone,date-formatting,Javascript,Timezone,Date Formatting,目标:找到本地时间和UTC时间偏移量,然后按照以下格式构建URL 示例URL:/Actions/Sleep?持续时间=2002-10-10T12:00:00−05:00 该格式基于W3C建议: 文件说: 例如,2002-10-10T12:00:00−二○○二年十月十日中午五时, 美国的中央夏令时和东部标准时间) 等于2002-10-10T17:00:00Z,比2002-10-10T12:00:00Z晚五小时 根据我的理解,我需要通过new Date()找到本地时间,然后使用getTimezon

目标:找到
本地时间
UTC时间偏移量
,然后按照以下格式构建URL

示例URL:/Actions/Sleep?持续时间=2002-10-10T12:00:00−05:00

该格式基于W3C建议:

文件说:

例如,2002-10-10T12:00:00−二○○二年十月十日中午五时, 美国的中央夏令时和东部标准时间) 等于2002-10-10T17:00:00Z,比2002-10-10T12:00:00Z晚五小时

根据我的理解,我需要通过new Date()找到本地时间,然后使用getTimezoneOffset()函数计算差值,然后将其附加到字符串的末尾

1.使用格式获取本地时间

var local = new Date().format("yyyy-MM-ddThh:mm:ss"); //today (local time)
输出

2013-07-02T09:00:00
7
2.按小时获取UTC时间偏移

var offset = local.getTimezoneOffset() / 60;
输出

2013-07-02T09:00:00
7
3.构造URL(仅时间部分)

输出:

2013-07-02T09:00:00-7:00
上述输出表示我的当地时间为2013/07/02上午9点,与UTC的差异为7小时(UTC比当地时间提前7小时)

到目前为止,它似乎是有效的,但如果getTimezoneOffset()返回负值,如-120,该怎么办?


我想知道在这种情况下格式应该是什么样子,因为我无法从W3C文档中理解。提前感谢。

以下内容应能正常工作,适用于所有浏览器(感谢@MattJohnson提供的提示)

函数字符串(日期){
var tzo=-date.getTimezoneOffset(),
dif=tzo>=0?'+':'-',
pad=函数(num){
var norm=Math.floor(Math.abs(num));
返回值(范数<10?'0':'')+norm;
};
返回日期。getFullYear()+
“-”+pad(date.getMonth()+1)+
“-”+pad(date.getDate())+
'T'+pad(date.getHours())+
“:”+pad(date.getMinutes())+
“:”+pad(date.getSeconds())+
dif+衬垫(tzo/60)+
“:”+pad(tzo%60);
}
var dt=新日期();
log(toIsoString(dt))
getTimezoneOffset()
返回引用的规范所需格式的相反符号

这种格式也称为,或者更准确地说是

在此格式中,UTC用
Z
表示,而所有其他格式用UTC的偏移量表示。其含义与JavaScript相同,但减法的顺序相反,因此结果带有相反的符号

此外,本机
日期
对象上没有名为
格式
的方法,因此#1中的函数将失败,除非您使用库来实现这一点。参考

如果您正在寻找一个可以直接使用这种格式的库,我建议您试试。事实上,这是默认格式,因此您可以简单地执行以下操作:

var m = moment();    // get "now" as a moment
var s = m.format();  // the ISO format is the default so no parameters are needed

// sample output:   2013-07-01T17:55:13-07:00

这是一个经过良好测试的跨浏览器解决方案,并具有许多其他有用的功能。

这是我为客户端时区提供的功能,重量轻且简单

  function getCurrentDateTimeMySql() {        
      var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
      var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, 19).replace('T', ' ');
      var mySqlDT = localISOTime;
      return mySqlDT;
  }
就我的两封信

我在datetimes中遇到了这个问题,所以我所做的是:

const moment = require('moment-timezone')

const date = moment.tz('America/Bogota').format()
然后将日期保存到db,以便能够从某个查询中进行比较


要安装
时刻时区

npm i moment-timezone
选中此项:

函数dateToLocalISO(日期){
const off=date.getTimezoneOffset()
常数absoff=Math.abs(关闭)
return(新日期(Date.getTime()-off*60*1000).toISOString().substr(0,23)+
(关闭>0?'-':'+')+
数学地板(绝对值/60).toFixed(0).padStart(2,'0')+':'+
(绝对值%60).toString().padStart(2,'0'))
}
//测试它:
d=新日期()
dateToLocalISO(d)
//==>“2019-06-21T16:07:22.181-03:00”
//类似于:
力矩=要求(‘力矩’)
力矩(d).格式('YYYY-MM-DDTHH:MM:ss.SSSZ')
//==>“2019-06-21T16:07:22.181-03:00”

我认为值得考虑的是,只需对标准库进行一次API调用,就可以获得所需的信息

new Date().toLocaleString( 'sv', { timeZoneName: 'short' } );

// produces "2019-10-30 15:33:47 GMT−4"
如果要添加“T”分隔符、删除“GMT-”或在末尾附加“:00”,则必须进行文本交换

但是如果你想玩的话,你可以很容易地玩。例如,使用12小时的时间或省略秒数等

请注意,我使用瑞典作为语言环境,因为它是使用ISO8601格式的国家之一。我认为大多数ISO国家使用这种“GMT-4”格式表示时区偏移量,而加拿大则使用时区缩写,例如“EDT”表示东部夏时制

您可以从较新的标准i18n函数“Intl.DateTimeFormat()”中获得相同的结果
但您必须通过选项告诉它包含时间,否则它只会给出日期。

无需片刻。js:这里有一个完整的往返答案,来自输入类型的“datetime local”,该类型在GMT时向UTCseconds输出一个等地字符串并返回:

<input type="datetime-local" value="2020-02-16T19:30">

isoLocal="2020-02-16T19:30"
utcSeconds=new Date(isoLocal).getTime()/1000

//here you have 1581899400 for utcSeconds

let isoLocal=new Date(utcSeconds*1000-new Date().getTimezoneOffset()*60000).toISOString().substring(0,16)
2020-02-16T19:30

isoLocal=“2020-02-16T19:30”
utcSeconds=新日期(isoLocal).getTime()/1000
//这是UTC秒的1581899400
设isoLocal=new Date(utcSeconds*1000 new Date().getTimezoneOffset()*60000.toISOString().substring(0,16)
2020-02-16T19:30

对于那些只想在本地时区中以YYYY-MM-DD格式显示今天日期的人来说,我的答案略有不同

让我澄清一下:

我的目标:用户时区中获取今天的日期,但格式为ISO8601(YYYY-MM-DD)

代码如下:

new Date().toLocaleDateString("sv") // "2020-02-23" // 

这是因为瑞典语言环境使用ISO 8601格式。

以下是我为此使用的函数:

function localToGMTStingTime(localTime = null) {
    var date = localTime ? new Date(localTime) : new Date();
    return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)).toISOString();
};

function GMTToLocalStingTime(GMTTime = null) {
    var date = GMTTime ? new Date(GMTTime) : new Date();;
    return new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString();
};

您可以通过一些简单的扩展方法来实现这一点。下面的日期扩展方法仅返回ISO格式的时区组件,然后您可以为日期/时间部分定义另一个,并将它们组合为完整的日期-时间偏移字符串

Date.prototype.getISOTimezoneOffset = function () {
    const offset = this.getTimezoneOffset();
    return (offset < 0 ? "+" : "-") + Math.floor(Math.abs(offset / 60)).leftPad(2) + ":" + (Math.abs(offset % 60)).leftPad(2);
}

Date.prototype.toISOLocaleString = function () {
    return this.getFullYear() + "-" + (this.getMonth() + 1).leftPad(2) + "-" +
        this.getDate().leftPad(2) + "T" + this.getHours().leftPad(2) + ":" +
        this.getMinutes().leftPad(2) + ":" + this.getSeconds().leftPad(2) + "." +
        this.getMilliseconds().leftPad(3);
}

Number.prototype.leftPad = function (size) {
    var s = String(this);
    while (s.length < (size || 2)) {
        s = "0" + s;
    }
    return s;
}
我知道现在是2020年,大多数人可能都在使用Moment.js,但一个简单的复制和可复制解决方案有时仍然很方便

(我拆分日期/时间和偏移方法的原因
function setDate(){
    var now = new Date();
    now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
    var timeToSet = now.toISOString().slice(0,16);

    /*
        If you have an element called "eventDate" like the following:

        <input type="datetime-local" name="eventdate" id="eventdate" />

        and you would like to  set the current and minimum time then use the following:
    */

    var elem = document.getElementById("eventDate");
    elem.value = timeToSet;
    elem.min = timeToSet;
}