【问题标题】:javascript toISOString() ignores timezone offset [duplicate]javascript toISOString() 忽略时区偏移
【发布时间】: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;

标签: javascript datetime timezone-offset


【解决方案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/…”并说祝你好运......
  • 我在离线多年后登录只是为了注意这个答案允许格式化 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,可以使用toISOStringkeepOffset参数:

    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"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-22
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 2016-12-07
        • 2019-12-04
        • 2015-05-11
        • 1970-01-01
        相关资源
        最近更新 更多