iPhone上的JavaScript日期解析

33

我正在开发一个可以离线使用的JavaScript网站,目标是移动设备。其中一种移动设备是iPhone。

我正在尝试解析来自我们REST API的日期(JSON对象的成员)。我正在使用

Date.parse("2010-03-15 10:30:00");

这段代码在安卓设备上能够正常工作,但是在iPhone设备上却提示日期无效。

我应该如何格式化我的日期字符串才能被iPhone正确解析?


尝试这个解决方案,对我有效:https://dev59.com/N3A75IYBdhLWcg3w0sp9#3085993 - Matty J
6个回答

102

并非所有的浏览器都支持相同的日期格式。最好的方法是基于分隔符字符(-,  ,和:)对字符串进行拆分,然后将每个数组项传递给Date 构造函数:

var arr = "2010-03-15 10:30:00".split(/[- :]/),
    date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);

console.log(date);
//-> Mon Mar 15 2010 10:30:00 GMT+0000 (GMT Standard Time)

这在所有浏览器中都可以正常工作。


8
可能需要将 T 加入你的正则表达式以支持 ISO 8601。 - Tomas
1
只是想澄清一下,日期将在您所在的时区创建,对吗?例如,我在加利福尼亚州,这个例子适用于我:var arr =“2010-03-15 10:30:00”。split(/ [-:]/),date = new Date(arr [0],arr [1] -1,arr [2],arr [3],arr [4],arr [5]);未定义日期Mon Mar 15 2010 10:30:00 GMT-0700(PDT)...所以,我需要获取timezoneOffset并从返回的日期中减去那些分钟以获得UTC日期。还是我漏掉了什么? - jottos
2
谢谢你,非常有帮助。在iOS上无法解析ISO8601格式的Safari浏览器。但这个方法可以在任何地方使用。 - James Hollister
1
iOS现在似乎可以很好地解析ISO8601,但它假定提供的时间是UTC,而其他浏览器则不是。太好了。 - dmkc
更新 /[- :]//[- :\/]/ - bhagyas
显示剩余5条评论

7

对于UTC/GMT时间,您可以尝试以下方法:

    var arr = "2014-10-27T16:05:44+0000".split(/[\-\+ :T]/);

    var date = new Date();
    date.setUTCFullYear(arr[0]);
    date.setUTCMonth(arr[1] - 1);
    date.setUTCDate(arr[2]);
    date.setUTCHours(arr[3]);
    date.setUTCMinutes(arr[4]);
    date.setUTCSeconds(arr[5]);

日期对象在使用时会以本地时区正确显示。

在字符类的开头或结尾,不需要转义-,而在字符类的任何位置都不需要转义+。同样适用于:/[-+ :T]/ - Sam
对于以Z结尾的日期:const arr = isoFormattedString.split(/[\-\+ :TZ]/); - Elijah Mock

3
你遵循ISO 8601格式,可能会更加顺利。
Date.parse("2010-03-15T10:30:00");

// e.g.
var d = new Date( Date.parse("2010-03-15T10:30:00") );
console.log( d.toString() ); //Mon Mar 15 2010 10:30:00 GMT+0000 (BST)

2
如果你想让它在桌面浏览器中工作,大多数版本的IE无法解析那个日期。 - Andy E
6
安卓和iPhone的移动Webkit浏览器都不会。 - Morten
适用于Android 2.3及以上版本(但在iOS 5和6上无法运行)。 - Patrick Boos
此外,在ES5中,该解析方法假定UTC时区。在ES6中,它将是本地时区。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/parse - Jacob Jedryszek
这在2022年可行,难以置信! - Suraj Lulla

1

更新于2019-07-29: 不删除下面的现有内容,但我强烈建议您不要使用这种方法。我从错误中吸取了教训。不要覆盖JavaScript的现有方法。这会影响您代码的可移植性和性能。如果您无法获取ISO 8601(这是JS和大多数API的标准实践)-那么请更改该系统。或者,编写自己的函数,必须始终调用以生成Date对象。


如果您可以更正您的REST API以发送正确的ISO 8601日期时间,处理此问题的正确方法是使用一个正则表达式shim,允许所有浏览器处理ISO 8601日期。当然,它可能会慢一些,但是使用Javascript处理日期就像试图让猫进入水盆一样困难。
请记住,以下方法覆盖了原始的Date.parse方法。在较大的项目或有许多开发人员具有不同期望的情况下,这可能会带来问题。只有在您知道自己在做什么时才使用。
/**
 * Date.parse with progressive enhancement for ISO 8601 <https://github.com/csnover/js-iso8601>
 * © 2011 Colin Snover <http://zetafleet.com>
 * Released under MIT license.
 */
(function (Date, undefined) {
    var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
    Date.parse = function (date) {
        var timestamp, struct, minutesOffset = 0;

        // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
        // before falling back to any implementation-specific date parsing, so that’s what we do, even if native
        // implementations could be faster
        //              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9 ±    10 tzHH    11 tzmm
        if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
            // avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
            for (var i = 0, k; (k = numericKeys[i]); ++i) {
                struct[k] = +struct[k] || 0;
            }

            // allow undefined days and months
            struct[2] = (+struct[2] || 1) - 1;
            struct[3] = +struct[3] || 1;

            if (struct[8] !== 'Z' && struct[9] !== undefined) {
                minutesOffset = struct[10] * 60 + struct[11];

                if (struct[9] === '+') {
                    minutesOffset = 0 - minutesOffset;
                }
            }

            timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
        }
        else {
            timestamp = origParse ? origParse(date) : NaN;
        }

        return timestamp;
    };
}(Date));

https://github.com/csnover/js-iso8601


0

代码中有一个错误

var date = new Date();
date.setUTCFullYear(arr[0]);
date.setUTCMonth(arr[1] - 1);
date.setUTCDate(arr[2]);
date.setUTCHours(arr[3]);
date.setUTCMinutes(arr[4]);
date.setUTCSeconds(arr[5]);

解决方案。如果Date()是月底,而且所设置的月份天数比实际少,则结果会相差一个月。


-1
用字符串包装起来就可以了。由于Safari有一些独特的解析和格式化日期的方式,所以这样做会产生魔法般的效果。
Date.parse(String("2010-03-15 10:30:00"));

如果仍然遇到问题,请使用Moment.js

很高兴能帮忙。:-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接