Câu hỏi Làm cách nào để định dạng ngày tháng Microsoft JSON?


Tôi đang lấy vết nứt đầu tiên của tôi tại Ajax với jQuery. Tôi đang lấy dữ liệu của mình trên trang của mình, nhưng tôi đang gặp một số rắc rối với dữ liệu JSON được trả về cho các kiểu dữ liệu Ngày. Về cơ bản, tôi nhận được một chuỗi trở lại trông như thế này:

/Date(1224043200000)/

Từ một người hoàn toàn mới đến JSON - Làm cách nào để định dạng hình ảnh này thành định dạng ngày ngắn? Điều này có nên được xử lý ở đâu đó trong mã jQuery không? Tôi đã thử jQuery.UI.datepicker plugin sử dụng $.datepicker.formatDate() không thành công.

FYI: Đây là giải pháp tôi đưa ra bằng cách sử dụng kết hợp các câu trả lời ở đây:

function getMismatch(id) {
  $.getJSON("Main.aspx?Callback=GetMismatch",
    { MismatchId: id },

    function (result) {
      $("#AuthMerchId").text(result.AuthorizationMerchantId);
      $("#SttlMerchId").text(result.SettlementMerchantId);
      $("#CreateDate").text(formatJSONDate(Date(result.AppendDts)));
      $("#ExpireDate").text(formatJSONDate(Date(result.ExpiresDts)));
      $("#LastUpdate").text(formatJSONDate(Date(result.LastUpdateDts)));
      $("#LastUpdatedBy").text(result.LastUpdateNt);
      $("#ProcessIn").text(result.ProcessIn);
    }
  );

  return false;
}

function formatJSONDate(jsonDate) {
  var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
  return newDate;
}

Giải pháp này nhận đối tượng của tôi từ phương thức gọi lại và hiển thị ngày tháng trên trang đúng cách bằng cách sử dụng thư viện định dạng ngày.


1793


gốc


Điều này có thể thú vị: hanselman.com/blog/… - citronas
Định dạng /Date(...)/ là đặc trưng cho định dạng Ngày tháng JSON được tích hợp sẵn của Microsoft - nó không phải là một phần của bất kỳ tiêu chuẩn nào, và JSON, đến từ Javascript, có một tiêu chuẩn: Định dạng ISO xác định: stackoverflow.com/a/15952652/176877  Vì vậy, câu hỏi này dành riêng cho định dạng Ngày JSON của Microsoft. Tôi đã sửa đổi tiêu đề để làm rõ điều này. - Chris Moschini
Bạn đang đùa! Microsoft đã đóng dấu spin riêng của họ trên JSON! và vào những ngày !! Khi nào họ sẽ học! - Nick.McDermaid
Sử dụng JSON Newtonsoft ở phía .NET và để có các giá trị được gõ đẹp ở phía JS, chỉ cần sử dụng: github.com/RickStrahl/json.date-extensions - baHI


Các câu trả lời:


Đánh giá là không cần thiết. Điều này sẽ hoạt động tốt:

var date = new Date(parseInt(jsonDate.substr(6)));

Hàm substr lấy ra phần "/ Date (", và hàm parseInt lấy số nguyên và bỏ qua ") /" ở cuối. Số kết quả được chuyển vào hàm tạo ngày.

EDIT: Tôi đã cố ý bỏ ra khỏi cơ số (đối số thứ 2 để phân tích cú pháp); xem bình luận của tôi dưới đây. Ngoài ra, tôi hoàn toàn đồng ý với Nhận xét của Rory: Ngày ISO-8601 được ưu tiên hơn định dạng cũ này - vì vậy định dạng này thường không nên được sử dụng cho phát triển mới. Xem tuyệt vời Json.NET thư viện cho một sự thay thế tuyệt vời mà serializes ngày sử dụng định dạng ISO-8601.

Đối với các ngày JSON được định dạng ISO-8601, chỉ cần chuyển chuỗi vào hàm tạo ngày:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

1566



