2010-02-07 52 views
17

tôi có mã này trong một trang HTML:Khác biệt trong JSON.stringify của các giá trị ngày trong các trình duyệt khác nhau

alert(JSON.stringify(new Date())); 

tôi bao gồm json2.js (2009-09-29 phiên bản) mới nhất trong trang web của tôi để hỗ trợ các trình duyệt cũ hơn không có JSON.stringify(). Tôi cũng có jquery-1.3.2.js. Tôi tin rằng trong các trình duyệt mới hơn có hỗ trợ JSON nguyên gốc, nó chỉ chuyển sang tính năng JSON gốc.

Dưới đây là kết quả tôi nhận được trong các trình duyệt khác nhau:

IE 8 on Windows XP: "2010-02-07T21:39:32Z" 
Chrome 4.0 on Windows XP: "2010-02-07T21:39:59Z" 
Firefox 3.0 of Windows XP: "2010-02-07T21:40:41Z" 
Chrome 4.0 on Ubuntu linux: "2010-02-07T21:41:49Z" 
Firefox 3.0 on Ubuntu linux: "2010-02-07T21:42:44Z" 
Chrome 4.0 on Mac OSX: "2010-02-07T21:43:56Z" 
Safari on Mac OSX: "2010-02-07T21:45:21Z" 
Firefox 3.5 on Mac OSX: "2010-02-07T21:44:10.101Z" 

Thông báo người cuối cùng? Nó chứa mili giây, và không ai trong số những người khác làm. Tôi không có FF3.5 cài đặt trên bất kỳ hệ thống khác, nhưng tôi giả sử họ sẽ có kết quả tương tự.

Có điều gì tôi có thể làm để làm cho tất cả các ngày trên tất cả các nền tảng đều giống nhau không? Dịch vụ REST phụ trợ của tôi có thể được cấu hình với một chuỗi định dạng để deserialize ngày JSON, nhưng nó không thể hỗ trợ nhiều định dạng, chỉ một.

+1

FWIW, tôi chỉ thử nghiệm FF 3.6 trên Win7 và nó cũng mang đến cho mili giây. –

+2

Bài đăng có liên quan trên danh sách gửi thư của Mozilla: https://mail.mozilla.org/pipermail/es5-discuss/2008-October/001989.html –

+0

Chà, họ đã triển khai nó theo cách này vài năm trước ?! Tôi ngạc nhiên điều này đã không gây ra nhiều vấn đề hơn. Tôi đánh giá cao việc cố gắng tuân thủ các tiêu chuẩn, nhưng nếu mọi thứ khác đang làm theo cách khác, ít nhất là đưa ra một tùy chọn cấu hình để dự phòng. – Tauren

Trả lời

9

tôi đã làm việc này thêm javascript sau:

// Added to make dates format to ISO8601 
Date.prototype.toJSON = function (key) { 
    function f(n) { 
     // Format integers to have at least two digits. 
     return n < 10 ? '0' + n : n; 
    } 

    return this.getUTCFullYear() + '-' + 
     f(this.getUTCMonth() + 1) + '-' + 
     f(this.getUTCDate())  + 'T' + 
     f(this.getUTCHours())  + ':' + 
     f(this.getUTCMinutes()) + ':' + 
     f(this.getUTCSeconds()) + '.' + 
     f(this.getUTCMilliseconds()) + 'Z'; 
}; 

Tôi chắc chắn điều này có lẽ chậm serialization, nhưng có vẻ như để làm cho mọi việc nhất quán trên các trình duyệt.

0

Tại sao không sử dụng chức năng formatDate trong plugin jQuery-UI Datepicker cho jQuery để tạo định dạng mà phía máy chủ của bạn yêu cầu?

+0

Tôi đang truyền một mảng các đối tượng có chứa ngày tháng.Điều này có nghĩa là đi qua toàn bộ mảng và thay thế các đối tượng Date bằng các biểu diễn chuỗi của chúng. Tôi đã hy vọng không phải sao chép một mảng hiện có (được tạo ra bởi một công cụ của bên thứ 3) vào phiên bản của riêng tôi với các chuỗi ngày tháng. Tuy nhiên, điều này chỉ có thể là những gì tôi cần làm. Cám ơn vì sự gợi ý! – Tauren

