如何使用 JavaScript 中的 ISO8601格式化具有时区偏移的日期?

目标: 找到 local timeUTC time offset,然后按照以下格式构造 URL。

示例 URL: /Actions/Sleep?duration=2002-10-10T12:00:00−05:00

这种格式是基于 W3C推荐标准的,文档上说:

例如,2002-10-10 T12:00:00-05:00(2002年10月10日中午, 美国中央夏令时和东部标准时) 等于2002-10-10 T17:00:00Z,比2002-10-10 T12:00:00Z 晚5个小时。

所以根据我的理解,我需要找到我的本地时间由 new Date(),然后使用 getTimezoneOffset()函数来计算差,然后附加到字符串的结尾。

  1. 使用 format获取当地时间

    var local = new Date().format("yyyy-MM-ddThh:mm:ss"); // 2013-07-02T09:00:00
    
  2. 得到 UTC 时间的小时偏移

    var offset = local.getTimezoneOffset() / 60; // 7
    
  3. 构造 URL (仅限时间部分)

    var duration = local + "-" + offset + ":00"; // 2013-07-02T09:00:00-7:00
    

上面的输出意味着我的本地时间是2013/07/029 am,与 UTC 的差距是7小时(UTC 比本地时间提前7小时)

到目前为止,它似乎工作,但如果 getTimezoneOffset()返回负值喜欢 -120?

我想知道在这种情况下格式应该是什么样子的,因为我无法从 W3C 文档中找到答案。

263161 次浏览

下面是一个简单的 helper 函数,它将为您格式化 JS 日期。

function toIsoString(date) {
var tzo = -date.getTimezoneOffset(),
dif = tzo >= 0 ? '+' : '-',
pad = function(num) {
return (num < 10 ? '0' : '') + num;
};


return date.getFullYear() +
'-' + pad(date.getMonth() + 1) +
'-' + pad(date.getDate()) +
'T' + pad(date.getHours()) +
':' + pad(date.getMinutes()) +
':' + pad(date.getSeconds()) +
dif + pad(Math.floor(Math.abs(tzo) / 60)) +
':' + pad(Math.abs(tzo) % 60);
}


var dt = new Date();
console.log(toIsoString(dt));

getTimezoneOffset()返回您引用的规范所要求的格式的相反符号。

这种格式也称为 ISO8601,或者更确切地说是 RFC3339

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

另外,在本机 Date对象上没有称为 format的方法,因此 # 1中的函数将失败,除非您使用库来实现这一点。请参阅 这份文件

如果您正在寻找一个可以直接使用这种格式的库,我建议您尝试使用 等一下 JS。事实上,这是默认格式,所以您可以简单地这样做:

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;
}

这只是我的意见

我正面临着这个问题的日期时间,所以我所做的是:

const moment = require('moment-timezone')


const date = moment.tz('America/Bogota').format()

然后将日期保存为 db,以便能够从某个查询中对其进行比较。


安装 moment-timezone

npm i moment-timezone

看看这个:

function dateToLocalISO(date) {
const off    = date.getTimezoneOffset()
const absoff = Math.abs(off)
return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) +
(off > 0 ? '-' : '+') +
Math.floor(absoff / 60).toFixed(0).padStart(2,'0') + ':' +
(absoff % 60).toString().padStart(2,'0'))
}


// Test it:
d = new Date()


dateToLocalISO(d)
// ==> '2019-06-21T16:07:22.181-03:00'


// Is similar to:


moment = require('moment')
moment(d).format('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小时或者省略秒数等等,你可以很容易的使用 其他选择

请注意,我使用瑞典作为区域设置,因为它是使用 ISO 8601格式的国家之一。我认为大多数 ISO 国家使用这种“ GMT-4”格式来表示时区偏移,除了加拿大使用时区缩写,例如“ EDT”表示东部白天时间。

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

不需要 Moment.js: 下面是一个完整的往返回答,来自于 输入类型的“ datetime-local”,它在 GMT 和返回时将一个 ISOLocal 字符串输出到 UTC 秒:

<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

我的回答是,对于那些只想以 YYYY-MM-DD 格式将今天的日期放在当地时区的人来说,稍微有些变化。

让我把话说清楚:

我的目标: 用户的时区中获取 今天的日期,但是 < strong > 格式为 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();
};

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

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;
}

示例用法:

var date = new Date();
console.log(date.toISOLocaleString() + date.getISOTimezoneOffset());
// Prints "2020-08-05T16:15:46.525+10:00"

我知道现在是2020年,大多数人可能已经在使用 Moment.js 了,但是一个简单的拷贝和可粘贴的解决方案有时还是很方便的。

