ChatGPT解决这个技术问题 Extra ChatGPT

Safari 中的日期无效

 alert(new Date('2010-11-29'));

chrome, ff 对此没有问题,但 safari 会喊“无效日期”。为什么 ?

编辑:好的,根据下面的评论,我使用了字符串解析并尝试了这个:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

编辑 2018 年 3 月 22 日 :似乎人们仍然在这里登陆 - 今天,我将使用 momentdate-fns 并完成它。 Date-fns 也非常轻松且无痛。

只是为了其他人在看同样的问题:我最终使用了 DateJS,它总体上解决了我的问题。有关详细信息,请参阅接受的答案。
使用 moment.js 解析时间戳。特别是在处理跨平台网络时
这是一个老问题。从 ECMAScript 2015 开始,ISO 8601 仅日期字符串被解析为 UTC。但是,可能仍然有一些旧浏览器根本不解析它或将其视为本地浏览器。
如问题“alert(new Date('29-11-2010')); alert(new Date('2010-29-11'));”中所述这两种格式在 Firefox/Chrome 中也不起作用。所以这两种格式我认为是完全错误的,根本不应该使用。

E
Elzo Valugi

对我来说,仅仅因为 Safari 不能正确地实现一个新库就太过分了,而且正则表达式是矫枉过正的。这是单线:

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

这一条线的帮助非常适合我的需要!谢谢!
这对我来说也很简单。不敢相信 Safari 不喜欢 - 但是带有 \\ 的相同格式可以工作。感谢@Elzo 并感谢 Shrinath 发布问题
我认为这是我倾向于忘记的最佳答案 /-/g 而不是 '-'
为没有实现库而鼓掌。
我仍然不明白为什么人们想要将整个库用于单一用途。荣誉没有实现一个。
C
Community

模式 yyyy-MM-dd 不是 Date 构造函数的官方支持格式。 Firefox 似乎支持它,但不要指望其他浏览器也这样做。

以下是一些受支持的字符串:

MM-dd-yyyy

年年/月/日

月/日/年

MMMM dd, yyyy

嗯 dd, yyyy

DateJS 似乎是解析非标准日期格式的好库。

编辑:刚刚选中 ECMA-262 standard。引用第 15.9.1.15 节:

日期时间字符串格式

ECMAScript 基于 ISO 8601 扩展格式的简化定义了日期时间的字符串交换格式。格式如下: YYYY-MM-DDTHH:mm:ss.sssZ 其中字段如下: YYYY 为公历年份的十进制数字。 “-”(连字符)在字符串中出现两次。 MM 是一年中的月份,从 01(一月)到 12(十二月)。 DD 是从 01 到 31 的月份中的某一天。“T”字面上出现在字符串中,表示时间元素的开始。 HH 是自午夜以来经过的完整小时数,以两位小数表示。 “:”(冒号)在字符串中出现两次。 mm 是自小时开始以来的完整分钟数,为两位小数。 ss 是自分钟开始以来的完整秒数,为两位小数。 “。” (点)字面上出现在字符串中。 sss 是自秒开始以来的完整毫秒数,以十进制三位数字表示。这俩 ”。”毫秒字段可以省略。 Z 是指定为“Z”(对于 UTC)或“+”或“-”后跟时间表达式 hh:mm 的时区偏移量 此格式包括仅日期形式:YYYY YYYY-MM YYYY-MM-DD

它还包括带有可选时区偏移的仅时间形式: THH:mm THH:mm:ss THH:mm:ss.sss 还包括“日期时间”,它可以是上述的任意组合。

因此,似乎 YYYY-MM-DD 包含在标准中,但出于某种原因,Safari 不支持它。

更新:查看 datejs documentation 后,使用它,您的问题应该可以使用如下代码解决:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");

ISO8601 格式用于 ECMAScript 标准的第 5 版,尚未得到广泛支持,最安全的方式去 IMO,手动解析日期:(
这对伙计很有帮助.. 谢谢.. :) 最后最终使用 datejs 进行格式化。
对于那些未来的人,请注意虽然 datejs 在大多数方面都很棒,但它并不能解决所有日期格式问题,尤其是 safari。这是一个 PITA,但如果您仍有问题,最好手动完成。
我的类似问题是由于 Safari 不知道如何以 RFC 822 时区格式读取时区。我能够通过使用 ISO 8601 格式来解决这个问题。如果您可以控制日期格式,我可以使用“yyyy-MM-dd'T'HH:mm:ss.sssXXX”创建即。 “2018-02-06T20:00:00.000+00:00”。无论出于何种原因,Safari 无法读取“2018-02-06T20:00:00.000+0000”,请注意时区格式中缺少冒号。
Safari 是新的 Internet Explorer!
M
Mazdak Shojaie

我面临着类似的问题。 Date.Parse("DATESTRING") 正在使用 Chrome(版本 59.0.3071.115)但不是 Safari(版本 10.1.1 (11603.2.5))

苹果浏览器:

Date.parse("2017-01-22 11:57:00")
NaN

铬合金:

Date.parse("2017-01-22 11:57:00")
1485115020000

对我有用的解决方案是将 dateString 中的空格替换为 "T"。 (例如:dateString.replace(/ /g,"T")

苹果浏览器:

Date.parse("2017-01-22T11:57:00")
1485086220000

铬合金:

Date.parse("2017-01-22T11:57:00")
1485115020000

请注意,来自 Safari 浏览器的响应比在 Chrome 浏览器中看到的响应少 8 小时(28800000 毫秒),因为 Safari 在本地 TZ 中返回响应(比 UTC 晚 8 小时)

在同一个 TZ 中获得两个时间

苹果浏览器:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

铬合金:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

或者,如果您不希望 Safari 和 Chrome 中的两个日期相同,您可以使用 new Date(year, month, date, hours, minutes, seconds, milliseconds) 构造函数。将字符串日期解析为其组件的数组,以便在构造函数中使用这些组件。 @nizantz 如果您认为可以将此类示例添加到您的答案中,那就太好了。
不是特别有用,因为您以 UTC 而不是本地时间获得日期。
这个 dateString.replace(/ /g,"T") 神奇的代码行对我有用。 :)
替换(/-/g, '/')
谢谢!比使用整个额外的库要容易得多!
l
liwp_Stephen

我用时刻来解决问题。例如

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();

谢谢你的灵魂!它是 Internet 上唯一适用于 React 应用程序的应用程序:IOS IPAD/IPHONE: chrome/safari ||安卓:铬 ||窗户:镀铬。没有测试所有设备和操作系统版本,但它仍然适用于我找到的每台设备!
对于任何未来的观众,请注意 moment 库现已弃用
你节省了我的时间,谢谢!
L
Luxx

要让解决方案适用于大多数浏览器,您应该使用这种格式创建日期对象

(year, month, date, hours, minutes, seconds, ms)

例如:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

适用于 IE、FF、Chrome 和 Safari。甚至更旧的版本。

IE Dev Center: Date Object (JavaScript)

Mozilla Dev Network: Date


我认为 new Date(2014, 6, 25) 不会创建 UTC 时间,而是创建本地时区 '2014-6-25T00:00' 的时间戳。 new Date(Date.UTC(2014, 6, 25)) 给出 UTC
A
Anja Ishmukhametova

将字符串转换为日期 fromat(您必须知道服务器时区)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

其中 +08:00 = 服务器的时区


这不考虑夏令时。 TZ 偏移量可能会波动,它取决于日期本身(和时间)。
S
Sampath

我遇到了同样的问题。然后我使用了 moment.Js。问题消失了。

从字符串创建时刻时,我们首先检查字符串是否与已知的 ISO 8601 格式匹配,如果未找到已知格式,则回退到 new Date(string)。警告:浏览器对解析字符串的支持不一致。因为没有关于应该支持哪些格式的规范,所以在某些浏览器中有效的内容在其他浏览器中无效。对于解析除 ISO 8601 字符串以外的任何内容的一致结果,您应该使用 String + Format。

例如

var date= moment(String);

O
OskarLebuda

对于使用 date-fns 的人,我们可以 parseISO 日期并使用它来格式化

无效的

import _format from 'date-fns/format';

export function formatDate(date: string, format: string): string {
  return _format(new Date(date), format);
}

Safari 上的此函数会使用 Invalid date 引发错误。

解决方案要修复它,我们应该使用:

import _format from 'date-fns/format';
import _parseISO from 'date-fns/parseISO';

export function formatDate(date: string, format: string): string {
  return _format(_parseISO(date), format);
}

P
Phrogz

尽管您可能希望浏览器支持 ISO 8601(或其仅日期子集),但事实并非如此。我知道的所有浏览器(至少在我使用的美国/英语语言环境中)都能够解析可怕的美国 MM/DD/YYYY 格式。

如果您已经有了日期的各个部分,您可能想尝试使用 Date.UTC()。如果你不这样做,但你必须使用 YYYY-MM-DD 格式,我建议使用正则表达式来解析你知道的部分,然后将它们传递给 Date.UTC()


我想字符串解析是要走的路:(
k
kenberkeley

fix-date 劫持 Date 怎么样?无依赖性,min + gzip = 280 B


唯一适用于我的解决方案。谢谢干杯...
v
venkatskpi

我在 Safari 浏览器中也面临同样的问题

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

这里的解决方案:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 

A
Abhay Aradhya

使用以下格式,它适用于所有浏览器

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

//您的输出将如下所示“Wed Mar 23 2016 00:00:00 GMT+0530 (IST)”

//请注意,在这种情况下,这将位于当前时区,由 IST 表示,要转换为 UTC 时区,您可以包括

alert(dateObj.toUTCSting);

//您现在的输出应该是“Tue, 22 Mar 2016 18:30:00 GMT”

请注意,现在 dateObj 以 GMT 格式显示时间,还请注意日期和时间已相应更改。

“toUTCSting”函数检索格林威治子午线的相应时间。这是通过建立当前时区与格林威治子午线时区之间的时差来实现的。

在上述情况下,转换前的时间是 2016 年 3 月 23 日的 00:00 小时和分钟。在从 GMT+0530 (IST) 小时转换为 GMT 之后(它基本上从给定的时间戳中减去 5.30 小时)例)时间反映了 2016 年 3 月 22 日的 18.30 小时(正好比第一次晚了 5.30 小时)。

