ฉันจะจัดรูปแบบ DateTime เป็นรูปแบบ UTC ของเว็บได้อย่างไร


90

ฉันมี DateTime ที่ต้องการจัดรูปแบบเป็น " 2009-09-01T00:00:00.000Z" แต่รหัสต่อไปนี้ให้ " 2009-09-01T00:00:00.000+01:00" (ทั้งสองบรรทัด):

new DateTime(2009, 9, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")
new DateTime(2009, 9, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")

มีความคิดอย่างไรที่จะทำให้มันทำงานได้?

คำตอบ:


165
string foo = yourDateTime.ToUniversalTime()
                         .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

1
@Downvoter: คุณต้องการบอกเราว่าคุณคิดว่าผิดกับคำตอบนี้หรือไม่?
LukeH

12
วิธีนี้ใช้งานได้ แต่. ToUniversalTime () จะทำให้วันที่ที่มีอยู่ของคุณยุ่งเหยิงหากเป็นเวลา UTC แล้ว แต่ตัวแปร yourDateTime ไม่ได้ระบุไว้ ฉันลงเอยด้วยการลบ. ToUniversalTime () และวันที่ก็เรียงตามสิ่งที่คาดหวังไว้ที่ปลายทั้งสองข้าง (ฐานข้อมูลและเว็บไคลเอนต์)
Robin Vessey

10
หากเวลาวันที่ของคุณเป็นเวลาสากลอยู่แล้วคุณสามารถโทรหา.ToUniversalTime()ทั้งหมดที่คุณต้องการได้โดยจะไม่เปลี่ยนแปลง - อย่างไรก็ตามหากคุณมีค่าเวลาสากลที่จัดเก็บเป็นเวลาท้องถิ่นแน่นอนว่ามันจะเปลี่ยนไป (แต่ในกรณีนี้คุณมีปัญหาใหญ่ที่ต้องจัดการ!) - อย่างไรก็ตามคำตอบนี้คือ แย่มาก คุณควรใช้"O"สตริงรูปแบบตามที่คำตอบด้านล่างระบุแทน
BrainSlugs83

1
@ BrainSlugs83: คำตอบที่ "แย่มาก" นี้ให้ OP ในสิ่งที่พวกเขาขอ: 2009-09-01T00:00:00.000Z. ใช้ "O" 2009-09-01T00:00:00.0000000Zระบุจะให้พวกเขาบางสิ่งบางอย่างที่แตกต่างกัน
LukeH

เอกสารประกอบการจัดรูปแบบสตริงแบบกำหนดเองสำหรับ DateTime docs.microsoft.com/en-us/dotnet/standard/base-types/…
Mark Hebert

75

ทำไมไม่ใช้เพียงรอบการเดินทาง ( "O", "o") รูปแบบ Specifier ?

ตัวระบุรูปแบบมาตรฐาน "O" หรือ "o" แสดงถึงสตริงรูปแบบวันที่และเวลาที่กำหนดเองโดยใช้รูปแบบที่เก็บรักษาข้อมูลโซนเวลาและส่งสตริงผลลัพธ์ที่สอดคล้องกับ ISO 8601 สำหรับค่า DateTime ตัวระบุรูปแบบนี้ได้รับการออกแบบมาเพื่อรักษาวันที่ และค่าเวลาพร้อมกับคุณสมบัติ DateTime.Kind ในข้อความ สตริงที่จัดรูปแบบสามารถแยกวิเคราะห์กลับได้โดยใช้เมธอด DateTime.Parse (String, IFormatProvider, DateTimeStyles) หรือ DateTime.ParseExact ถ้าพารามิเตอร์ styles ถูกตั้งค่าเป็น DateTimeStyles.RoundtripKind

ตัวระบุรูปแบบมาตรฐาน "O" หรือ "o" สอดคล้องกับ "yyyy" - "MM" - "dd'T'HH": "mm": "ss". "fffffffK" สำหรับค่า DateTime และ "yyyy" - "MM" - "dd'T'HH": "mm": "ss". "fffffffzzz" สตริงรูปแบบที่กำหนดเองสำหรับค่า DateTimeOffset ในสตริงนี้คู่ของเครื่องหมายคำพูดเดี่ยวที่คั่นอักขระแต่ละตัวเช่นยัติภังค์เครื่องหมายทวิภาคและตัวอักษร "T" บ่งชี้ว่าอักขระแต่ละตัวเป็นตัวอักษรที่ไม่สามารถเปลี่ยนแปลงได้ เครื่องหมายวรรคตอนไม่ปรากฏในสตริงเอาต์พุต

ตัวระบุรูปแบบมาตรฐาน O "หรือ" o "(และ" yyyy "-" MM "-" dd'T'HH ":" mm ":" ss "." fffffffK "รูปแบบที่กำหนดเอง) ใช้ประโยชน์จากสามวิธี ISO 8601 นั้นแสดงถึงข้อมูลโซนเวลาเพื่อรักษาคุณสมบัติ Kind ของค่า DateTime:

public class Example
{
   public static void Main()
   {
       DateTime dat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                   DateTimeKind.Unspecified);
       Console.WriteLine("{0} ({1}) --> {0:O}", dat, dat.Kind); 

       DateTime uDat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                    DateTimeKind.Utc);
       Console.WriteLine("{0} ({1}) --> {0:O}", uDat, uDat.Kind);

       DateTime lDat = new DateTime(2009, 6, 15, 13, 45, 30, 
                                    DateTimeKind.Local);
       Console.WriteLine("{0} ({1}) --> {0:O}\n", lDat, lDat.Kind);

       DateTimeOffset dto = new DateTimeOffset(lDat);
       Console.WriteLine("{0} --> {0:O}", dto);
   }
}
// The example displays the following output: 
//    6/15/2009 1:45:30 PM (Unspecified) --> 2009-06-15T13:45:30.0000000 
//    6/15/2009 1:45:30 PM (Utc) --> 2009-06-15T13:45:30.0000000Z 
//    6/15/2009 1:45:30 PM (Local) --> 2009-06-15T13:45:30.0000000-07:00 
//     
//    6/15/2009 1:45:30 PM -07:00 --> 2009-06-15T13:45:30.0000000-07:00

