Javascript 日期在 iOS 上无效

标签 javascript android ios cordova

我正在开发一个基于 Phonegap 的 iOS 应用程序,该应用程序已经为 Android 完成。以下几行适用于 Android,但不适用于 iOS。为什么?

var d = new Date("2015-12-31 00:00:00");
console.log(d.getDate() + '. ' + d.getMonth() + ' ' + d.getFullYear();

安卓的结果:
31.11 2015

在 iOS 上的结果:
NaN. NaN NaN

差异来自哪里?

最佳答案

您的日期字符串不是指定用于 new Date 的格式.规范中唯一的格式是 a simplified version of ISO-8601 ,在 ES5 (2009) 中添加。你的字符串不是那种格式,但它真的很接近。将其更改为规范中未包含但普遍支持的格式也很容易
四种选择:

  • 使用即将推出的Temporal功能(现在处于第 3 阶段)
  • 指定格式
  • 几乎普遍支持的未指定格式
  • 自己解析

  • 使用即将推出的Temporal特征
    Temporal proposal在 2021 年 8 月的此更新中处于第 3 阶段。您可以使用它来解析您的字符串,将其视为 UTC 或本地时间:
    将字符串视为 UTC:

    // (Getting the polyfill)
    const {Temporal} = temporal;
    
    const dateString = "2015-12-31 00:00:00";
    const instant = Temporal.Instant.from(dateString.replace(" ", "T") + "Z");
    // Either use the Temporal.Instant directly:
    console.log(instant.toLocaleString());
    // ...or get a Date object:
    const dt = new Date(instant.epochMilliseconds);
    console.log(dt.toString());
    <script src="https://unpkg.com/@js-temporal/polyfill/dist/index.umd.js"></script>

    或将其视为本地时间:

    // (Getting the polyfill)
    const {Temporal} = temporal;
    
    const dateString = "2015-12-31 00:00:00";
    
    console.log("Parsing as local time:");
    const tz = Temporal.Now.timeZone();
    const instant = tz.getInstantFor(dateString.replace(" ", "T"));
    console.log(instant.toLocaleString());
    const dt = new Date(instant.epochMilliseconds);
    console.log(dt.toString());
    <script src="https://unpkg.com/@js-temporal/polyfill/dist/index.umd.js"></script>
    Temporal不存在下面提到的指定日期/时间字符串格式在历史上没有指定时区的问题。
    指定格式
    如果将空格更改为 T ,您将符合规范:

    var dateString = "2015-12-31 00:00:00";
    // Treats the string as local time -- BUT READ BELOW, this varied
    var d = new Date(dateString.replace(" ", "T"));
    console.log(d.toString());

    (我假设您实际上并没有使用字符串文字,因此 replace 调用。)
    为了在旧浏览器中进行可靠的时区处理,您还需要附加 Z (对于 GMT/UTC)或时区指示符( +/- HH:MM ),因为在 ES5 中错误地指定了没有它们的字符串处理,在 ES2015 中更新,然后在 ES2016 中进一步更新。当前版本的现代浏览器现在遵循规范,其中说:
  • 如果字符串上有时间但没有时区指示符,则以本地时间解析字符串
  • 如果字符串上没有时间且没有时区指示符,则以 UTC
  • 解析字符串

    (ES5 said 始终默认为 UTC。ES2015 said 始终默认为本地时间。ES2016 是定义当前行为的位置。此后一直稳定。)
    所以最好包含一个时区指示器,特别是如果您必须支持旧版浏览器。请注意,它必须是 Z (UTC) 或 +/- HH:MM ;缩写如 CST是不允许的,因为它们没有标准。这是一个 UTC 示例:

    var dateString = "2015-12-31 00:00:00";
    // Treat the string as UTC
    var d = new Date(dateString.replace(" ", "T") + "Z");
    console.log(d.toString());

    几乎普遍支持的未指定格式
    规范中没有第二种格式,但几乎得到普遍支持,并且已经存在很长时间了:YYYY/MM/DD HH:MM:SS ,这被解释为本地时间。所以:

    var dateString = "2015-12-31 00:00:00";
    // Treats the string as local time
    var d = new Date(dateString.replace(/-/g, "/"));
    console.log(d.toString());

    不过,这又是未指明的行为,所以请谨慎购买。但它至少可以在 IE8+(可能更早)、Chrome 和其他任何使用 V8 JavaScript 引擎、Firefox 和 Safari 的平台上运行。
    自己解析
    自己解析该字符串也很容易。使用 ES2020+ 特性:

    function parseDate(str) {
        const [dateparts, timeparts] = str.split(" ");
        const [year, month, day] = dateparts.split("-");
        const [hours = 0, minutes = 0, seconds = 0] = timeparts?.split(":") ?? [];
        // Treats the string as UTC, but you can remove the `Date.UTC` part and use
        // `new Date` directly to treat the string as local time
        return new Date(Date.UTC(+year, +month - 1, +day, +hours, +minutes, +seconds));
    }
    
    const dateString = "2015-12-31 00:00:00";
    const d = parseDate(dateString);
    console.log(d.toString());

    或者只有 ES5 级别的功能(因为问题来自 2015 年):

    function parseDate(str) {
        var parts = str.split(" ");
        var dateparts = parts[0].split("-");
        var timeparts = (parts[1] || "").split(":");
        var year = +dateparts[0];
        var month = +dateparts[1];
        var day = +dateparts[2];
        var hours = timeparts[0] ? +timeparts[0] : 0;
        var minutes = timeparts[1] ? +timeparts[1] : 0;
        var seconds = timeparts[2] ? +timeparts[2] : 0;
        // Treats the string as UTC, but you can remove the `Date.UTC` part and use
        // `new Date` directly to treat the string as local time
        return new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds));
    }
    
    var dateString = "2015-12-31 00:00:00";
    var d = parseDate(dateString);
    console.log(d.toString());

    关于Javascript 日期在 iOS 上无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13363673/

    相关文章:

    javascript - 为什么 "ended"音频html5事件多次触发?

    javascript - 仅应用jquery mobile 页面的一部分?

    java - 将 HashMap<String,String> 放入带有节标题的 ListVIew 中

    android - Windows - Android SDK 管理器未列出任何要安装的平台或包

    java - Google Maps API v2 调用 getmap() 抛出 NullPointerException

    ios - 在 Swift 中使用可编码扩展更新对象属性

    ios - 代码 7 : linker command failed with exit code 1 (use -v to see invocation)

    javascript - 是否有 TCP 套接字库/协议(protocol)可以进行消息分帧并受 JS 和 C# 支持?

    javascript - 如何使用 jquery 或 javascript 获取 tabcontainer ID?

    ios - 如何正确且线程安全地删除 Realm 中的对象