进一步将任何日期对象转换为时间戳,您可以使用

alert(dateObj.getTime());

//输出看起来类似于“1458671400000”

这将为您提供时间的唯一时间戳


D
Daniël Brito

最好的方法是使用以下格式:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

所有浏览器都支持此功能,不会给您带来任何问题。请注意,月份是从 0 到 11 书写的。


在 Safari 和 Chrome 上运行良好,但在 Firefox 上仍然存在问题。 Safari: var date = new Date(2018,06,08,19,17) Sun Jul 08 2018 19:17:00 GMT+0800 (+08) Chrome: var date = new Date(2018,06,08,19, 17) Sun Jul 08 2018 19:17:00 GMT+0800 (Malaysia Time) Firefox: var date = new Date(2018,06,08,19,17) 日期 2018-07-08T11:17:00.000Z
G
GorvGoyl

对我来说,问题是我忘记在 YYYY-MM-DD 格式的单个数字月份或日期之前添加 0
我正在解析的内容:2021-11-5
它应该是什么:2021-11-05

因此,我编写了一个小工具,将 YYYY-M-D 转换为 YYYY-MM-DD,即 2021-1-1 转换为 2021-01-01

const date = "2021-1-1"
const YYYY = date.split("-")[0];

    //convert M->MM i.e. 2->02
    const MM =
      date.split("-")[1].length == 1
        ? "0" + date.split("-")[1]
        : date.split("-")[1];

    //convert D->DD i.e. 2->02
    const DD =
      date.split("-")[2].length == 1
        ? "0" + date.split("-")[2]
        : date.split("-")[2];

    // YYYY-MM-DD
    const properDateString = `${YYYY + "-" + MM + "-" + DD}`;

    const dateObj = new Date(properDateString);

S
S. Costello

正如@nizantz 之前提到的,在 Safari 中使用 Date.parse() 对我不起作用。经过一番研究,我了解到 File 对象的 lastDateModified 属性已被弃用,Safari 不再支持。使用 File 对象的 lastModified 属性解决了我的问题。当网上发现不良信息时,肯定不喜欢它。

感谢所有为这篇文章做出贡献的人,他们帮助我走上了了解我的问题所需的道路。如果没有这些信息,我可能永远也不会弄清楚我的根本问题。也许这会帮助我遇到类似情况的其他人。


d
dev7

迟到了,但在我们的例子中,当我们使用 ES6 反引号而不是 String() 来输入强制转换时,我们在 Safari 和 iOS 中遇到了这个问题

这给出了“无效日期”错误

const dateString = '2011-11-18';
const dateObj = new Date(`${dateString}`); 

但这有效

const dateObj = new Date(String(dateString)); 

Y
Yasir Shabbir Choudhary

Safari中面临同样的问题,通过在网页中插入它来解决

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

希望它也适用于您的情况

谢谢


为什么你认为这会奏效?我查看了脚本,它似乎没有覆盖 Date 对象中的方法。我去了这里:polyfill.io/v3/url-builder,似乎没有关于解析日期的内容。
S
SARAVANAN KALIMUTHU

这不起作用alert(new Date('2010-11-29')); Safari 有一些奇怪/严格的处理日期格式的方式alert(new Date(String('2010-11-29'))); 试试这样。

(或者)

使用 Moment js 可以解决这个问题,在 ios 14 之后,safari 变得更加奇怪

试试这个警报(时刻(字符串(“2015-12-31 00:00:00”)));

时刻JS


在将其粘贴到更多位置之前,请花时间阅读 Is it acceptable to add a duplicate answer to several questions?
请停止向其他人推荐 momentjs momentjs.com/docs/#/-project-status
R
Ravi S

使用格式“mm/dd/yyyy”。例如:- 新日期('02/28/2015')。它适用于所有浏览器。


A
AndrewMcLagan

这不是最好的解决方案,尽管我只是捕捉到错误并发回当前日期。如果用户想使用不符合标准的浏览器,我个人觉得不解决 Safari 问题——他们必须忍受怪癖。

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

我建议让您的后端发送 ISO 日期。


恕我直言,当您的意思是用户必须使用您为其编写代码的浏览器时,这在一般意义上看起来很糟糕。这也取决于我们的用例和目标受众——如果一个网站是为大众市场消费而构建的,我们至少也会支持 IE10。我确信 MS 中的某些人在为 Internet Explorer 设计/编码时也有同样的想法。我们都知道现在是如何谈论它的。