如何将DateTime格式化为Web UTC格式?


89

我有一个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")

有什么想法如何使其工作吗?

Answers:


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

1
@Downvoter:您想告诉我们您认为这个答案有什么问题吗?
2014年

12
这可行,但是.ToUniversalTime()会弄乱您现有的日期(如果已经在UTC处,但是yourDateTime变量未指定)。我最终删除了.ToUniversalTime(),然后将日期与两端(数据库和Web客户端)的预期日期对齐。
罗宾·威西

10
如果您的日期时间已经是世界通用时间,则可以调用.ToUniversalTime()所有您想要的日期,而不会更改它。-但是,如果您已经将通用时间值存储为本地时间,则当然它将对其进行更改(但是在这种情况下,您将面临更大的问题要解决!)-无论如何,这个答案是可怕。您应该使用"O"以下答案指定的格式字符串。
BrainSlugs83 '18 -10-29

1
@ BrainSlugs83:这个“糟糕”的答案实际上给了OP他们所要求的:2009-09-01T00:00:00.000Z。使用“ O”说明符会使他们有所不同:2009-09-01T00:00:00.0000000Z
路加

文档自定义字符串格式化的DateTime docs.microsoft.com/en-us/dotnet/standard/base-types/...
马克·赫伯特

74

为什么不只使用往返(“ O”,“ o”)格式说明符

“ O”或“ o”标准格式说明符使用保留时区信息并发出符合ISO 8601的结果字符串的模式表示自定义日期和时间格式字符串。对于DateTime值,此格式说明符旨在保留日期和时间值以及文本中的DateTime.Kind属性。如果将styles参数设置为DateTimeStyles.RoundtripKind,则可以使用DateTime.Parse(String,IFormatProvider,DateTimeStyles)或DateTime.ParseExact方法来解析格式化的字符串。

标准格式说明符“ O”或“ o”对应于DateTime值的自定义格式字符串“ yyyy'-'MM'-'dd'T'HH':'mm':'ss'。'fffffffK” DateTimeOffset值的“ yyyy'-'MM'-'dd'T'HH':'mm':'ss'。'fffffffzzz”自定义格式字符串。在此字符串中,用单引号对界定单个字符(例如,连字符,冒号和字母“ T”),表示单个字符是不能更改的文字。撇号不会出现在输出字符串中。

O”或“ o”标准格式说明符(以及“ yyyy'-'MM'-'dd'T'HH':'mm':'ss'。'fffffffK”自定义格式字符串)利用了三种方式ISO 8601代表时区信息以保留DateTime值的Kind属性:

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" 不是Zulu格式。
astrowalker

@astrowalker应该起作用。他在回答中给了您多种选择。您只需要选择一个即可。在您的情况下(以及在OP中),您将使用DateTimeKind.Utc产生结尾处带有“ z”的字符串(也称为“ Zulu格式”或“ UTC时间”)。只需看看他的UTC示例输出即可。就我而言,我使用了: dtVariable.ToUniversalTime().ToString("o")将转换为"2019-05-26T19:50:34.4400000Z""yyyy-MM-ddTHH:mm:ss.fffffffZ"。注意:我还使用Javscript的new Date(dtDateString).getTime()方法对此进行了测试,它可以正确解析由此产生的日期字符串。
MikeTeeVee

@MikeTeeVee,我只是指出提供的解决方案不起作用(对于DTO)。合适的方法是dto.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'")。为了记录,仅"o"添加偏移量,它不是Zulu格式。
astrowalker

1
对于那些尝试进行字符串转换的人:$"{DateTime.UtcNow:O}"
TiagoCésarOliveira

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

返回2017-02-10T08:12:39.483Z


6

最好使用的格式是“ yyyy”-'MM'-'dd'T'HH':'mm':'ss'。'fffK”。

如果日期是UTC,则字符串上的最后一个K会更改为“ Z”;如果是本地日期,则将使用时区(+ -hh:mm)。(http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

正如LukeH所说,如果希望所有日期都为UTC,最好使用ToUniversalTime。

最终的代码是:

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

-3

试试这个:

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

先前问的问题


3
我尚未尝试解析(但),而是尝试将其打印出来。
Grzenio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.