วันที่ไม่ถูกต้องในซาฟารี


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

โครเมี่ยม ff ไม่มีปัญหากับสิ่งนี้ แต่ซาฟารีร้องว่า "วันที่ไม่ถูกต้อง" ทำไม

แก้ไข: ตกลงตามความคิดเห็นด้านล่างฉันใช้การแยกสตริงและลองนี้:

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

แก้ไข Mar 22 2018 : ดูเหมือนว่าผู้คนยังคงลงจอดที่นี่ - วันนี้ฉันจะใช้momentหรือdate-fnsไม่ก็ไปกับมัน Date-fns นั้นไร้ความเจ็บปวดและเบามากเช่นกัน


สำหรับคนอื่นที่มองปัญหาเดียวกัน: ฉันลงเอยด้วยการใช้ DateJS ซึ่งแก้ไขปัญหาโดยรวมของฉัน .. ดูคำตอบที่ยอมรับสำหรับรายละเอียด
Shrinath

2
ใช้moment.jsเพื่อวิเคราะห์การประทับเวลา โดยเฉพาะอย่างยิ่งเมื่อต้องรับมือกับเว็บข้ามแพลตฟอร์ม
Ming Yuen

1
นี่เป็นคำถามเก่า ตั้งแต่วันที่ ECMAScript 2015 สตริงวันที่เท่านั้น ISO 8601 จะถูกแยกวิเคราะห์เป็น UTC อย่างไรก็ตามอาจยังมีเบราว์เซอร์รุ่นเก่าที่จะไม่แยกวิเคราะห์เลยหรือถือเป็นแบบโลคอล
RobG

คำตอบ:


167

รูปแบบyyyy-MM-ddไม่ใช่รูปแบบที่สนับสนุนอย่างเป็นทางการสำหรับตัวDateสร้าง Firefox ดูเหมือนจะสนับสนุน แต่ไม่นับในเบราว์เซอร์อื่นที่ทำเช่นเดียวกัน

นี่คือสตริงที่รองรับบางส่วน:

  • MM-DD-YYYY
  • ปปปป / ดด / วว
  • dd / mm / ปปปป
  • MMMM dd, yyyy
  • MMM dd, yyyy

DateJSดูเหมือนว่าเป็นห้องสมุดที่ดีสำหรับการแยกวิเคราะห์รูปแบบวันที่ที่ไม่ได้มาตรฐาน

แก้ไข : เพียงแค่การตรวจสอบECMA-262 มาตรฐาน ข้อความจากส่วนที่ 15.9.1.15:

รูปแบบสตริงเวลาวันที่

ECMAScript กำหนดรูปแบบการแลกเปลี่ยนสตริงสำหรับวันที่ - เวลาตามความเรียบง่ายของ ISO 8601 Extended Format รูปแบบมีดังนี้: YYYY-MM-DDTHH: mm: ss.sssZ โดยที่ฟิลด์จะเป็นดังนี้:

  • YYYY คือตัวเลขทศนิยมของปีในปฏิทินเกรโกเรียน
  • "-" (เครื่องหมายขีดคั่น) ปรากฏขึ้นสองครั้งในสตริง
  • MM คือเดือนของปีจาก 01 (มกราคม) ถึง 12 (ธันวาคม)
  • DD คือวันของเดือนจาก 01 ถึง 31
  • "T" จะปรากฏขึ้นอย่างแท้จริงในสตริงเพื่อระบุจุดเริ่มต้นขององค์ประกอบเวลา
  • HH คือจำนวนชั่วโมงทั้งหมดที่ผ่านไปตั้งแต่เที่ยงคืนเป็นทศนิยมสองหลัก
  • ":" (โคลอน) ปรากฏขึ้นสองครั้งในสตริง
  • mm คือจำนวนนาทีที่สมบูรณ์ตั้งแต่จุดเริ่มต้นชั่วโมงเป็นทศนิยมสองหลัก
  • ss คือจำนวนวินาทีที่สมบูรณ์ตั้งแต่จุดเริ่มต้นนาทีเป็นทศนิยมสองหลัก
  • "" (จุด) ปรากฏตามตัวอักษรในสตริง
  • sss คือจำนวนมิลลิวินาทีที่สมบูรณ์ตั้งแต่จุดเริ่มต้นที่สองเป็นทศนิยมสามหลัก ทั้ง "." และฟิลด์มิลลิวินาทีอาจถูกตัดออก
  • Z คือเขตเวลาชดเชยที่ระบุเป็น "Z" (สำหรับ UTC) หรือ "+" หรือ "-" ตามด้วยนิพจน์เวลา hh: mm

