ฉันจะจัดรูปแบบวันที่ Microsoft JSON ได้อย่างไร


2000

ฉันกำลังแตกครั้งแรกที่Ajaxกับ jQuery ฉันได้รับข้อมูลของฉันไปที่หน้าของฉัน แต่ฉันมีปัญหากับข้อมูล JSON ที่ส่งคืนสำหรับชนิดข้อมูล Date โดยทั่วไปฉันได้รับสายกลับที่มีลักษณะเช่นนี้:

/Date(1224043200000)/

จากคนใหม่โดยสิ้นเชิงกับ JSON - ฉันจะจัดรูปแบบนี้เป็นรูปแบบวันที่แบบย่อได้อย่างไร ควรจัดการสิ่งนี้ในรหัส jQuery หรือไม่ ฉันลองjQuery.UI.datepickerใช้ปลั๊กอินโดย$.datepicker.formatDate()ไม่ประสบความสำเร็จ

FYI: ต่อไปนี้เป็นวิธีการแก้ปัญหาที่ฉันใช้เพื่อหาคำตอบที่นี่:

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

วิธีการแก้ปัญหานี้ได้วัตถุของฉันจากวิธีการโทรกลับและแสดงวันที่บนหน้าอย่างถูกต้องโดยใช้ห้องสมุดรูปแบบวันที่


26
สิ่งนี้อาจน่าสนใจ: hanselman.com/blog/…
citronas

6
รูปแบบ /Date(...)/ เป็นรูปแบบเฉพาะของรูปแบบ JSON Date ในตัวของ Microsoft - ไม่ใช่ส่วนหนึ่งของมาตรฐานใด ๆ และ JSON มาจาก Javascript มีมาตรฐาน: รูปแบบ ISO ที่ Javascript ระบุ: stackoverflow.com/a / 15952652/176877 ดังนั้นคำถามนี้เฉพาะกับรูปแบบวัน JSON ของ Microsoft ฉันแก้ไขชื่อเพื่อให้ความกระจ่าง
Chris Moschini

15
คุณล้อเล่นแน่ ๆ! Microsoft ได้ประทับตราสปินของตัวเองใน JSON! และในวันที่ !! พวกเขาจะเรียนรู้เมื่อไหร่!
Nick.McD เงือก

ใช้ Newtonsoft JSON ทางด้าน. NET และเพื่อให้ได้ค่าที่ดีในด้าน JS เพียงใช้: github.com/RickStrahl/json.date-extensions
baHI

คุณสามารถใช้ JSON ++ แทน JSON JSON ++ เป็นเดียวกันกว่า JSON แต่ด้วยการสนับสนุนประเภท JavaScript Dateเช่น
brillout

คำตอบ:


1688

eval()ไม่จำเป็น. สิ่งนี้จะทำงานได้ดี:

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

substr()ฟังก์ชั่นจะออก/Date(ส่วนหนึ่งและparseInt()ฟังก์ชั่นได้รับจำนวนเต็มและละเว้น)/ในตอนท้าย หมายเลขผลลัพธ์ถูกส่งผ่านไปยังตัวDateสร้าง


ฉันตั้งใจปล่อยให้ radix (อาร์กิวเมนต์ที่ 2 ถึงparseInt); ดูความคิดเห็นของฉันด้านล่าง

นอกจากนี้ฉันเห็นด้วยอย่างสมบูรณ์ ความคิดเห็นของ Rory : วันที่ ISO-8601 เป็นที่ต้องการมากกว่ารูปแบบเก่าดังนั้นรูปแบบนี้โดยทั่วไปไม่ควรใช้สำหรับการพัฒนาใหม่ ดูห้องสมุดJson.NET ที่ยอดเยี่ยมสำหรับทางเลือกที่ยอดเยี่ยมที่จัดลำดับวันที่ด้วยรูปแบบ ISO-8601

สำหรับวันที่จัดรูปแบบ JSON ของ ISO-8601 เพียงแค่ส่งสตริงไปยังตัวDateสร้าง:

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

4
@Broam: ทั้งสองวิธี (ฟังก์ชั่นแทนที่และคำตอบนี้) จะต้องเปลี่ยนถ้า MS เปลี่ยนรูปแบบ
Roy Tinker

23
คุณช่วยกรุณาอัพเดทด้วย radix var date = new Date (parseInt (jsonDate.substr (6), 10));
James Kyburz

6
@JamesKyburz: กฎทุกข้อมีข้อยกเว้นและฉันคิดว่านี่เป็นข้อยกเว้น หมายเลขวันที่ของ JSON จาก. NET ไม่เคยมีผู้นำ "0" ดังนั้นเราจึงสามารถปล่อยให้เลขฐานได้อย่างปลอดภัย
Roy Tinker

22
เป็นที่น่าสังเกตว่ารูปแบบวันที่นี้ค่อนข้างแย่และการย้ายทั่วไปคือวันที่ในรูปแบบ ISO-8601 ใน JSON ดูhanselman.com/blog/…
Rory

