Làm cách nào để định dạng DateTime thành định dạng UTC trên web?


89

Tôi có DateTime mà tôi muốn định dạng thành " 2009-09-01T00:00:00.000Z", nhưng mã sau cung cấp cho tôi " 2009-09-01T00:00:00.000+01:00" (cả hai dòng):

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

Bất kỳ ý tưởng làm thế nào để làm cho nó hoạt động?

Câu trả lời:


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

1
@Downvoter: Bạn có muốn cho chúng tôi biết bạn nghĩ gì sai với câu trả lời này không?
LukeH

12
Điều này đã hiệu quả nhưng .ToUniversalTime () sẽ làm rối tung ngày hiện tại của bạn nếu ngày đó đã đến UTC nhưng biến yourDateTime không chỉ định ngày đó. Tôi đã kết thúc việc loại bỏ .ToUniversalTime () và các ngày sau đó sắp xếp theo những gì được mong đợi ở cả hai đầu (cơ sở dữ liệu và ứng dụng khách web).
Robin Vessey

10
Nếu ngày tháng của bạn đã là giờ quốc tế, bạn có thể gọi .ToUniversalTime()tất cả những gì bạn muốn, nó sẽ không thay đổi nó. - Tuy nhiên, nếu bạn có một giá trị thời gian chung được lưu trữ dưới dạng giờ địa phương, thì tất nhiên nó sẽ thay đổi nó (nhưng trong trường hợp đó, bạn có những vấn đề lớn hơn phải giải quyết!) - Dù sao, câu trả lời này là khủng khiếp. "O"Thay vào đó, bạn nên sử dụng chuỗi định dạng như được chỉ định bởi câu trả lời bên dưới.
BrainSlugs83

1
@ BrainSlugs83: Câu trả lời này "khủng khiếp" thực sự mang đến cho OP những gì họ yêu cầu: 2009-09-01T00:00:00.000Z. Sử dụng "O" specifier sẽ cung cấp cho họ một cái gì đó khác nhau: 2009-09-01T00:00:00.0000000Z.
LukeH

Tài liệu về định dạng chuỗi tùy chỉnh cho DateTime docs.microsoft.com/en-us/dotnet/standard/base-types/…
Mark Hebert

75

Tại sao không chỉ sử dụng Định dạng khứ hồi ("O", "o") ?

Bộ xác định định dạng chuẩn "O" hoặc "o" đại diện cho một chuỗi định dạng ngày và giờ tùy chỉnh bằng cách sử dụng một mẫu lưu giữ thông tin múi giờ và tạo ra một chuỗi kết quả tuân theo ISO 8601. Đối với các giá trị DateTime, bộ định dạng này được thiết kế để lưu giữ ngày và giá trị thời gian cùng với thuộc tính DateTime.Kind trong văn bản. Chuỗi đã định dạng có thể được phân tích cú pháp lại bằng cách sử dụng phương thức DateTime.Parse (String, IFormatProvider, DateTimeStyles) hoặc DateTime.ParseExact nếu tham số kiểu được đặt thành DateTimeStyles.RoundtripKind.

Mã định dạng chuẩn "O" hoặc "o" tương ứng với chuỗi định dạng tùy chỉnh "yyyy '-' MM '-' dd'T'HH ':' mm ':' ss '.' FffffffK" cho các giá trị DateTime và "yyyy" - 'MM' - 'dd'T'HH': 'mm': 'ss'. 'fffffffzzz "chuỗi định dạng tùy chỉnh cho các giá trị DateTimeOffset. Trong chuỗi này, các cặp dấu ngoặc kép phân tách các ký tự riêng lẻ, chẳng hạn như dấu gạch ngang, dấu hai chấm và chữ "T", cho biết rằng ký tự riêng lẻ là một chữ không thể thay đổi. Dấu nháy đơn không xuất hiện trong chuỗi đầu ra.

Bộ định dạng định dạng chuẩn O "hoặc" o "(và chuỗi định dạng tùy chỉnh" yyyy "- 'MM' - 'dd'T'HH': 'mm': 'ss'. 'FffffffK") tận dụng lợi thế của ba cách ISO 8601 đại diện cho thông tin múi giờ để duy trì thuộc tính Loại của các giá trị 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

Bởi vì nó không hoạt động theo yêu cầu, bạn đã trích dẫn nó - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffzzz" không phải là định dạng Zulu.
astrowalker

@astrowalker Nó sẽ hoạt động. Anh ấy đã cho bạn nhiều lựa chọn trong câu trả lời của mình. Bạn chỉ cần chọn một. Trong trường hợp của bạn (và trong OP), bạn sẽ sử dụng DateTimeKind.Utc để tạo chuỗi có "z" ở cuối (còn gọi là "Định dạng Zulu" hoặc "Giờ UTC"). Chỉ cần nhìn vào đầu ra ví dụ của anh ấy cho UTC. Trong trường hợp của tôi, tôi đã sử dụng: dtVariable.ToUniversalTime().ToString("o")sẽ chuyển đổi thành "2019-05-26T19:50:34.4400000Z"hoặc "yyyy-MM-ddTHH:mm:ss.fffffffZ". Lưu ý: Tôi cũng đã thử nghiệm điều này với new Date(dtDateString).getTime()phương pháp của Javscript và nó phân tích cú pháp chính xác chuỗi ngày được tạo bởi phương thức này.
MikeTeeVee

@MikeTeeVee, tôi vừa chỉ ra các giải pháp được cung cấp sẽ không hoạt động (đối với DTO). Cách thích hợp là dto.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'"). Đối với bản ghi, chỉ cần "o"thêm bù đắp, nó không phải là định dạng Zulu.
astrowalker

1
Đối với những người cố gắng để làm một sự chuyển đổi chuỗi:$"{DateTime.UtcNow:O}"
Tiago César Oliveira

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

trả về 2017-02-10T08: 12: 39.483Z


6

Định dạng tốt nhất để sử dụng là "yyyy" - 'MM' - 'dd'T'HH': 'mm': 'ss'. 'FffK ".

K cuối cùng trên chuỗi sẽ được thay đổi thành 'Z' nếu ngày là UTC hoặc với múi giờ (+ -hh: mm) nếu là địa phương. ( http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx )

Như LukeH đã nói, bạn nên sử dụng ToUniversalTime nếu bạn muốn rằng tất cả các ngày sẽ là UTC.

Mã cuối cùng là:

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

6

Một số người đã chỉ ra rằng 'ToUniversalTime' hơi không an toàn ở chỗ nó có thể gây ra chênh lệch thời gian không chính xác ngoài ý muốn. Mở rộng ra, tôi đang cung cấp một ví dụ chi tiết hơn về giải pháp. Mẫu ở đây tạo một phần mở rộng cho đối tượng DateTime trả về một cách an toàn DateTime UTC nơi bạn có thể sử dụng ToString như mong muốn….

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

Bạn muốn sử dụng lớp DateTimeOffset .

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

xin lỗi tôi đã bỏ lỡ định dạng ban đầu của bạn với mili giây

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

5

Mã này đang làm việc cho tôi:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.