javascript toISOString() 忽略时区偏移
Posted
技术标签:
【中文标题】javascript toISOString() 忽略时区偏移【英文标题】:javascript toISOString() ignores timezone offset [duplicate] 【发布时间】:2012-06-05 12:27:09 【问题描述】:我现在正在尝试将 Twitter 日期时间转换为本地 iso 字符串(用于 prettyDate)2 天。我只是弄错了当地时间..
我正在使用以下函数:
function getLocalISOTime(twDate)
var d = new Date(twDate);
var utcd = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(),
d.getMinutes(), d.getSeconds(), d.getMilliseconds());
// obtain local UTC offset and convert to msec
localOffset = d.getTimezoneOffset() * 60000;
var newdate = new Date(utcd + localOffset);
return newdate.toISOString().replace(".000", "");
在 newdate 中一切正常,但 toISOString() 再次将其扔回原来的时间...... 谁能帮我从 Twitterdate 中获取 iso 中的当地时间,格式为: 2012 年 5 月 31 日星期四 08:33:41 +0000
【问题讨论】:
你最后描述的格式不是ISO-8601E格式(另见Date.toISOString。你可以很容易地实现你想要的格式;它非常接近你用dateObj.toString()
得到的格式. 试试看。
谢谢!结束了: var d = new Date(twDate); return new Date(d.toISOString().replace("Z", "-02:00")).toISOString().replace(".000", "");不是最漂亮的解决方案,但适用于我的时区。
@Bergi:自相矛盾的是,旧问题不能与新问题重复;)
这是一个没有任何手动时区设置的方法: var now = new Date(); now.setMinutes(now.getMinutes() - now.getTimezoneOffset()); var timeToSet = now.toISOString().slice(0,16); var elem = document.getElementById("eventdate"); elem.value = timeToSet; elem.min = timeToSet;
【参考方案1】:
moment.js
很棒,但有时您不想为简单的事情提取大量依赖项。
以下也可以:
var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -1);
console.log(localISOTime) // => '2015-01-26T06:40:36.181'
slice(0, -1)
去掉了代表祖鲁时区的尾随 Z
,可以用您自己的时区替换。
【讨论】:
简短而简单 - 太棒了!为了使其更具人类可读性,我将 .toISOString().slice(0,-5).replace("T", " ");在您的解决方案结束时。 时间以 UTC(协调世界时)表示,带有一个特殊的 UTC 指示符(“Z”)。 太好了,谢谢。在这里,作为一个带有可选日期参数的函数: function localISOTime(d) if (!d) d = new Date() var tzoffset = d.getTimezoneOffset() * 60000; //以毫秒为单位的偏移量 return (new Date(Date.now() - tzoffset)).toISOString().slice(0, -1); 为什么是“-”(现在的 tzoffset)? 您的解决方案不显示您的当地时间。它欺骗了日期,认为您的 UTC 日期是您的本地日期。你不应该改变你的日期你应该添加你的时区偏移【参考方案2】:我不使用moment
的解决方案是将其转换为时间戳,添加时区偏移量,然后转换回日期对象,然后运行toISOString()
var date = new Date(); // Or the date you'd like converted.
var isoDateTime = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString();
【讨论】:
我喜欢这种方法。您的示例无法按原样工作,因为您尚未定义日期。如果你在前面加上 var date = new Date();以您的示例为例,它有效。 不使用库的绝佳解决方案,谢谢! 它有效!但我不明白你为什么乘以 60000 ? :s 漂亮而且非常简单。谢谢你。请注意:它确实在字符串末尾保留了“Z”,这在技术上是错误的,但很容易编辑。 @betoharres 就是将时区偏移量转换为毫秒,这就是getTime所在。【参考方案3】:moment.js FTW!!!
只需将您的日期转换为一个时刻,然后随心所欲地对其进行操作:
var d = new Date(twDate);
var m = moment(d).format();
console.log(m);
// example output:
// 2016-01-08T00:00:00-06:00
http://momentjs.com/docs/
【讨论】:
这不是一个正确的答案...你能用 Moment.js 给出正确的答案吗?如果这是一个真正的答案,我可以每次回答“x86 FTW !!! intel.com/content/dam/www/public/us/en/documents/manuals/…”并说祝你好运...... When is “use jQuery” not a valid answer to a javascript question? 我在离线多年后登录只是为了注意这个答案允许格式化 Date 以便.NET API 接收带有 TimeZone 的日期并正确反序列化它。在 js 项目中拥有 moment.js 并没有那么糟糕,知道 ECMAScript 中的 Date API 缺少多少功能。 我在离线多年后登录只是为了注意答案中提供的解决方案允许在 ISO8601 中正确序列化本地时间。 moment.js 的存在是因为 ECMAScript 的 Date API 很烂。【参考方案4】:下面这个日期函数不需要额外的脚本库就可以达到预期的效果。基本上它只是一个简单的以正确格式连接的日期组件,以及对 Date 对象原型的扩充。
Date.prototype.dateToISO8601String = function()
var padDigits = function padDigits(number, digits)
return Array(Math.max(digits - String(number).length + 1, 0)).join(0) + number;
var offsetMinutes = this.getTimezoneOffset();
var offsetHours = offsetMinutes / 60;
var offset= "Z";
if (offsetHours < 0)
offset = "-" + padDigits(offsetHours.replace("-","") + "00",4);
else if (offsetHours > 0)
offset = "+" + padDigits(offsetHours + "00", 4);
return this.getFullYear()
+ "-" + padDigits((this.getUTCMonth()+1),2)
+ "-" + padDigits(this.getUTCDate(),2)
+ "T"
+ padDigits(this.getUTCHours(),2)
+ ":" + padDigits(this.getUTCMinutes(),2)
+ ":" + padDigits(this.getUTCSeconds(),2)
+ "." + padDigits(this.getUTCMilliseconds(),2)
+ offset;
Date.dateFromISO8601 = function(isoDateString)
var parts = isoDateString.match(/\d+/g);
var isoTime = Date.UTC(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
var isoDate = new Date(isoTime);
return isoDate;
function test()
var dIn = new Date();
var isoDateString = dIn.dateToISO8601String();
var dOut = Date.dateFromISO8601(isoDateString);
var dInStr = dIn.toUTCString();
var dOutStr = dOut.toUTCString();
console.log("Dates are equal: " + (dInStr == dOutStr));
用法:
var d = new Date();
console.log(d.dateToISO8601String());
希望这对其他人有所帮助。
编辑
更正了 cmets 中提到的 UTC 问题,并将 Alex 归功于 dateFromISO8601
函数。
【讨论】:
这对我有帮助,我认为这是一个更好的答案。 虽然您获得了正确的本地时间,但您通过添加“Z”代替时区来错误地将时间与祖鲁时间相关联。如果您将由此创建的时间投入到任何符合 ISO 标准的应用程序中,您将不会得到正确的时间作为回报。您应该致电.getTimezoneOffset()
,然后将分钟计算为小时格式,以使您的 ISO 日期符合要求。
那是错误的,我担心不起作用
现在您获得了 UTC 值,但将它们与本地时区偏移量结合起来?
按照代码当前的情况,这不会输出符合 ISO8601 的字符串,并且会为除 UTC 时区之外的所有字符串输出不正确的时间。符合 ISO8601 的偏移量采用 +HH:MM
而不是 +HH00
的形式。如果您要使用+/-NN:NN
后缀作为本地时区与Z
之间的偏移小时/分钟,则需要使用本地月份、日期、小时、分钟、秒和毫秒,而不是UTC 版本。此函数应称为Date.prototype.toLocalISOString
,它更符合标准Date
函数。 dateFromISO8601
是不必要的,因为 new Date()
有效。【参考方案5】:
获取当前日期和时间会很有帮助。
var date=new Date();
var today=new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().replace(/T/, ' ').replace(/\..+/, '');
【讨论】:
【参考方案6】:使用moment.js
,可以使用toISOString
的keepOffset
参数:
toISOString(keepOffset?: boolean): string;
moment().toISOString(true)
【讨论】:
【参考方案7】:Moment js 解决方案是
var d = new Date(new Date().setHours(0,0,0,0));
m.add(m.utcOffset(), 'm')
m.toDate().toISOString()
// output "2019-07-18T00:00:00.000Z"
【讨论】:
以上是关于javascript toISOString() 忽略时区偏移的主要内容,如果未能解决你的问题,请参考以下文章
date-fns 中的啥方法相当于 moment().toISOString()
TypeError:formats.dateTimeString.toISOString 不是函数
toISOString 在 iPhone 中无法与 Cordova Ionic 一起使用