4
วิธีนี้ไม่สามารถพิจารณาเขตเวลาดังนั้นอาจทำให้เกิดปัญหาร้ายแรงเมื่อเซิร์ฟเวอร์และผู้ใช้ของคุณอยู่ในเขตเวลาที่แตกต่างกัน ฉันโพสต์คำตอบด้านล่างซึ่งอธิบายวิธีที่ง่ายและรวดเร็วในการจัดการกับ WCF และด้าน Javascript: stackoverflow.com/a/10743718/51061
Scott Willeke

135

คุณสามารถใช้สิ่งนี้เพื่อรับวันที่จาก JSON:

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

จากนั้นคุณสามารถใช้สคริปต์รูปแบบวันที่ของ JavaScript (1.2 KB เมื่อลดขนาดและ gzipped) เพื่อแสดงตามที่คุณต้องการ


7
ไม่มีอะไรผิดปกติกับเส้นลำดับคือ \ // เครื่องหมายทับแรกจะถูกหลบหนีดังนั้นจึงไม่นับว่าเป็นความคิดเห็น มันเป็นบรรณาธิการของคุณหลอกคุณบรรทัดจะทำงานได้ดี
andreialecu

152
@rball เรื่องไร้สาระ:jsonDate = new Date(+jsonDate.replace(/\/Date\((\d+)\)\//, '$1'));
หนังตา

39
pst ถูกต้องเป็นไปได้ที่จะทำสิ่งนี้ในหลากหลายวิธีโดยไม่มี 'eval' Crockford กล่าวว่า 'eval Is Evil' เพราะอ่านได้น้อยกว่าและมีความปลอดภัยน้อยกว่านอกจากนี้เขาอาจบอกเป็นนัย ๆ ว่าประสิทธิภาพลดลงและอันตรายมากขึ้นเพราะมันฮิตคอมไพเลอร์ javascript
Mark Rogers

13
@Edy: new Functionเกือบจะไม่ดีเท่าeval: dev.opera.com/articles/view/efficient-javascript/…
Marcel Korpel

5
@Edy: นั่นเป็นอีกรูปแบบหนึ่งของการประเมินและเป็นเพียง 'ความชั่วร้าย' แยกสตริงแทน (ดูคำตอบของฉันด้านล่าง)
Roy Tinker

98

สำหรับผู้ที่ใช้ Newtonsoft Json.NETอ่านบนวิธีการทำมันผ่านพื้นเมือง JSON ใน IE8, Firefox 3.5 บวก Json.NET

นอกจากนี้เอกสารเกี่ยวกับการเปลี่ยนรูปแบบวันที่ที่เขียนโดย Json.NET ก็มีประโยชน์เช่นกัน: วันที่จัดลำดับด้วย Json.NET

สำหรับผู้ที่ขี้เกียจเกินไปนี่คือขั้นตอนด่วน เนื่องจาก JSON มีการนำไปใช้งาน DateTime แบบหลวมคุณจึงต้องใช้IsoDateTimeConverter()หลวมคุณจำเป็นต้องใช้ โปรดทราบว่าตั้งแต่ Json.NET 4.5 รูปแบบวันที่เริ่มต้นคือ ISO ดังนั้นจึงไม่จำเป็นต้องใช้รหัสด้านล่าง

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

JSON จะผ่านพ้นไป

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

ในที่สุด JavaScript บางตัวในการแปลงวันที่ ISO เป็นวันที่ 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;
}

ฉันใช้มันแบบนี้

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

6
ตัวสร้างวันที่ของ JavaScript สามารถแยกสตริงสำหรับคุณ:new Date("2009-04-12T20:44:55")
David Hogue

5
คำเตือน - รูปแบบตัวสร้าง Date () และการแยกวิเคราะห์ไม่ได้มาตรฐานก่อน ECMAScript 6 ตัวอย่างเช่น IE 9 จะถือว่าวันที่คุณให้ตัวสร้างเป็นเวลาท้องถิ่นแม้ว่าจะอยู่ใน IS0-8601 ก็ตาม อย่าพึ่งพาตัวสร้างวันที่หากคุณรองรับเบราว์เซอร์รุ่นเก่า codeofmatt.com/2013/06/07/…
DanO

การส่งวันที่ที่ไม่ใช่ UTC จะทำให้คุณประสบปัญหาไม่ช้าก็เร็ว
tymtam

สายไปงานเลี้ยงเล็กน้อยที่นี่ แต่สิ่งที่จะ (+ a [1], + a [2] - 1, + a [3], + a [4], + a [5], + a [6]) ; เป็นตัวแทนในบริบทนี้?
Yanant

@yanant - The +a[1]ฯลฯ หมายถึงชิ้นอาร์เรย์ของ regex และ+จะโยนมันทิ้งไปยังหมายเลขดังนั้น+a[1]เท่ากับ2009ฯลฯ นี่คือการสลายอาร์เรย์: 0: "2009-04-12T20:44:55" 1: "2009" 2: "04" 3: "12" 4: "20" 5: "44" 6: "55"
เจสัน Jong

67

ตัวอย่างดั้งเดิม:

/Date(1224043200000)/  

ไม่สะท้อนการจัดรูปแบบที่ WCF ใช้เมื่อส่งวันที่ผ่าน WCF REST โดยใช้การทำให้เป็นอันดับ JSON ในตัว (อย่างน้อยใน. NET 3.5, SP1)

ฉันพบคำตอบที่นี่มีประโยชน์ แต่จำเป็นต้องแก้ไข regex เล็กน้อยเนื่องจากปรากฏว่าออฟเซ็ต GMT ออฟเซ็ตของเขตเวลานั้นถูกผนวกเข้ากับหมายเลขที่ส่งคืน (ตั้งแต่ 1970) ใน WCF JSON

ในบริการ WCF ฉันมี:

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

ApptVisitLinkInfo ถูกกำหนดอย่างง่าย ๆ :

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

เมื่อ "Field2" ถูกส่งกลับเป็น Json จากบริการค่าคือ:

/Date(1224043200000-0600)/

ขอให้สังเกตว่าเขตเวลารวมออฟเซ็ตเป็นส่วนหนึ่งของค่า

Regex ที่แก้ไขแล้ว:

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

มันกระตือรือร้นมากขึ้นและคว้าทุกสิ่งระหว่าง parens ไม่ใช่แค่หมายเลขแรก เวลาที่เกิดขึ้นนั้นรวมไปถึงการชดเชยเขตเวลาทั้งหมดสามารถป้อนเข้าสู่ eval เพื่อรับวัตถุวันที่

บรรทัดผลลัพธ์ของ JavaScript สำหรับการแทนที่คือ:

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

10
นี่เป็นความผิดวันใหม่ (1224043200000-0600) จะลบ 600 ออกจากวันเท่านั้นในกรณีนี้คือ 600 ไมล์ต่อวินาทีไม่ใช่ 6 ชั่วโมงเท่าที่ควร
ariel


ฉันคิดว่าการชดเชยเขตเวลาจะรวมอยู่ในกรณีที่คุณมีเขตเวลาในวัตถุ DateTime ใน. NET (ซึ่งเป็นพฤติกรรมเริ่มต้น) หากวันที่ของคุณอยู่ใน UTC ให้ใช้ DateTime.SpecifyKind (date, DateTimeKind.UTC) และคุณจะได้รับค่า UTC ที่เหมาะสมเมื่อมันเป็นอนุกรมโดยไม่มีการชดเชยซึ่งคุณสามารถแปลงกลับเป็นเขตเวลาของผู้ใช้ได้ตามต้องการ หากอยู่ในเวลาท้องถิ่นให้ใช้. ToUniversalTime () และจะแปลงเป็น UTC และระบุ "ชนิด" ไว้ให้คุณแล้ว
jvenema

ใน javascript -0100 จะเป็นสตริงไบนารีดังนั้นระวัง!
verbedr

เมื่อคุณได้รับวันที่แปลงจาก WCF เป็น JS แล้วจะย้อนกลับอย่างไร คุณต้องวันที่เป็นจำนวนเต็ม (ใช้ date.getTime ()) ที่คุณต้องการส่งผ่านไปยัง WCF เดียวกันหรือไม่
NitinSingh

65

อย่าทำซ้ำตัวเองโดยใช้การแปลงวันที่อัตโนมัติ $.parseJSON()

คำตอบสำหรับการโพสต์ของคุณให้การแปลงวันที่ด้วยตนเองเป็นวันที่ JavaScript ฉันได้ขยาย jQuery $.parseJSON()เพียงเล็กน้อยดังนั้นจึงสามารถแยกวันที่โดยอัตโนมัติเมื่อคุณสั่ง มันประมวลผลวันที่จัดรูปแบบ ASP.NET ( /Date(12348721342)/) เช่นเดียวกับวันที่จัดรูปแบบ ISO ( 2010-01-01T12.34.56.789Z) ที่ได้รับการสนับสนุนโดยฟังก์ชั่น JSON พื้นเมืองในเบราว์เซอร์ (และห้องสมุดเช่น json2.js)

อย่างไรก็ตาม. หากคุณไม่ต้องการทำซ้ำรหัสการแปลงวันที่ซ้ำแล้วซ้ำอีกฉันขอแนะนำให้คุณอ่านโพสต์บล็อกนี้และรับรหัสที่จะทำให้ชีวิตของคุณง่ายขึ้นเล็กน้อย


61

ถ้าคุณพูดใน JavaScript

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

คุณจะเห็นว่ามันเป็นวันที่ที่ถูกต้องและคุณสามารถใช้ที่ใดก็ได้ในโค้ด JavaScript ด้วยกรอบงานใด ๆ


3
นั่นคือสิ่งที่ฉันจะคิดเช่นกันเว้นแต่จะเป็น: var thedate = / Date (1224043200000) /; อย่างน้อยสำหรับฉัน ...
rball

2
วันที่ () และวันที่ (1224043200000) ทั้งคู่ให้ผลลัพธ์เหมือนกันทั้งใน Chrome และ Firefox ไม่แน่ใจว่าสิ่งนี้ใช้ได้กับเบราว์เซอร์รุ่นเก่าหรือไม่ แต่คำตอบนี้ใช้ไม่ได้กับเบราว์เซอร์ตอนนี้
James

@ James ใช่มันให้วันที่ปัจจุบันกับเบราว์เซอร์ :(
vissu

9
คุณต้องเขียนเป็น "วันที่ใหม่ (1224043200000)"
BrainSlugs83

60

คลิกที่นี่เพื่อตรวจสอบการสาธิต

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

ผลลัพธ์ - "10/15/2008"


เป็นเพียงการปรับปรุงวิธีการข้างต้น ฟังก์ชั่น formatearFecha (fec) {var value = new Date (parseInt (fec.replace (/ (^. * () | ([+ -]. * $) / g, ''))); var mes = value.getMonth (); var dia = value.getDate (); var date = dia + "/" + mes + "/" + value.getFullYear (); ถ้า (dia <10) date = date.substr (0, 0) + '0' + dia + date.substr (1); ถ้า (mes <10) date = date.substr (0, 3) + '0' + mes + date.substr (4); วันที่ส่งคืน;} วันที่จัดรูปแบบเป็น ddMMyyyy ไชโย!
Matias

38

Updated

เรามีห้องสมุด UI ภายในที่มีการรับมือกับทั้งไมโครซอฟท์ ASP.NET ในตัวรูปแบบ JSON เช่น/Date(msecs)/ถามเกี่ยวกับที่นี่ แต่เดิมและรูปแบบวัน JSON รวมทั้ง JSON.NET 2014-06-22T00:00:00.0ของมากที่สุดเช่น นอกจากนี้เรายังต้องรับมือกับoldIE ที่ไม่สามารถรับมือกับอะไรได้นอกจากทศนิยม 3 ตำแหน่งตำแหน่งทศนิยม

ก่อนอื่นเราตรวจสอบว่าเราใช้วันที่ชนิดใดแยกวิเคราะห์เป็น JavaScript ปกติ Dateวัตถุแล้วจัดรูปแบบที่ออก

1) ตรวจสอบรูปแบบวันที่ของ Microsoft

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

2) ตรวจสอบรูปแบบวันที่ 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) รูปแบบวันที่แยกวิเคราะห์ MS:

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