(我将日期/时间和偏移量方法分开的原因是因为我使用了一个旧的 约会库,它已经提供了一个带有自定义格式说明符的灵活的 toString方法,只是没有包含时区偏移量。因此,我为没有这个库的任何人添加了 toISOLocaleString。)

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;
}

只使用没有库的 javascript 实际上只有两行:

var dt = new Date();
// Date in UTC and ISO format: "2021-11-30T20:33:32.222Z"
console.log(dt.toISOString());
var dtOffset = new Date(dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset()));
// Date in EST and ISO format: "2021-11-30T15:33:32.222Z"
console.log(dtOffset.toISOString());

new Date()将默认为当前语言环境,但是如果需要,您也可以直接指定它:

var dt = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));

考虑使用矩(如 Matt 的回答)。

从版本 2.20.0开始,您可以调用. toISOString (true)来防止 UTC 转换:

console.log(moment().toISOString(true));


// sample output:   2022-04-06T16:26:36.758+03:00
let myDate = new Date(dateToBeFormatted * 1000); // depends if you have milliseconds, or seconds, then the * 1000 might be not, or required.
timeOffset = myDate.getTimezoneOffset();
myDate = new Date(myDate.getTime() - (timeOffset * 60 * 1000));


console.log(myDate.toISOString().split('T')[0]);

灵感来自 https://stackoverflow.com/a/29774197/11127383,包括 时区偏移注释

卢森:

DateTime.now().toISODate() // 2022-05-23

一个简单的方法:

//using a sample date
let iso_str = '2022-06-11T01:51:59.618Z';
let d = new Date(iso_str);


let tz = 'America/Santiago'
let options = {
timeZone:tz ,
timeZoneName:'longOffset',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
fractionalSecondDigits: 3
}




str_locale = d.toLocaleString("sv-SE",options);
iso_str_tz = str_locale.replace(/(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2}),(\d+)\s+/,'$1-$2-$3T$4:$5:$6.$7').replace('GMT−', '-' ).replace('GMT+','+')




console.log('iso_str               : ',iso_str);
console.log('str_locale            : ',str_locale);
console.log('iso_str_tz            : ',iso_str_tz);
console.log('iso_str_tz --> date   : ',new Date(iso_str_tz));
console.log('iso_str_tz --> iso_str: ',new Date(iso_str_tz).toISOString());
  • 日期到 ISO 字符串,
  • 与本地(计算机)时区,
  • 不管有没有毫秒

国际标准化组织编号: https://en.wikipedia.org/wiki/ISO_8601

如何使用: ToIsoLocalTime (新日期())

function toIsoLocalTime(value) {
if (value instanceof Date === false)
value = new Date();
const off = value.getTimezoneOffset() * -1;
const del = value.getMilliseconds() ? 'Z' : '.'; // have milliseconds ?
value = new Date(value.getTime() + off * 60000); // add or subtract time zone
return value
.toISOString()
.split(del)[0]
+ (off < 0 ? '-' : '+')
+ ('0' + Math.abs(Math.floor(off / 60))).substr(-2)
+ ':'
+ ('0' + Math.abs(off % 60)).substr(-2);
}


function test(value) {
const event = new Date(value);
console.info(value + ' -> ' + toIsoLocalTime(event) + ', test = ' + (event.getTime() === (new Date(toIsoLocalTime(event))).getTime() ));
}


test('2017-06-14T10:00:00+03:00'); // test with timezone
test('2017-06-14T10:00:00'); // test with local timezone
test('2017-06-14T10:00:00Z'); // test with UTC format
test('2099-12-31T23:59:59.999Z'); // date with milliseconds
test((new Date()).toString()); // now

使用 暂时的

Temporal.Now.zonedDateTimeISO().toString()
// '2022-08-09T14:16:47.762797591-07:00[America/Los_Angeles]'

省略小数秒和 IANA 时区:

Temporal.Now.zonedDateTimeISO().toString({
timeZoneName: "never",
fractionalSecondDigits: 0
})
// '2022-08-09T14:18:34-07:00'

注意: 时态目前(2022)作为 填料可用,但不久将在主流浏览器中可用。

使用 moment.js,可以使用 toISOStringkeepOffset参数:

toISOString(keepOffset?: boolean): string;

moment().toISOString(true)

使用 翻译: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校对: 奇芳校的替代方法

import dayjs from "dayjs"


const formattedDateTime = dayjs(new Date()).format()


console.log(formattedDateTime) // Prints 2022-11-09T07:49:29+03:00

我找到了另一个更简单的解决办法:

let now = new Date();
// correct time zone offset for generating iso string
now.setMinutes(now.getMinutes() - now.getTimezoneOffset())
now = now.toISOString();

我通过从当前日期对象中减去时区偏移量来撤消时区偏移量。 来自 date 对象的 UTC 时间现在指向本地时间。 这使您有可能获得当地时间的 ISO 日期。