@Broam: Cả hai phương thức (hàm thay thế và câu trả lời này) sẽ phải thay đổi nếu MS thay đổi định dạng. - Roy Tinker
@ LeeWhitney: Có, nhưng nó sẽ bỏ qua hậu tố (đó là một bù đắp múi giờ). Hàm parseInt lấy các số từ phía trước của chuỗi được truyền tới nó cho đến khi nó gặp một ký tự không phải là chữ số hoặc phần cuối của chuỗi, tại thời điểm nó dừng lại và trả về kết quả dạng số. - Roy Tinker
Bạn có thể vui lòng cập nhật nó với radix var date = new Date (parseInt (jsonDate.substr (6), 10)); - James Kyburz
@ JamesKyburz: Mọi quy tắc đều có ngoại lệ và tôi nghĩ đây là khi ngoại lệ được áp dụng. Số ngày JSON từ .NET không bao giờ có một "0" hàng đầu, vì vậy chúng tôi có thể bỏ đi một cách an toàn. - Roy Tinker
Cần lưu ý rằng định dạng ngày tháng này khá tệ và việc di chuyển chung là định dạng ngày theo định dạng ISO-8601 trong JSON. Xem hanselman.com/blog/… - Rory


Bạn có thể sử dụng điều này để có được một ngày từ JSON:

var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));

Và sau đó bạn có thể sử dụng định dạng ngày tháng JavaScript script (1.2 KB khi được rút gọn và gzip) để hiển thị nó theo ý muốn của bạn.


115



Không có gì sai với dòng, trình tự là \ //. Dấu gạch chéo đầu tiên được thoát ra để nó không được tính như bình luận. Đó là trình soạn thảo của bạn lừa bạn, dòng sẽ hoạt động tốt. - andreialecu
@ rball, vô nghĩa: jsonDate = new Date(+jsonDate.replace(/\/Date\((\d+)\)\//, '$1')); - eyelidlessness
pst là chính xác, nó có thể làm điều này trong nhiều cách mà không có 'eval'. Crockford nói rằng 'eval Is Evil' bởi vì nó ít dễ đọc hơn và kém an toàn hơn, hơn nữa anh ta có thể ngụ ý rằng nó kém hiệu quả và nguy hiểm hơn vì nó truy cập trình biên dịch javascript. - Mark Rogers
@Edy: new Function gần như tệ như eval: dev.opera.com/articles/view/efficient-javascript/… - Marcel Korpel
@Edy: Đó là một dạng khác của eval, và cũng giống như 'ác'. Phân tích chuỗi thay thế (xem câu trả lời của tôi bên dưới) - Roy Tinker


Đối với những người sử dụng Newtonsoft Json.NET, hãy đọc về cách thực hiện thông qua JSON gốc trong IE8, Firefox 3.5 cộng với Json.NET.

Ngoài ra tài liệu về việc thay đổi định dạng ngày tháng được viết bởi Json.NET rất hữu ích: Tuần tự ngày với Json.NET

Đối với những người quá lười biếng, đây là các bước nhanh chóng. Vì JSON có triển khai DateTime mất thời gian, bạn cần sử dụng IsoDateTimeConverter(). Lưu ý rằng kể từ khi Json.NET 4.5 định dạng ngày mặc định là ISO nên mã dưới đây là không cần thiết.

string jsonText = JsonConvert.SerializeObject(p, new IsoDateTimeConverter());

JSON sẽ đi qua như

"fieldName": "2009-04-12T20:44:55"

Cuối cùng, một số JavaScript để chuyển đổi ngày ISO thành một ngày JavaScript:

function isoDateReviver(value) {
  if (typeof value === 'string') {
    var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(?:([\+-])(\d{2})\:(\d{2}))?Z?$/.exec(value);
      if (a) {
        var utcMilliseconds = Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]);
        return new Date(utcMilliseconds);
      }
  }
  return value;
}

Tôi đã sử dụng nó như thế này

$("<span />").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName);

84



Trình tạo ngày tháng JavaScript có thể phân tích cú pháp chuỗi cho bạn: new Date("2009-04-12T20:44:55") - David Hogue
Cảnh báo - Các định dạng và phân tích cú pháp Date () Constructor là không chuẩn trước ECMAScript 6. Ví dụ, IE 9 xử lý ngày mà bạn cung cấp cho hàm khởi tạo như là một giờ địa phương ngay cả khi nó nằm trong IS0-8601 đó được ngụ ý là UCT ở mọi nơi khác. Đừng dựa vào hàm tạo ngày nếu bạn hỗ trợ các trình duyệt cũ hơn. codeofmatt.com/2013/06/07/… - DanO
Việc gửi ngày không phải UTC sẽ sớm hay muộn sẽ khiến bạn gặp rắc rối. - tymtam


Ví dụ ban đầu:

/Date(1224043200000)/  

không phản ánh định dạng được WCF sử dụng khi gửi ngày qua WCF REST bằng cách sử dụng tuần tự hóa JSON dựng sẵn. (ít nhất là trên .NET 3.5, SP1)