4) รูปแบบวันที่แยกวิเคราะห์ ISO

อย่างน้อยเรามีวิธีที่จะทำให้แน่ใจว่าเรากำลังจัดการกับวันที่ ISO มาตรฐานหรือวันที่ ISO ที่แก้ไขให้มีสามมิลลิวินาทีเสมอ (ดูด้านบน ) เสมอดังนั้นรหัสจึงแตกต่างกันไปขึ้นอยู่กับสภาพแวดล้อม

4a) รูปแบบวันที่ ISO แบบแยกวิเคราะห์รับมือกับปัญหาของ 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) แยกวิเคราะห์รูปแบบ ISO ด้วยทศนิยมสามมิลลิวินาทีคงที่ - ง่ายกว่ามาก:

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

5) จัดรูปแบบ:

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) ผูกมันทั้งหมดเข้าด้วยกัน:

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

    return formatDate(d);
}

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

คำตอบเก่า

หากคุณใช้ฟังก์ชั่น Ajax ของ jQuery 1.4 กับ ASP.NET MVC คุณสามารถเปลี่ยนคุณสมบัติ DateTime ทั้งหมดเป็นวัตถุวันที่ด้วย:

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

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

ใน jQuery 1.5 คุณสามารถหลีกเลี่ยงการแทนที่parseJSONเมธอดทั่วโลกโดยใช้ตัวเลือกตัวแปลงในการโทร Ajax

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