+3

'formatDate' không phải là một hàm jQuery. Có vẻ như là một phần của điều khiển datepicker. –

4

Bạn cũng có thể điều chỉnh json2.js một chút để luôn sử dụng riêng Date.prototype.toJSON thay vì bản gốc có thể. Ở đây tôi uncomment hai dòng và nó hoạt động một cách chính xác:

// if (typeof Date.prototype.toJSON !== 'function') { 

    Date.prototype.toJSON = function (key) { 

     return isFinite(this.valueOf()) ? 
       this.getUTCFullYear() + '-' + 
      f(this.getUTCMonth() + 1) + '-' + 
      f(this.getUTCDate())  + 'T' + 
      f(this.getUTCHours())  + ':' + 
      f(this.getUTCMinutes()) + ':' + 
      f(this.getUTCSeconds()) + 'Z' : null; 
    }; 

    String.prototype.toJSON = 
    Number.prototype.toJSON = 
    Boolean.prototype.toJSON = function (key) { 
     return this.valueOf(); 
    }; 
// } 
+1

Haha! Tôi chỉ đăng chính xác những điều tương tự này chỉ 5 giây sau khi bạn ... Tôi không nghĩ rằng bạn cần phải thêm các chuỗi, số, và Boolean nguyên mẫu nếu bạn chỉ muốn tùy chỉnh Ngày. – Tauren

3

// Bạn có thể muốn xem xét việc tăng cường lên máy chủ, để nhận ra bất kỳ giá trị ISO 8601 định dạng thời gian:

'2010-02-08T03: 37: 34.327Z'

'2010- 02-08T03: 38: 06Z '

'2010-02-08T03: 38 + 01: 00'

'2010-02-08T03: 34: 18-05: 00'

' 2010 -02- 08T03: 34Z '

' 2010-02-08 '

Đây là phương pháp để chuyển đổi bất kỳ chuỗi ISO nào thành đối tượng ngày javascript. Nó có thể được sử dụng trên các máy chủ với một bản dịch nhỏ:

Date.from_iso= function(s){ 
    var D, M= [], hm, min= 0, d2, 
    Rx= /([\d:]+)(\.\d+)?(Z|(([+\-])(\d\d):(\d\d))?)?$/; 
    D= s.substring(0, 10).split('-'); 
    if(s.length> 11){ 
     M= s.substring(11).match(Rx) || []; 
     if(M[1]) D= D.concat(M[1].split(':')); 
     if(M[2]) D.push(Math.round(M[2]*1000));// msec 
    } 
    for(var i= 0, L= D.length; i<L; i++){ 
     D[i]= parseInt(D[i], 10); 
    } 
    D[1]-= 1; 
    while(D.length< 6) D.push(0); 
    if(M[4]){ 
     min= parseInt(M[6])*60+ parseInt(M[7], 10);// timezone not UTC 
     if(M[5]== '+') min*= -1; 
    } 
    try{ 
     d2= Date.fromUTCArray(D); 
     if(min) d2.setUTCMinutes(d2.getUTCMinutes()+ min); 
    } 
    catch(er){ 
     // bad input 
    } 
    return d2; 
} 
Date.fromUTCArray= function(A){ 
    var D= new Date; 
    while(A.length < 7) A.push(0); 
    var T= A.splice(3, A.length); 
    D.setUTCFullYear.apply(D, A); 
    D.setUTCHours.apply(D, T); 
    return D; 
} 
+0

Cảm ơn mã, nó có thể có ích trong khách hàng. Tôi nghĩ rằng tôi có thể sử dụng Joda Time để phân tích các định dạng ISO khác nhau ở phía máy chủ. Tôi đang sử dụng Jersey với xử lý JSON JSON để thực hiện REST trong một máy chủ java. Theo mặc định, nó cố gắng chuyển đổi từ một số định dạng khác nhau, nhưng tiếc là chỉ một trong những định dạng mà tôi cần. Nó có một cách để ghi đè định dạng, nhưng chỉ với một chuỗi định dạng duy nhất. Tôi chắc chắn có một cách tôi có thể nhận được sâu hơn và ghi đè nó tốt hơn, nhưng tôi sẽ phải dành nhiều thời gian hơn để làm điều đó. – Tauren

Các vấn đề liên quan