Tôi tìm thấy câu trả lời ở đây hữu ích, nhưng một chỉnh sửa nhỏ để regex là cần thiết, vì nó xuất hiện rằng múi giờ GMT bù đắp đang được nối vào số trở lại (từ năm 1970) trong WCF JSON.

Trong một dịch vụ WCF tôi có:

[OperationContract]
[WebInvoke(
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.WrappedRequest
    )]
ApptVisitLinkInfo GetCurrentLinkInfo( int appointmentsId );

ApptVisitLinkInfo được định nghĩa đơn giản:

public class ApptVisitLinkInfo {
    string Field1 { get; set; }
    DateTime Field2 { get; set; }
    ...
}

Khi "Field2" được trả về dưới dạng Json từ dịch vụ, giá trị là:

/Date(1224043200000-0600)/

Lưu ý rằng chênh lệch múi giờ được bao gồm như là một phần của giá trị.

Regex đã sửa đổi:

/\/Date\((.*?)\)\//gi

Hơi háo hức hơn và nắm lấy mọi thứ giữa các parens, không chỉ là con số đầu tiên. Thời gian kết quả là năm 1970, cộng với thời gian bù đắp tất cả có thể được đưa vào eval để có được một đối tượng ngày tháng.

Dòng kết quả của JavaScript cho thay thế là:

replace(/\/Date\((.*?)\)\//gi, "new Date($1)");

57



điều này là sai, ngày mới (1224043200000-0600) sẽ chỉ trừ 600 từ ngày, trong trường hợp này là 600 mili giây, không phải 6 giờ. - ariel
@ariel: Hãy xem Ngày Javascript từ mili giây và múi giờ - Bergi
Tôi nghĩ rằng bù đắp múi giờ chỉ được bao gồm nếu bạn có một múi giờ trên đối tượng DateTime trong .NET (đó là hành vi mặc định). Nếu ngày của bạn ở dạng UTC, hãy sử dụng DateTime.SpecifyKind (ngày, DateTimeKind.UTC) và bạn sẽ nhận được giá trị UTC đúng khi nó nối tiếp, không có bù đắp, sau đó bạn có thể chuyển đổi về múi giờ của người dùng nếu cần. Nếu đó là giờ địa phương, hãy sử dụng .ToUniversalTime () và nó sẽ chuyển thành UTC và có "Loại" đã được chỉ định cho bạn. - jvenema
trong javascript -0100 sẽ là một chuỗi nhị phân nên hãy cẩn thận! - verbedr
một khi bạn đã có ngày chuyển đổi từ WCF sang JS, làm thế nào về đảo ngược. Bạn gotta ngày là số nguyên (bằng cách sử dụng date.getTime ()) mà bạn muốn vượt qua để WCF cùng? - NitinSingh


Đừng lặp lại - tự động chuyển đổi ngày bằng $.parseJSON()

Câu trả lời cho bài đăng của bạn cung cấp chuyển đổi ngày thủ công sang ngày JavaScript. Tôi đã mở rộng jQuery $.parseJSON() chỉ một chút, vì vậy nó có thể tự động phân tích ngày khi bạn hướng dẫn nó. Nó xử lý các ngày định dạng ASP.NET (/Date(12348721342)/) cũng như ngày được định dạng theo ISO (2010-01-01T12.34.56.789Z) được hỗ trợ bởi các hàm JSON nguyên gốc trong các trình duyệt (và các thư viện như json2.js).

Dù sao. Nếu bạn không muốn lặp lại mã chuyển đổi ngày của mình nhiều lần, tôi khuyên bạn nên đọc bài đăng trên blog này và lấy mã giúp cuộc sống của bạn dễ dàng hơn một chút.


53





Nếu bạn nói bằng JavaScript,

var thedate = new Date(1224043200000);
alert(thedate);

bạn sẽ thấy rằng đó là ngày chính xác và bạn có thể sử dụng nó ở bất kỳ đâu trong mã JavaScript với bất kỳ khung công tác nào.


50



Đó là những gì tôi đã nghĩ quá trừ khi nó kết thúc là: var thedate = / Date (1224043200000) /; ít nhất là đối với tôi ... - rball
Date () và Date (1224043200000) đều cho kết quả tương tự trong cả Chrome và Firefox. Không chắc chắn nếu điều này làm việc trong các trình duyệt cũ, nhưng câu trả lời này không hoạt động trong các trình duyệt bây giờ. - James
@ James, Có, nó cho ngày hiện tại của trình duyệt. :( - vissu
Bạn cần phải viết nó là "ngày mới (1224043200000)". - BrainSlugs83


Nhấn vào đây để xem Demo

JavaScript / jQuery

var = MyDate_String_Value = "/Date(1224043200000)/"
var value = new Date
            (
                 parseInt(MyDate_String_Value.replace(/(^.*\()|([+-].*$)/g, ''))
            );
var dat = value.getMonth() +
                         1 +
                       "/" +
           value.getDate() +
                       "/" +
       value.getFullYear();

Kết quả - "15/10/2008"


47



Chỉ là một cải tiến cho phương pháp trên. function formatearFecha (fec) {var value = new Date (parseInt (fec.replace (/ (^. * () | ([+ -]. * $) / g, ''))); var mes = value.getMonth (); var dia = value.getDate (); var date = dia + "/" + mes + "/" + value.getFullYear (); if (dia <10) date = date.substr (0, 0) + '0' + dia + date.substr (1); if (mes <10) date = date.substr (0, 3) + '0' + mes + date.substr (4); ngày trả về;} ngày được định dạng thành ddMMyyyy. - Matias
ohh !!! cảm ơn bạn rất nhiều!!! nó thực sự làm cho tháng của tôi. - Raihan Ridoy


Đã cập nhật

Chúng tôi có một thư viện giao diện người dùng nội bộ phải đối phó với cả định dạng JSON tích hợp sẵn của Microsoft, như /Date(msecs)/, được hỏi về ban đầu ở đây và hầu hết định dạng ngày của JSON bao gồm JSON.NET, như 2014-06-22T00:00:00.0. Ngoài ra chúng ta cần phải đối phó với không thể đối phó với bất kỳ thứ gì ngoài 3 số thập phân.

Đầu tiên chúng tôi phát hiện loại ngày chúng tôi đang tiêu thụ, phân tích cú pháp nó thành một JavaScript bình thường Date đối tượng, sau đó định dạng.

1) Phát hiện định dạng ngày Microsoft

// Handling of Microsoft AJAX Dates, formatted like '/Date(01238329348239)/'
function looksLikeMSDate(s) {
    return /^\/Date\(/.test(s);
}

2) Phát hiện định dạng ngày ISO

var isoDateRegex = /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d\d?\d?)?([\+-]\d\d:\d\d|Z)?$/;

function looksLikeIsoDate(s) {
    return isoDateRegex.test(s);
}

3) Định dạng ngày của Parse MS:

function parseMSDate(s) {
    // Jump forward past the /Date(, parseInt handles the rest
    return new Date(parseInt(s.substr(6)));
}

4) Phân tích cú pháp định dạng ngày ISO.