น่าเสียดายที่คุณต้องเปลี่ยนไปใช้เส้นทาง eval รุ่นเก่าเพื่อให้ Dates แยกวิเคราะห์ทั่วโลกแทน - ไม่เช่นนั้นคุณต้องแปลงเป็นรายกรณีเพิ่มเติม


27

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


ไม่ถูกต้อง JSON ใช้วันที่ของ Javascript พร้อมด้วยข้อมูลเขตเวลาที่เพิ่มเข้ามา - epoch เหมือนกับ epoch ของ class javascript Date (สำหรับเหตุผลที่ชัดเจน)
BrainSlugs83

3
@ BrainSlug83 - คำตอบนี้ให้ข้อมูลอ้างอิงสำหรับการยืนยันว่า JSON ไม่มีประเภทวันที่ในตัว หากคุณไม่เห็นด้วยโปรดให้ข้อมูลอ้างอิงอื่น (คุณไม่ได้นึกถึงกรอบงานเฉพาะที่ตัดสินใจใช้รูปแบบสตริงเพื่อแทนวันที่ใช่หรือไม่นั่นไม่ได้เป็นส่วนหนึ่งของมาตรฐาน JSON จริง ๆ แล้วไม่น่าจะเป็นเพราะมันจะทำให้เป็นไปไม่ได้ที่จะรวมสตริงที่ไม่ใช่ ควรจะเป็นวันที่ แต่มีชุดอักขระที่ตรงกับรูปแบบวันที่)
nnnnnn

25

ฉันต้องค้นหาวิธีการแก้ไขปัญหานี้และในที่สุดฉันก็พบกับ moment.js ซึ่งเป็นห้องสมุดที่ดีที่สามารถแยกรูปแบบวันที่นี้และอีกมากมาย

var d = moment(yourdatestring)

มันช่วยบรรเทาอาการปวดหัวให้ฉันดังนั้นฉันคิดว่าฉันจะแบ่งปันกับคุณ :)
คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับมันได้ที่นี่: http://momentjs.com/


24

