android Javascript日期在iOS上无效

rm5edbpk  于 2022-12-16  发布在  Android
关注(0)|答案(7)|浏览(123)

我正在开发一个基于Phonegap的iOS应用程序,这已经在Android上实现了。下面的代码行在Android上运行良好,但在iOS上却不行。为什么?

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

Android的结果:

31.11 2015

iOS上的结果:

NaN. NaN NaN

差异从何而来?

cygmwpex

cygmwpex1#

您的日期字符串不是指定用于new Date的格式。规范中的唯一格式是ISO-8601的简化版本(2009年在ES 5中添加,并在ES 2015和ES 2016中更新),以及Date.prototype.toString输出的格式。您的字符串不是这两种格式中的任何一种,但它非常接近于ISO-8601格式。将它更改为规范中没有的格式也很容易,但它得到了普遍支持
为您提供四个选项:

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

使用即将推出的Temporal功能

截至2021年8月的更新,Temporal proposal处于阶段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>

或将其视为本地时间:
一个二个一个一个
Temporal不存在下面提到的问题,即指定的日期/时间字符串格式在没有指定时区时曾经存在的问题。

类似ISO-8601的格式

如果将空间更改为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),因为没有它们的字符串处理在ES 5中被错误地指定,在ES 2015中更新,然后在ES 2016中进一步更新。

  • 如果字符串中有时间,但没有时区指示符,则用本地时间解析字符串
  • 如果字符串中没有时间,也没有时区指示符,则以UTC格式解析字符串

(ES5 ES 2015表示始终默认为本地时间。ES 2016是定义当前行为的地方。此后一直保持稳定。)
所以最好包含一个时区指示符,特别是当你必须支持老版本的浏览器时,注意它必须是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的系统中工作。

自己解析

您自己也可以轻松解析该字符串。使用ES 2020+功能:

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());

或仅具有ES 5级功能(因为问题是从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());
laawzig2

laawzig22#

我不能告诉你为什么,也许是因为iOS不像Android那样支持Javascript日期功能,或者支持不同的格式?
但我可以给予你一个变通办法:

var s = "2015-12-31 00:00:00".split(" ")[0].split("-"),
    d = new Date( s[0], s[1], s[2], 0, 0, 0 );

console.log(d);
var s = "2015-12-31 00:00:00".replace(/[ :]/g, "-").split("-"),
    d = new Date( s[0], s[1], s[2], s[3], s[4], s[5] );

console.log(d);
gfttwv5a

gfttwv5a3#

一个同时适用于IOS和Android并在不需要时避免字符串操作的解决方案是

let fullDate = "1991-03-29 00:00:00";
let date = new Date(fullDate);

// In case its IOS, parse the fulldate parts and re-create the date object.
if(Number.isNaN(date.getMonth())) {
  let arr = fullDate.split(/[- :]/);
  date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
}
agxfikkp

agxfikkp4#

如果有人还在找的话。
在IE,Safari,IOS-FF,IOS-Safari等中为我工作。

getIOSSaveDateObj = function(dateString){
    if(dateString.indexOf('-') > 0){
        var arr = dateString.split(/[- :]/);
        var date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
    }else{
        var arr = dateString.split(/[. :]/);
        var date = new Date(arr[2], arr[1]-1, arr[0], arr[3], arr[4], arr[5]);
    }
    return date;
}
iqxoj9l9

iqxoj9l95#

我很难解决这个问题,我终于找到了一个更简单的解决方案,使用了moment.js。你需要做的不多,只是声明每个设备中的日期和作品。

qacovj5a

qacovj5a6#

尝试使用var d = new Date("2015/12/31 00:00:00");对我有效。

57hvy0tb

57hvy0tb7#

还有

var d = new Date("2015/12/31T00:00:00");

对我很有效:)
谢谢@dda

相关问题