Chúng tôi ít nhất có một cách để đảm bảo rằng chúng tôi đang xử lý các ngày ISO chuẩn hoặc ngày ISO được sửa đổi để luôn có ba phần nghìn giây (xem ở trên), do đó, mã khác nhau tùy thuộc vào môi trường.

4a) Phân tích cú pháp chuẩn ISO Date format, đối phó với các vấn đề của oldIE:

function parseIsoDate(s) {
    var m = isoDateRegex.exec(s);

    // Is this UTC, offset, or undefined? Treat undefined as UTC.
    if (m.length == 7 ||                // Just the y-m-dTh:m:s, no ms, no tz offset - assume UTC
        (m.length > 7 && (
            !m[7] ||                    // Array came back length 9 with undefined for 7 and 8
            m[7].charAt(0) != '.' ||    // ms portion, no tz offset, or no ms portion, Z
            !m[8] ||                    // ms portion, no tz offset
            m[8] == 'Z'))) {            // ms portion and Z
        // JavaScript's weirdo date handling expects just the months to be 0-based, as in 0-11, not 1-12 - the rest are as you expect in dates.
        var d = new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]));
    } else {
        // local
        var d = new Date(m[1], m[2]-1, m[3], m[4], m[5], m[6]);
    }

    return d;
}

4b) Phân tích cú pháp định dạng ISO với ba chữ số thập phân cố định ba giây - dễ dàng hơn nhiều:

function parseIsoDate(s) {
    return new Date(s);
}

5) Định dạng nó:

function hasTime(d) {
    return !!(d.getUTCHours() || d.getUTCMinutes() || d.getUTCSeconds());
}

function zeroFill(n) {
    if ((n + '').length == 1)
        return '0' + n;

    return n;
}