ฉันลงเอยด้วยการเพิ่ม "อักขระลงในนิพจน์ปกติของ Panos เพื่อกำจัดสิ่งที่สร้างขึ้นโดย serializer Microsoft สำหรับเมื่อเขียนวัตถุลงในสคริปต์แบบอินไลน์:

ดังนั้นหากคุณมีพร็อพเพอร์ตี้ในรหัส C # ของคุณนั่นเป็นสิ่งที่ต้องการ

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

และใน aspx ของคุณคุณมี

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

คุณจะได้รับสิ่งที่ต้องการ

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

สังเกตคำพูดคู่

ในการทำให้สิ่งนี้เป็นรูปแบบที่ eval จะทำให้เสื่อมเสียสิทธิ์ได้อย่างถูกต้องฉันใช้:

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

ฉันใช้Prototypeและเพื่อเพิ่มมัน

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

22

ใน jQuery 1.5 ตราบใดที่คุณมีjson2.js ที่จะครอบคลุมเบราว์เซอร์รุ่นเก่าคุณสามารถยกเลิกการกำหนดวันที่ทั้งหมดที่มาจาก Ajax ดังนี้:

(function () {
    var DATE_START = "/Date(";
    var DATE_START_LENGTH = DATE_START.length;

    function isDateString(x) {
        return typeof x === "string" && x.startsWith(DATE_START);
    }

    function deserializeDateString(dateString) {
        var dateOffsetByLocalTime = new Date(parseInt(dateString.substr(DATE_START_LENGTH)));
        var utcDate = new Date(dateOffsetByLocalTime.getTime() - dateOffsetByLocalTime.getTimezoneOffset() * 60 * 1000);
        return utcDate;
    }

    function convertJSONDates(key, value) {
      if (isDateString(value)) {
        return deserializeDateString(value);
      }
      return value;
    }

    window.jQuery.ajaxSetup({
      converters: {
        "text json": function(data) {
          return window.JSON.parse(data, convertJSONDates);
        }
      }
    });
}());

ฉันรวมตรรกะที่ถือว่าคุณส่งวันที่ทั้งหมดจากเซิร์ฟเวอร์เป็น UTC (ซึ่งคุณควร); ผู้บริโภคจะได้รับDateวัตถุJavaScript ที่มีค่าติ๊กที่เหมาะสมเพื่อสะท้อนสิ่งนี้ นั่นคือการโทรgetUTCHours()ฯลฯ ในวันที่จะส่งคืนค่าเดียวกันกับที่ทำบนเซิร์ฟเวอร์และการโทรgetHours()จะส่งคืนค่าในเขตเวลาท้องถิ่นของผู้ใช้ตามที่กำหนดโดยเบราว์เซอร์

สิ่งนี้ไม่ได้คำนึงถึงรูปแบบWCF ที่มีการชดเชยเวลา แต่จะเพิ่มได้ง่าย


เช่นเดียวกับหมายเหตุ: เพื่อให้โค้ดทำงานคุณต้องสร้างเมธอด startsWith ของชนิดสตริง
Hugo Zapata

21

การใช้ jQuery UI datepicker จริง ๆ แล้วสมเหตุสมผลถ้าคุณรวม jQuery UI แล้ว:

$.datepicker.formatDate('MM d, yy', new Date(parseInt('/Date(1224043200000)/'.substr(6)))); 

เอาท์พุท:

15 ตุลาคม 2551


20

อย่าคิดมากเกินไป เช่นเดียวกับที่เราทำมานานหลายทศวรรษส่งผ่านการชดเชยตัวเลขจากยุคมาตรฐาน de-facto ของ 1 มกราคม 1970 เที่ยงคืน GMT / UTC / & c ในจำนวนวินาที (หรือมิลลิวินาที) ตั้งแต่ยุคนี้ JavaScript ชอบมัน, Java ชอบมัน, C ชอบและอินเทอร์เน็ตชอบ


2
และแย่มากที่มีมากกว่า 20 ยุคให้เลือก en.wikipedia.org/wiki/Epoch_(reference_date)
Jerther

นั่นเป็นสิ่งที่ดีเกี่ยวกับมาตรฐาน
Marc L.

18

ทุกคำตอบเหล่านี้มีสิ่งหนึ่งที่เหมือนกัน: ทุกคนเก็บวันที่เป็นค่าเดียว (โดยปกติจะเป็นสตริง)

ตัวเลือกอื่นคือการใช้ประโยชน์จากโครงสร้างโดยธรรมชาติของ JSON และแสดงวันที่เป็นรายการของตัวเลข:

{ "name":"Nick",
  "birthdate":[1968,6,9] }

แน่นอนว่าคุณต้องตรวจสอบให้แน่ใจว่าปลายทั้งสองด้านของการสนทนาเห็นด้วยกับรูปแบบ (ปี, เดือน, วัน) และฟิลด์ใดที่มีความหมายว่าเป็นวันที่ ... แต่มันมีข้อดีของการหลีกเลี่ยงปัญหาเรื่องวันที่อย่างสมบูรณ์ การแปลงเป็นสตริง มันคือตัวเลขทั้งหมด - ไม่มีสตริงเลย นอกจากนี้การใช้คำสั่ง: ปีเดือนวันยังช่วยให้การเรียงลำดับที่เหมาะสมตามวันที่

