Bagaimana cara memformat DateTime ke format web UTC?

90

Saya memiliki DateTime yang ingin saya format menjadi " 2009-09-01T00:00:00.000Z", tetapi kode berikut memberi saya " 2009-09-01T00:00:00.000+01:00" (kedua baris):

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

Ada ide bagaimana membuatnya bekerja?

Grzenio
sumber

Jawaban:

165
string foo = yourDateTime.ToUniversalTime()
                         .ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
LukeH
sumber
1
@Downvoter: Apakah Anda ingin memberi tahu kami apa yang menurut Anda salah dengan jawaban ini?
LukeH
12
Ini berhasil tetapi .ToUniversalTime () akan mengacaukan tanggal yang ada jika sudah di UTC tetapi variabel yourDateTime tidak menentukannya. Saya akhirnya menghapus .ToUniversalTime () dan tanggal kemudian sejalan dengan apa yang diharapkan di kedua ujung (database dan klien web).
Robin Vessey
10
Jika waktu tanggal Anda sudah menjadi waktu universal, Anda dapat memanggil .ToUniversalTime()semua yang Anda inginkan, itu tidak akan mengubahnya. - Namun, jika Anda memiliki nilai waktu universal yang disimpan sebagai waktu lokal, maka tentu saja itu akan mengubahnya (tetapi dalam kasus ini, Anda memiliki masalah yang lebih besar untuk ditangani!) - Bagaimanapun, jawabannya adalah mengerikan. Anda harus menggunakan "O"string format seperti yang ditentukan oleh jawaban di bawah ini.
BrainSlugs83
1
@ BrainSlugs83: ini "mengerikan" Jawabannya benar-benar memberikan OP apa yang mereka minta: 2009-09-01T00:00:00.000Z. Menggunakan "O" specifier akan memberi mereka sesuatu yang berbeda: 2009-09-01T00:00:00.0000000Z.
LukeH
Dokumentasi untuk pemformatan string kustom untuk DateTime docs.microsoft.com/en-us/dotnet/standard/base-types/…
Mark Hebert
75

Mengapa tidak hanya menggunakan Penentu Format The Round-trip ("O", "o") ?

Penentu format standar "O" atau "o" mewakili string format tanggal dan waktu kustom menggunakan pola yang mempertahankan informasi zona waktu dan mengeluarkan string hasil yang sesuai dengan ISO 8601. Untuk nilai DateTime, penentu format ini dirancang untuk mempertahankan tanggal dan nilai waktu bersama dengan properti DateTime.Kind dalam teks. String yang diformat dapat diurai kembali dengan menggunakan metode DateTime.Parse (String, IFormatProvider, DateTimeStyles) atau DateTime.ParseExact jika parameter gaya disetel ke DateTimeStyles.RoundtripKind.

Penentu format standar "O" atau "o" sesuai dengan string format kustom "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffffffK" untuk nilai DateTime dan "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' fffffffzzz" string format khusus untuk nilai DateTimeOffset. Dalam string ini, pasangan tanda kutip tunggal yang membatasi karakter individu, seperti tanda hubung, titik dua, dan huruf "T", menunjukkan bahwa karakter individu adalah literal yang tidak dapat diubah. Tanda kutip tidak muncul di string keluaran.

Penentu format standar O "atau" o "(dan string format kustom" yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffffffK ") memanfaatkan tiga cara bahwa ISO 8601 mewakili informasi zona waktu untuk mempertahankan properti Jenis nilai 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
Dmitry Pavlov
sumber
Karena tidak berfungsi seperti yang diminta, Anda mengutipnya - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffzzz" bukan format Zulu.
astrowalker
@astrowalker Seharusnya berhasil. Dia memberi Anda banyak pilihan dalam jawabannya. Anda hanya perlu memilih satu. Dalam kasus Anda (dan dalam OP), Anda akan menggunakan DateTimeKind.Utc untuk menghasilkan string dengan "z" di akhir (alias "Zulu Format" atau "UTC Time"). Lihat saja contoh keluarannya untuk UTC. Dalam kasus saya, saya menggunakan: dtVariable.ToUniversalTime().ToString("o")yang akan diubah menjadi "2019-05-26T19:50:34.4400000Z"atau "yyyy-MM-ddTHH:mm:ss.fffffffZ". Catatan: Saya juga telah menguji ini dengan new Date(dtDateString).getTime()metode Javscript dan dengan benar mengurai string tanggal yang dihasilkan oleh ini.
MikeTeeVee
@MikeTeeVee, saya baru saja menunjukkan bahwa solusi yang diberikan tidak akan berfungsi (untuk DTO). Cara yang tepat adalah dto.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'"). Sebagai catatan, "o"tambahkan saja offset, bukan format Zulu.
astrowalker
1
Bagi mereka yang mencoba melakukan transformasi string:$"{DateTime.UtcNow:O}"
Tiago César Oliveira
19
string.Format("{0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow)

mengembalikan 2017-02-10T08: 12: 39.483Z

arviman
sumber
Anda perlu menggunakan fffalih-alih FFFatau 000 tidak akan ditampilkan sedetik pun tepat pada tanda.
Ryan Lundy
6

Format terbaik untuk digunakan adalah "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffK".

K terakhir pada string akan diubah menjadi 'Z' jika tanggalnya UTC atau dengan zona waktu (+ -hh: mm) jika lokal. ( http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx )

Seperti yang dikatakan LukeH, sebaiknya gunakan ToUniversalTime jika Anda ingin semua tanggalnya UTC.

Kode terakhirnya adalah:

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

Beberapa orang telah menunjukkan bahwa 'ToUniversalTime' agak tidak aman karena dapat menyebabkan penyebaran waktu yang salah yang tidak diinginkan. Memperluas itu saya memberikan contoh solusi yang lebih rinci. Contoh di sini membuat ekstensi ke objek DateTime yang mengembalikan DateTime UTC dengan aman di mana Anda dapat menggunakan ToString sesuai keinginan….

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();
    }
}
pengguna3228938
sumber
5

Anda ingin menggunakan kelas DateTimeOffset .

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

maaf saya melewatkan format asli Anda dengan milidetik

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

Kode ini berfungsi untuk saya:

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);
Ergin Çelik
sumber
-3

Coba ini:

DateTime date = DateTime.ParseExact(
    "Tue, 1 Jan 2008 00:00:00 UTC", 
    "ddd, d MMM yyyy HH:mm:ss UTC", 
    CultureInfo.InvariantCulture);

Pertanyaan sebelumnya

Ian P
sumber
3
Saya belum mencoba menguraikannya, saya mencoba mencetaknya.
Grzenio