เนื่องจากไม่ได้ผลตามที่ร้องขอคุณจึงยกมาเลย - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffzzz" ไม่ใช่รูปแบบซูลู
astrowalker

@astrowalker มันควรจะทำงาน เขาให้คุณเลือกหลายทางในคำตอบของเขา คุณต้องเลือกเพียงอย่างเดียว ในกรณีของคุณ (และใน OP) คุณจะใช้ DateTimeKind.Utc เพื่อสร้างสตริงที่มี "z" ต่อท้าย (aka "Zulu Format" หรือ "UTC Time") เพียงแค่ดูตัวอย่างผลลัพธ์ของเขาสำหรับ UTC ในกรณีของฉันฉันใช้: dtVariable.ToUniversalTime().ToString("o")ซึ่งจะแปลงไปหรือ"2019-05-26T19:50:34.4400000Z" "yyyy-MM-ddTHH:mm:ss.fffffffZ"หมายเหตุ: ฉันได้ทดสอบสิ่งนี้ด้วยnew Date(dtDateString).getTime()วิธีการของ Javscript แล้วและมันแยกวิเคราะห์สตริงวันที่ที่สร้างโดยสิ่งนี้อย่างถูกต้อง
MikeTeeVee

@MikeTeeVee ฉันแค่ชี้ให้เห็นว่าโซลูชันที่ให้มาใช้ไม่ได้ (สำหรับ DTO) วิธีที่เหมาะสมคือdto.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'"). สำหรับเร็กคอร์ดเพียงแค่"o"เพิ่มออฟเซ็ตไม่ใช่รูปแบบซูลู
astrowalker

1
สำหรับผู้ที่พยายามแปลงสตริง:$"{DateTime.UtcNow:O}"
Tiago César Oliveira

19
string.Format("{0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow)

ผลตอบแทน 2017-02-10T08: 12: 39.483Z


คุณต้องใช้fffแทนมิFFFฉะนั้น 000 จะไม่แสดงเป็นวินาทีตรงกับเครื่องหมาย
Ryan Lundy

6

รูปแบบที่ดีที่สุดที่จะใช้คือ "yyyy" - "MM" - "dd'T'HH": "mm": "ss". "fffK"

K สุดท้ายบนสตริงจะเปลี่ยนเป็น 'Z' หากวันที่เป็น UTC หรือด้วยเขตเวลา (+ -hh: mm) ถ้าเป็นแบบโลคัล ( http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx )

ดังที่ LukeH กล่าวว่าเป็นการดีที่จะใช้ ToUniversalTime หากคุณต้องการให้วันที่ทั้งหมดเป็น UTC

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

string foo = yourDateTime.ToUniversalTime()
                         .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK");

6

มีบางคนชี้ให้เห็นว่า 'ToUniversalTime' ค่อนข้างไม่ปลอดภัยเนื่องจากอาจทำให้เวลาคลาดเคลื่อนโดยไม่ได้ตั้งใจ ขยายความว่าฉันกำลังให้ตัวอย่างรายละเอียดเพิ่มเติมของโซลูชัน ตัวอย่างที่นี่สร้างส่วนขยายให้กับวัตถุ DateTime ที่ส่งคืน UTC DateTime อย่างปลอดภัยซึ่งคุณสามารถใช้ ToString ได้ตามต้องการ ...

class Program
{
    static void Main(string[] args)
    {
        DateTime dUtc = new DateTime(2016, 6, 1, 3, 17, 0, 0, DateTimeKind.Utc);
        DateTime dUnspecified = new DateTime(2016, 6, 1, 3, 17, 0, 0, DateTimeKind.Unspecified);

        //Sample of an unintended mangle:
        //Prints "2016-06-01 10:17:00Z"
        Console.WriteLine(dUnspecified.ToUniversalTime().ToString("u"));

        //Prints "2016 - 06 - 01 03:17:00Z"
        Console.WriteLine(dUtc.SafeUniversal().ToString("u"));

        //Prints "2016 - 06 - 01 03:17:00Z"
        Console.WriteLine(dUnspecified.SafeUniversal().ToString("u"));
    }
}

public static class ConvertExtensions
{
    public static DateTime SafeUniversal(this DateTime inTime)
    {
        return (DateTimeKind.Unspecified == inTime.Kind)
            ? new DateTime(inTime.Ticks, DateTimeKind.Utc)
            : inTime.ToUniversalTime();
    }
}

5

คุณต้องการใช้คลาสDateTimeOffset

var date = new DateTimeOffset(2009, 9, 1, 0, 0, 0, 0, new TimeSpan(0L));
var stringDate = date.ToString("u");

ขออภัยฉันพลาดการจัดรูปแบบเดิมของคุณในช่วงมิลลิวินาที

var stringDate = date.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

5

รหัสนี้ใช้งานได้สำหรับฉัน:

var datetime = new DateTime(2017, 10, 27, 14, 45, 53, 175, DateTimeKind.Local);
var text = datetime.ToString("o");
Console.WriteLine(text);
--  2017-10-27T14:45:53.1750000+03:00

// datetime from string
var newDate = DateTime.ParseExact(text, "o", null);

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