แค่คิดนอกกรอบที่นี่ - วันที่ JSON ไม่จำเป็นต้องเก็บเป็นสตริง

โบนัสอีกอย่างในการทำเช่นนี้คือคุณสามารถเลือก (และมีประสิทธิภาพ) ระเบียนทั้งหมดสำหรับปีหรือเดือนที่กำหนดได้อย่างง่ายดายโดยใช้ประโยชน์จากวิธีที่CouchDBจัดการกับแบบสอบถามเกี่ยวกับค่าอาร์เรย์


มีเป็นรูปแบบมาตรฐานสำหรับวันที่ใน JSON ซึ่งเป็นรูปแบบ RFC 3339
gnasher729

@ ผู้ประกาศที่จะดี แต่ไม่ใช่ในกรณีนี้ ไม่มีการอ้างอิงจาก RFC 7159 ถึง 3339 หรือในทางกลับกัน ไม่มีรูปแบบวันที่ JSON มาตรฐานทางกฎหมาย สิ่งที่เหลืออยู่คือมาตรฐานตามความเป็นจริงแต่ละข้อมีข้อดีข้อเสีย นั่นเป็นสิ่งที่ดีเกี่ยวกับมาตรฐาน
Marc L.

17

โพสต์ในกระทู้ที่น่ากลัว:

var d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2)));
alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2));

1
เป็นแนวคิดที่ดี แต่ถ้ารวมเขตเวลาไว้ด้วย ดีกว่าที่จะใช้ substr (6) ในกรณีนั้นแทนที่จะเป็นชิ้น (6, -2) - ดูคำตอบของฉันด้านล่าง
Roy Tinker

17

เพียงเพื่อเพิ่มวิธีอื่นที่นี่ "วิธีการ ticks" ที่WCFใช้นั้นมีแนวโน้มที่จะเกิดปัญหากับเขตเวลาหากคุณไม่ระวังอย่างยิ่งเช่นที่อธิบายไว้ที่นี่และที่อื่น ๆ ดังนั้นตอนนี้ฉันใช้รูปแบบ ISO 8601 ที่ทั้ง. NET และ JavaScript สนับสนุนรับรองสำเนาถูกต้องซึ่งรวมถึงการปรับค่าเขตเวลา ด้านล่างเป็นรายละเอียด:

ใน WCF / .NET:

โดยที่ CreationDate คือ System.DateTime ToString ("o") กำลังใช้ตัวระบุรูปแบบการเดินทางไป - กลับของ. NET ที่สร้างสตริงวันที่ที่ตรงตามมาตรฐาน ISO 8601

new MyInfo {
    CreationDate = r.CreationDate.ToString("o"),
};

ในจาวาสคริปต์

หลังจากเรียกใช้ JSON ฉันจะแก้ไขวันที่เป็นวัตถุ JavaSript Date โดยใช้ตัวสร้าง Date ซึ่งยอมรับสตริงวันที่ ISO 8601 ...

$.getJSON(
    "MyRestService.svc/myinfo",
    function (data) {
        $.each(data.myinfos, function (r) {
            this.CreatedOn = new Date(this.CreationDate);
        });
        // Now each myinfo object in the myinfos collection has a CreatedOn field that is a real JavaScript date (with timezone intact).
       alert(data.myinfos[0].CreationDate.toLocaleString());
    }
)

เมื่อคุณมีวันที่ JavaScript คุณสามารถใช้วิธี Date ที่สะดวกและเชื่อถือได้เช่นtoDateString , toLocaleStringเป็นต้น


16
var newDate = dateFormat(jsonDate, "mm/dd/yyyy"); 

มีตัวเลือกอื่นโดยไม่ใช้ห้องสมุด jQuery หรือไม่?


นี่เป็นคำถามใหม่และควรถามเป็นคำถามของตนเองและไม่ได้ฝังอยู่ที่นี่
Spencer Sullivan

11

สิ่งนี้อาจช่วยคุณได้

 function ToJavaScriptDate(value) { //To Parse Date from the Returned Parsed Date
        var pattern = /Date\(([^)]+)\)/;
        var results = pattern.exec(value);
        var dt = new Date(parseFloat(results[1]));
        return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
    }

10

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

function JSONDate(dateStr) {
    var m, day;
    jsonDate = dateStr;
    var d = new Date(parseInt(jsonDate.substr(6)));
    m = d.getMonth() + 1;
    if (m < 10)
        m = '0' + m
    if (d.getDate() < 10)
        day = '0' + d.getDate()
    else
        day = d.getDate();
    return (m + '/' + day + '/' + d.getFullYear())
}

function JSONDateWithTime(dateStr) {
    jsonDate = dateStr;
    var d = new Date(parseInt(jsonDate.substr(6)));
    var m, day;
    m = d.getMonth() + 1;
    if (m < 10)
        m = '0' + m
    if (d.getDate() < 10)
        day = '0' + d.getDate()
    else
        day = d.getDate();
    var formattedDate = m + "/" + day + "/" + d.getFullYear();
    var hours = (d.getHours() < 10) ? "0" + d.getHours() : d.getHours();
    var minutes = (d.getMinutes() < 10) ? "0" + d.getMinutes() : d.getMinutes();
    var formattedTime = hours + ":" + minutes + ":" + d.getSeconds();
    formattedDate = formattedDate + " " + formattedTime;
    return formattedDate;
}