รูปแบบนี้รวมถึงแบบฟอร์มวันที่เท่านั้น:

  • ปปปป
  • YYYY-MM
  • YYYY-MM-DD

นอกจากนี้ยังมีแบบฟอร์มเฉพาะเวลาที่มีการเพิ่มออฟเซ็ตเขตเวลาเสริม:

  • THH: mm
  • THH: 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

@darioo ดังนั้นฉันลองตอบคำถามของคุณดังนี้: "var start = Date.parseExact (เวลาประทับ" YYYY-DD-MM HH: mm: SS ");" การประทับเวลาคือ "2016-01-28 00:00:00" อย่างไรก็ตามตอนนี้ฉันได้รับข้อผิดพลาดว่า "Date.parseExact ไม่ใช่ฟังก์ชัน" คุณรู้ไหมว่าเกิดอะไรขึ้นที่นี่
threxx

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" ให้สังเกตว่าไม่มีเครื่องหมายจุดคู่ในรูปแบบเขตเวลา
Olmstov

224

สำหรับฉันที่ใช้ไลบรารีใหม่เพียงเพราะ Safari ไม่สามารถทำได้อย่างถูกต้องมากเกินไปและ regex เกินไป นี่คือoneliner :

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

หากการสแลชเป็นเพียงปัญหาของฉันฉันจะยอมรับคำตอบของคุณ (แม้ว่ามันจะเป็นเป้าหมายเดียวของฉันเมื่อฉันถามคำถามนี้) ตอนนี้ฉันพบ dateJS แล้วฉันได้ติดตั้ง MMM DD, YYYY เพื่อประสบการณ์การใช้งานที่เป็นมิตรมากขึ้น !!!
Shrinath

13
ความช่วยเหลือหนึ่งบรรทัดนี้สมบูรณ์แบบสำหรับความต้องการของฉัน! ขอบคุณ!
Cyril N.

4
มันง่ายพอสำหรับฉันเช่นกัน ไม่อยากเชื่อเลยว่า Safari ไม่ชอบ - แต่รูปแบบเดียวกันกับ \\ ใช้งานได้ ขอบคุณ @Elzo และขอบคุณ Shrinath สำหรับการโพสต์คำถาม
Pete

1
ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุดที่ฉันมักจะลืม / - / g แทน '-'
Jacek Pietal

12
เสียงปรบมือที่ไม่ใช้ห้องสมุด
lharby

56

ฉันกำลังเผชิญกับปัญหาที่คล้ายกัน Date.Parse("DATESTRING")ทำงานบน Chrome (รุ่น 59.0.3071.115) แต่ไม่ใช่ของ Safari (เวอร์ชัน 10.1.1 (11603.2.5))

Safari:

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

โครเมียม:

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

วิธีการแก้ปัญหาที่ทำงานให้ฉันได้รับการเปลี่ยนพื้นที่ใน dateString "T"ด้วย (ตัวอย่าง: dateString.replace(/ /g,"T"))

Safari:

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

โครเมียม:

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

โปรดทราบว่าการตอบสนองจากเบราว์เซอร์ Safari คือ 8 ชั่วโมง (28800000ms) น้อยกว่าการตอบสนองที่เห็นในเบราว์เซอร์ Chrome เนื่องจาก Safari ส่งการตอบกลับในท้องถิ่น TZ (ซึ่งเป็น 8 ชั่วโมงหลัง UTC)