function formatDate(d) {
    if (hasTime(d)) {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
        s += ' ' + d.getHours() + ':' + zeroFill(d.getMinutes()) + ':' + zeroFill(d.getSeconds());
    } else {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
    }

    return s;
}

6) Tie tất cả lại với nhau:

function parseDate(s) {
    var d;
    if (looksLikeMSDate(s))
        d = parseMSDate(s);
    else if (looksLikeIsoDate(s))
        d = parseIsoDate(s);
    else
        return null;

    return formatDate(d);
}

Câu trả lời dưới đây là hữu ích để buộc định dạng ngày tháng này vào phân tích cú pháp JSON của jQuery để bạn có được các đối tượng Date thay vì các chuỗi, hoặc nếu bạn vẫn bị kẹt trong jQuery <1.5 bằng cách nào đó.

Câu trả lời cũ

Nếu bạn đang sử dụng hàm Ajax của jQuery 1.4 với ASP.NET MVC, bạn có thể biến tất cả các thuộc tính DateTime thành các đối tượng Date với:

// Once
jQuery.parseJSON = function(d) {return eval('(' + d + ')');};

$.ajax({
    ...
    dataFilter: function(d) {
        return d.replace(/"\\\/(Date\(-?\d+\))\\\/"/g, 'new $1');
    },
    ...
});

Trong jQuery 1.5, bạn có thể tránh ghi đè parseJSON trên toàn cầu bằng cách sử dụng tùy chọn trình biến đổi trong cuộc gọi Ajax.

http://api.jquery.com/jQuery.ajax/

Thật không may, bạn phải chuyển sang tuyến eval cũ hơn để có được Ngày phân tích trên toàn cầu tại chỗ - nếu không bạn cần chuyển đổi chúng theo phân tích cú pháp sau phân biệt từng trường hợp.


31





Tôi cũng đã phải tìm kiếm một giải pháp cho vấn đề này và cuối cùng tôi đã xem qua moment.js, một thư viện đẹp có thể phân tích định dạng ngày tháng này và nhiều hơn nữa.

var d = moment(yourdatestring)

Nó tiết kiệm một số nhức đầu cho tôi vì vậy tôi nghĩ rằng tôi muốn chia sẻ nó với bạn. :)
Bạn có thể tìm thêm một số thông tin tại đây: http://momentjs.com/


21





Tôi đã kết thúc việc thêm các ký tự vào biểu thức chính quy của Panos để loại bỏ các ký tự được tạo bởi trình nối tiếp của Microsoft khi viết các đối tượng vào một tập lệnh nội tuyến:

Vì vậy, nếu bạn có một tài sản trong C # của bạn mã ẩn đó là một cái gì đó như

protected string JsonObject { get { return jsSerialiser.Serialize(_myObject); }}

Và trong aspx của bạn, bạn có

<script type="text/javascript">
    var myObject = '<%= JsonObject %>';
</script>

Bạn sẽ nhận được một cái gì đó như

var myObject = '{"StartDate":"\/Date(1255131630400)\/"}';

Lưu ý các dấu ngoặc kép.

Để có được điều này vào một form mà eval sẽ deserialize một cách chính xác, tôi đã sử dụng:

myObject = myObject.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');

tôi sử dụng Prototype và sử dụng nó tôi đã thêm

String.prototype.evalJSONWithDates = function() {
    var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
    return jsonWithDates.evalJSON(true);
}

21





Không có loại ngày được xây dựng trong JSON. Điều này trông giống như số giây / mili giây từ một số thời đại. Nếu bạn biết thời đại, bạn có thể tạo ngày bằng cách thêm đúng số lượng thời gian.


20



Điều đó không chính xác, JSON sử dụng các ngày Javascript, với thông tin múi giờ bổ sung-- kỷ nguyên giống như thời đại của lớp Date javascript (vì lý do hiển nhiên). - BrainSlugs83
@ BrainSlug83 - câu trả lời này cung cấp một tham chiếu cho xác nhận rằng JSON không có kiểu ngày được tích hợp sẵn. Nếu bạn không đồng ý, vui lòng cung cấp tài liệu tham khảo thay thế. (Bạn không nghĩ đến một khuôn khổ cụ thể đã quyết định về một định dạng chuỗi để biểu diễn ngày tháng là bạn? Đó không phải là một phần của tiêu chuẩn JSON, thực sự nó không thể được vì nó sẽ làm cho nó không thể bao gồm một chuỗi mà không phải là được coi là một ngày nhưng điều đó xảy ra để có một tập hợp các ký tự phù hợp với mẫu ngày tháng.) - nnnnnn