10

นอกจากนี้คุณยังสามารถใช้ไลบรารี JavaScript moment.jsซึ่งมีประโยชน์เมื่อคุณวางแผนที่จะจัดการกับรูปแบบที่แปลแล้วและดำเนินการอื่น ๆ ด้วยค่าวันที่:

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

    function (result) {
        $("#AuthMerchId").text(result.AuthorizationMerchantId);
        $("#SttlMerchId").text(result.SettlementMerchantId);
        $("#CreateDate").text(moment(result.AppendDts).format("L"));
        $("#ExpireDate").text(moment(result.ExpiresDts).format("L"));
        $("#LastUpdate").text(moment(result.LastUpdateDts).format("L"));
        $("#LastUpdatedBy").text(result.LastUpdateNt);
        $("#ProcessIn").text(result.ProcessIn);
    }
    );
    return false;
}

การตั้งค่าการโลคัลไลซ์เป็นเรื่องง่ายเหมือนกับการเพิ่มไฟล์กำหนดค่า (คุณสามารถรับไฟล์ได้ใน momentjs.com) ในโปรเจ็กต์ของคุณและกำหนดค่าภาษา:

moment.lang('de');

9

ฉันได้รับวันที่เช่นนี้:

"/Date(1276290000000+0300)/"

ในบางตัวอย่างวันที่อยู่ในรูปแบบที่แตกต่างกันเล็กน้อย:

"/Date(12762900000000300)/"
"Date(1276290000000-0300)"

เป็นต้น

ดังนั้นฉันจึงมาพร้อมกับ RegExp ต่อไปนี้:

/\/+Date\(([\d+]+)\)\/+/

และรหัสสุดท้ายคือ:

var myDate = new Date(parseInt(jsonWcfDate.replace(/\/+Date\(([\d+-]+)\)\/+/, '$1')));

หวังว่ามันจะช่วย

อัปเดต: ฉันพบลิงค์นี้จาก Microsoft: ฉันจะเรียงลำดับวันที่ด้วย JSON ได้อย่างไร

ดูเหมือนว่าเราทุกคนกำลังมองหา


1
การเปลี่ยน Regexp ช้า ... มันเร็วกว่ามากที่จะจับส่วนจำนวนเต็มโดยใช้ substr (6) และส่งต่อไปยัง parseInt () - ดูคำตอบของฉันด้านล่าง
Roy Tinker


9

ตรวจสอบมาตรฐาน ISO วันที่; แบบนี้:

yyyy.MM.ddThh:mm

2008.11.20T22:18มันจะกลายเป็น


ตาม JSON Schema รูปแบบ "วันที่และเวลา" สอดคล้องกับ RFC 3339, ส่วนที่ 5.6 ดังนั้นคุณควรเขียน "yyyy-MM-ddTHH: mm: ssZ" สำหรับวันที่ใน GMT หรือ Z ถูกแทนที่ด้วยเขตเวลาเช่น + hh: mm
gnasher729

ปัญหาคือว่า WCF และอื่น ๆ "เก่า" MS JSON เป็นอันดับไม่ได้ใช้รูปแบบนี้และที่จะต้องคิด
Marc L.

9

มันน่าหงุดหงิด ทางออกของฉันคือการแยกวิเคราะห์ "/ และ /" จากค่าที่สร้างโดย JavaScriptSerializer ของ ASP.NET ดังนั้นแม้ว่า JSON อาจไม่มีวันที่ตามตัวอักษรมันยังคงได้รับการตีความโดยเบราว์เซอร์เป็นวันที่ซึ่งเป็นสิ่งที่ฉันจริงๆ ต้องการ:{"myDate":Date(123456789)}

กำหนดเอง JavaScriptConverter สำหรับ DateTime?

ฉันต้องเน้นความถูกต้องของความคิดเห็นของ Roy Tinker นี่ไม่ใช่ JSON ที่ถูกกฎหมาย แฮ็คสกปรกบนเซิร์ฟเวอร์เพื่อลบปัญหาก่อนที่จะกลายเป็นปัญหาสำหรับ JavaScript มันจะทำให้หายใจไม่ออก JSON parser ฉันใช้มันเพื่อลงจากพื้นดิน แต่ฉันจะไม่ใช้มันอีกต่อไป อย่างไรก็ตามฉันยังรู้สึกว่าคำตอบที่ดีที่สุดอยู่ที่การเปลี่ยนวิธีการที่เซิร์ฟเวอร์จัดรูปแบบวันที่เช่น ISO ตามที่กล่าวไว้ที่อื่น


2
นั่นไม่ใช่ JSON ที่ถูกกฎหมาย มันจะทำงานได้เมื่อประเมินด้วยล่าม Javascript แต่ถ้าคุณใช้โปรแกรมถอดรหัส JSON มันจะทำให้หายใจไม่ออก
Roy Tinker

