Safari中的日期无效


155
 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,它总体上解决了我的问题。有关详细信息,请参见接受的答案。
Shrinath 2010年

2
使用moment.js解析时间戳。跨平台的Web特别打交道时
铭源

1
这是一个老问题。从ECMAScript 2015开始,ISO 8601仅日期字符串被解析为UTC。但是,周围仍然可能存在一些较旧的浏览器,它们要么根本不解析它,要么将其视为本地浏览器。
RobG

Answers:


166

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

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

  • MM-dd-yyyy
  • yyyy / MM / dd
  • MM / dd / yyyy
  • MMMM dd,yyyy
  • MMM dd,yyyy

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

编辑:刚刚检查了ECMA-262标准。引用第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

它还包括仅时间形式,并附加了可选的时区偏移量:

  • 高度:mm
  • 高度:mm:ss
  • THH:mm:ss.sss

还包括“日期时间”,它可以是上述的任何组合。

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

更新:查看datejs文档后,使用它,应使用类似以下代码的方法解决您的问题:

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

4
ISO8601格式已在ECMAScript标准的第5版中使用,但尚未得到广泛支持,这是去IMO的最安全方法,手动解析日期:(
CMS

1
花花公子非常有帮助。.谢谢.. :)最终使用datejs进行了格式化。
Shrinath

对于将来的用户,请注意,尽管datejs在大多数方面都很棒,但它并不能解决所有日期格式问题,尤其是野生动物园。这是PITA,但如果仍有问题,最好手动进行。
totallyNotLizards 2012年

@darioo因此,我尝试按照以下方式回答您的问题:“ var start = Date.parseExact(timestamp,“ YYYY-DD-MM HH:mm:SS”);“ 时间戳为“ 2016-01-28 00:00:00”。但是现在我得到了一个错误,即“ Date.parseExact不是函数”。你知道吗,这里发生了什么?
threxx '16

5
我的类似问题是由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”,请注意时区格式中缺少冒号。
奥尔姆斯托夫

224

对我来说,仅仅因为Safari无法正确实现新库而实施一个新库就太多了,而正则表达式则显得过于刻板。这是oneliner

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

如果仅是一个斜线是我的问题,那么我会“接受”您的回答(尽管当我问这个问题时,这是我唯一的目标)。现在,我找到了dateJS,我实现了MMM DD,YYYY格式,以获得更加用户友好的体验!!!
Shrinath 2011年

13
这一行帮助非常适合我的需求!谢谢!
西里尔N.

4
这对我来说也很简单。不能相信Safari不喜欢-却可以使用\\相同的格式。感谢@Elzo和Shrinath发布了问题
Pete

1
我认为这是最好的答案,我往往会忘记/ - /克,而不是“ - ”
亚采Pietal

12
鼓掌不实施图书馆。
lharby

55

我面临着类似的问题。 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小时(28800000ms),因为Safari以本地TZ返回了响应(比世界标准时间晚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,如果您认为可以将此类示例添加到您的答案中,那就太好了。
h3dkandi

这不是特别有用,因为您使用UTC而非本地时间来获取日期。
乔纳斯·阿佩格兰(JonasÄppelgran)'18年

1
这条dateString.replace(/ /g,"T")神奇的代码行对我有用。:)
Mazdak Shojaie

replace(/-/ g,'/')
Jack Hu

11

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

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


6

将字符串从atat转换为Date(您必须知道服务器时区)

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

其中+08:00 =服务器的timeZone


这没有考虑DST。TZ偏移量可能会波动,并且取决于日期本身(和时间)。
哥斯达黎加

5

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

从字符串创建时刻时,我们首先检查字符串是否与已知的ISO 8601格式匹配,然后如果找不到已知格式,则退回到新的Date(string)。

警告:浏览器对字符串的支持不一致。因为没有关于应该支持哪种格式的规范,所以在某些浏览器中有效的格式在其他浏览器中无效。

为了获得一致的解析ISO 8601字符串以外的结果的结果,应使用字符串+格式。

例如

var date= moment(String);

3

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

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


我猜想字符串解析是要走的路:(
Shrinath 2010年

1

使用以下格式,它将在所有浏览器上正常工作

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

//您的输出将类似于“ 2016年3月23日星期三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”

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



1

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

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)Date 2018-07-08T11:17:00.000Z
Biranchi

0

在Safari中面临相同的问题,并将其插入网页即可解决

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

希望它也能适用

谢谢


您为什么认为这行得通?我看了看脚本,似乎没有覆盖Date对象中的方法。我去了这里:polyfill.io/v3/url-builder,解析日期似乎没什么。
哥斯达黎加

0

如@nizantz先前所述,在Safari中使用Date.parse()不适用于我。经过一些研究,我了解到File对象的lastDateModified属性已被弃用,而Safari不再支持该属性。使用File对象的lastModified属性解决了我的问题。当在网上发现错误信息时,一定会喜欢它。

感谢所有对这篇文章做出贡献的人,这些文章帮助我走上了学习我的问题所需要的道路。如果没有此信息,我可能永远也找不到我的根本问题。也许这会帮助我类似情况的其他人。


0

我在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 

0

尽管我只是捕获错误并发回当前日期,但这并不是最佳解决方案。我个人觉得如果用户要使用sh * t不符合标准的浏览器,就无法解决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设计/编码时也会有同样的想法。我们都知道现在如何谈论它。
Shrinath

-1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.