เพื่อให้ได้ทั้งสองครั้งใน TZ เดียวกัน

Safari:

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

1
dateString.replace(/ /g,"T")รหัสมายากลนี้ทำงานแบบฉัน :)
Mazdak Shojaie

แทนที่ (/ - / g, '/')
แจ็คหู

11

ฉันใช้ช่วงเวลาในการแก้ปัญหา ตัวอย่างเช่น

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

10

หากต้องการให้โซลูชันทำงานกับเบราว์เซอร์ส่วนใหญ่คุณควรสร้าง date-object ด้วยรูปแบบนี้

(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: วันที่วัตถุ (JavaScript)

Mozilla Dev Network: วันที่


6

แปลงสตริงเป็น Date fromat (คุณต้องรู้เขตเวลาของเซิร์ฟเวอร์)

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

โดยที่ +08: 00 = timeZone จากเซิร์ฟเวอร์


สิ่งนี้ไม่ได้คำนึงถึง DST TZ offset สามารถผันผวนได้และขึ้นอยู่กับวันที่ (และเวลา)
costa

5

ฉันมีปัญหาเดียวกันจากนั้นฉันใช้เวลาครู่หนึ่ง. ปัญหาได้หายไปแล้ว

เมื่อสร้างสักครู่จากสตริงเราจะตรวจสอบก่อนว่าสตริงนั้นตรงกับรูปแบบ ISO 8601 ที่รู้จักหรือไม่จากนั้นกลับไปสู่วันที่ใหม่ (สตริง) หากไม่พบรูปแบบที่รู้จัก

คำเตือน: การสนับสนุนเบราว์เซอร์สำหรับการวิเคราะห์คำสตริงไม่สอดคล้องกัน เนื่องจากไม่มีข้อมูลจำเพาะเกี่ยวกับรูปแบบที่ควรได้รับการสนับสนุนสิ่งที่ใช้ได้กับเบราว์เซอร์บางตัวจะไม่ทำงานในเบราว์เซอร์อื่น

เพื่อผลลัพธ์ที่สอดคล้องกันในการแยกวิเคราะห์สิ่งอื่น ๆ นอกเหนือจากสตริง ISO 8601 คุณควรใช้ String + Format

เช่น

var date= moment(String);

3

แม้ว่าคุณอาจหวังว่าเบราว์เซอร์จะรองรับISO 8601 (หรือชุดย่อยเฉพาะวันที่) แต่ก็ไม่เป็นเช่นนั้น เบราว์เซอร์ทั้งหมดที่ฉันรู้จัก (อย่างน้อยในสหรัฐอเมริกา / อังกฤษที่ฉันใช้) สามารถแยกวิเคราะห์MM/DD/YYYYรูปแบบสหรัฐที่น่ากลัวได้

หากคุณมีบางส่วนของวันที่คุณอาจต้องการลองใช้Date.UTC ()แทน ถ้าคุณทำไม่ได้ แต่คุณต้องใช้รูปแบบนี้ผมขอแนะนำให้ใช้การแสดงออกปกติจะแยกชิ้นที่คุณรู้แล้วผ่านพวกเขาไปYYYY-MM-DDDate.UTC()


ฉันเดาสตริงแยกเป็นวิธีที่จะไป :(
Shrinath

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

// ผลลัพธ์ของคุณจะมีลักษณะเช่นนี้ "พุธ 23 มีนาคม 2016 00:00:00 GMT + 0530 (IST)"

// หมายเหตุนี้จะอยู่ในเขตเวลาปัจจุบันในกรณีนี้แสดงโดย IST เพื่อแปลงเป็นเขตเวลา UTC ที่คุณสามารถรวมได้

alert(dateObj.toUTCSting);

// ผลลัพธ์ของคุณในตอนนี้ต้องการสิ่งนี้ "อังคาร, 22 มี.ค. 2016 18:30:00 GMT"

โปรดทราบว่าในขณะนี้ dateObj แสดงเวลาในรูปแบบ GMT และโปรดทราบว่าวันที่และเวลามีการเปลี่ยนแปลงตามลำดับ

ฟังก์ชัน "toUTCSting" จะดึงเวลาที่สอดคล้องกันที่ Greenwich meridian สิ่งนี้ทำได้โดยการสร้างความแตกต่างของเวลาระหว่างเขตเวลาปัจจุบันของคุณกับเขตเวลา Greenwich Meridian

ในกรณีข้างต้นเวลาก่อนการแปลงคือ 00:00 ชั่วโมงและนาทีในวันที่ 23 มีนาคมของปี 2559 และหลังจากการแปลงจาก GMT + 0530 (IST) ชั่วโมงเป็น GMT (โดยทั่วไปแล้วจะลบ 5.30 ชั่วโมงจากเวลาประทับที่กำหนดในนี้ กรณี) เวลาดังกล่าวแสดงเวลา 18.30 น. ของวันที่ 22 มีนาคมในปี 2559 (ตรงตามเวลา 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 (เวลามาเลเซีย) Firefox: var date = new Date (2018,06,08,19,17) วันที่ 2018-07-08T11: 17: 00.000Z
Biranchi

0

ปัญหาเดียวกันที่พบใน Safari และแก้ไขได้ด้วยการแทรกในหน้าเว็บ

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

หวังว่ามันจะทำงานกับกรณีของคุณด้วย

ขอบคุณ


ทำไมคุณคิดว่าสิ่งนี้จะได้ผล ฉันดูสคริปต์และดูเหมือนจะไม่แทนที่วิธีการในวัตถุวันที่ ฉันไปที่นี่: polyfill.io/v3/url-builderและดูเหมือนว่าจะไม่มีอะไรเกี่ยวกับการแยกวันที่
costa

0

ดังที่ @nizantz พูดถึงก่อนหน้านี้การใช้ Date.parse () ไม่ได้ผลสำหรับฉันใน Safari หลังจากการวิจัยเล็กน้อยฉันได้เรียนรู้ว่าคุณสมบัติ LastDateModified สำหรับวัตถุไฟล์นั้นเลิกใช้แล้วและไม่ได้รับการสนับสนุนจาก Safari อีกต่อไป การใช้คุณสมบัติ LastModified ของวัตถุ File แก้ไขปัญหาของฉัน แน่นอนว่าไม่ชอบเมื่อพบข้อมูลที่ไม่ดีออนไลน์

ขอบคุณทุกคนที่มีส่วนร่วมในโพสต์นี้ที่ช่วยฉันในการไปตามเส้นทางที่ฉันต้องการเพื่อเรียนรู้เกี่ยวกับปัญหาของฉัน หากไม่ใช่สำหรับข้อมูลนี้ฉันจะไม่สามารถหาปัญหารากของฉันได้ บางทีนี่อาจช่วยคนอื่นในสถานการณ์ที่คล้ายกันของฉัน


0

ฉันกำลังเผชิญกับปัญหาเดียวกันใน Safari Browser

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

นี่ไม่ใช่ทางออกที่ดีที่สุด แต่ฉันก็แค่จับข้อผิดพลาดแล้วส่งกลับวันที่ปัจจุบัน โดยส่วนตัวฉันรู้สึกเหมือนไม่ได้แก้ปัญหา Safari หากผู้ใช้ต้องการใช้เบราว์เซอร์ที่ไม่ได้มาตรฐาน sh * t พวกเขาต้องใช้ชีวิตด้วยนิสัยใจคอ

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' ตัวอย่างเช่น: - ใหม่วันที่ ('02 / 28/2015 ') มันทำงานได้ดีในทุกเบราว์เซอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.