1
ตกลง และถ้าฉันแค่จัดการกับข้อมูลชิ้นนี้ฉันจะไม่พิจารณามัน แต่ถ้าฉันจัดการกับวัตถุหลายวันที่และคุณสมบัติอื่น ๆ มันง่ายกว่าที่จะประเมิน () สิ่งทั้งหมดนั้นดีกว่าเลือกคุณสมบัติทีละอย่าง ในที่สุดปัญหารากคือการขาดวันที่ (ตามกฎหมาย) JSON เรายังเหลือแฮ็กสร้างสรรค์ของเรา
StarTrekRedneck

8

โพสต์ล่าช้า แต่สำหรับผู้ที่ค้นหาโพสต์นี้

ลองนึกภาพสิ่งนี้:

    [Authorize(Roles = "Administrator")]
    [Authorize(Roles = "Director")]
    [Authorize(Roles = "Human Resources")]
    [HttpGet]
    public ActionResult GetUserData(string UserIdGuidKey)
    {
        if (UserIdGuidKey!= null)
        {
            var guidUserId = new Guid(UserIdGuidKey);
            var memuser = Membership.GetUser(guidUserId);
            var profileuser = Profile.GetUserProfile(memuser.UserName);
            var list = new {
                              UserName = memuser.UserName,
                              Email = memuser.Email ,
                              IsApproved = memuser.IsApproved.ToString() ,
                              IsLockedOut = memuser.IsLockedOut.ToString() ,
                              LastLockoutDate = memuser.LastLockoutDate.ToString() ,
                              CreationDate = memuser.CreationDate.ToString() ,
                              LastLoginDate = memuser.LastLoginDate.ToString() ,
                              LastActivityDate = memuser.LastActivityDate.ToString() ,
                              LastPasswordChangedDate = memuser.LastPasswordChangedDate.ToString() ,
                              IsOnline = memuser.IsOnline.ToString() ,
                              FirstName = profileuser.FirstName ,
                              LastName = profileuser.LastName ,
                              NickName = profileuser.NickName ,
                              BirthDate = profileuser.BirthDate.ToString() ,
            };
            return Json(list, JsonRequestBehavior.AllowGet);
        }
        return Redirect("Index");
    }

อย่างที่คุณเห็นฉันกำลังใช้คุณสมบัติของ C # 3.0 ในการสร้าง Generics "อัตโนมัติ" มันขี้เกียจนิดหน่อย แต่ฉันชอบและมันก็ใช้งานได้ เพียงแค่ทราบ: โปรไฟล์เป็นคลาสที่กำหนดเองที่ฉันสร้างขึ้นสำหรับโครงการแอปพลิเคชันเว็บ


ดังนั้นทุกครั้งที่คุณเพิ่มบทบาทใหม่ [อนุญาต (บทบาท = "ทรัพยากรมนุษย์")] คุณต้องรวบรวมและปรับใช้หรือไม่ ว้าว .... :)
อเล็กซ์ Nolasco

1
หากนี่คือบริการ JSON การเปลี่ยนเส้นทางดูเหมือนจะผิด ฉันจะส่งคืน 404 ไม่พบว่าหากป้อนคีย์ไม่ถูกต้องจะไม่สามารถพบได้ (และ 404 หากไม่พบจริง) เมื่อผู้ใช้ของฉันไม่ได้เข้าสู่ระบบฉันกลับ 403 สิ่งต้องห้าม
Richard Corfield

มันเป็นวิธีที่ "นำมาใช้ใหม่" ตัวอย่างเช่นถ้าฉันต้องการรับข้อมูลผู้ใช้จากมุมมองอื่นฉันสามารถรับได้ตราบเท่าที่ฉันส่งรหัส อย่างไรก็ตามหากไม่ได้ระบุรหัสหน้าจะเปลี่ยนเส้นทางไปยังรายการผู้ใช้ (ดัชนี) เพื่อเลือกผู้ใช้ วิธีแก้ปัญหาง่ายๆที่จำเป็นสำหรับแอพเพียงวิธีที่สมองของฉันปรุงมันในเวลานั้น
Ray Linder

8

FYI สำหรับทุกคนที่ใช้ Python บนฝั่งเซิร์ฟเวอร์: datetime.datetime (). ctime () ส่งคืนสตริงที่สามารถแยกวิเคราะห์ได้โดย "new Date ()" นั่นคือถ้าคุณสร้างอินสแตนซ์ datetime.datetime ใหม่ (เช่นกับ datetime.datetime.now) สตริงสามารถรวมอยู่ในสตริง JSON จากนั้นสตริงนั้นสามารถส่งผ่านเป็นอาร์กิวเมนต์แรกของตัวสร้างวันที่ ฉันยังไม่พบข้อยกเว้นใด ๆ แต่ฉันยังไม่ได้ทดสอบอย่างจริงจังเช่นกัน


8

วิธีการแก้ปัญหา Mootools:

new Date(Date(result.AppendDts)).format('%x')

ต้องการ mootools-more ทดสอบโดยใช้ mootools-1.2.3.1-more บน Firefox 3.6.3 และ IE 7.0.5730.13



8

เพิ่มปลั๊กอินjQuery UIในหน้าของคุณ:

function DateFormate(dateConvert) {
    return $.datepicker.formatDate("dd/MM/yyyy", eval('new ' + dateConvert.slice(1, -1)));
};

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