给定DateTime对象,如何获取字符串格式的ISO 8601日期?

给定:

DateTime.UtcNow

如何获取以ISO8601兼容格式表示相同值的字符串?

请注意,ISO 8601定义了许多类似的格式。我正在寻找的特定格式是:

yyyy-MM-ddTHH:mm:ssZ
771253 次浏览
DateTime.UtcNow.ToString("s")

返回类似2008-04-10T06:30:00的内容

UtcNow显然返回了UTC次,所以在以下情况下没有坏处:

string.Concat(DateTime.UtcNow.ToString("s"), "Z")

读者须知:一些评论者指出了这个答案中的一些问题(特别是与第一个建议有关)。请参阅评论部分以获取更多信息。

DateTime.UtcNow.ToString("yyyy-MM-ddTHH\\:mm\\:ss.fffffffzzz", CultureInfo.InvariantCulture);

使用自定义日期时间格式,这将为您提供类似于
的日期2008-09-22 T 13:57:31.2311892-04:00.

另一种方法是:

DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture);

它使用标准“往返”风格(ISO 8601)为您提供
2008-09-22 T 14:01:54.9571247 Z.

要获取指定的格式,您可以使用:

DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)

DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture)应该给你你正在寻找的东西,因为“s”格式说明符被描述为可排序的日期/时间模式;符合ISO 8601。

编辑:要在OP要求的末尾获得额外的Z,请使用"o"而不是"s"

要将DateTime. UtcNow转换为yyyy-MM-ddTHH: mm: ssZ的字符串表示形式,您可以使用带有自定义格式字符串的DateTime结构的ToString()方法。将自定义格式字符串与DateTime一起使用时,请务必记住,您需要使用单引号来转义分隔符。

以下将返回您想要的字符串表示:

DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", DateTimeFormatInfo.InvariantInfo)

我只使用XmlConvert

XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.RoundtripKind);

它会自动保存时区。

"s"标准格式说明符表示由日期时间格式信息。可排序的日期时间模式属性定义的自定义日期和时间格式字符串。该模式反映已定义的标准(ISO8601),并且该属性是只读的。因此,无论使用的区域性或提供的格式提供程序如何,它总是相同的。自定义格式字符串为"yyyy'-'MM'-'dd'T'HH':'mm':'ss"

使用此标准格式说明符时,格式化或解析操作始终使用不变区域性。

-从MSDN

用途:

private void TimeFormats(){DateTime localTime = DateTime.Now;DateTime utcTime = DateTime.UtcNow;DateTimeOffset localTimeAndOffset = new DateTimeOffset(localTime, TimeZoneInfo.Local.GetUtcOffset(localTime));
//UTCstring strUtcTime_o = utcTime.ToString("o");string strUtcTime_s = utcTime.ToString("s");string strUtcTime_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");
//Localstring strLocalTimeAndOffset_o = localTimeAndOffset.ToString("o");string strLocalTimeAndOffset_s = localTimeAndOffset.ToString("s");string strLocalTimeAndOffset_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");
//OutputResponse.Write("<br/>UTC<br/>");Response.Write("strUtcTime_o: " + strUtcTime_o + "<br/>");Response.Write("strUtcTime_s: " + strUtcTime_s + "<br/>");Response.Write("strUtcTime_custom: " + strUtcTime_custom + "<br/>");
Response.Write("<br/>Local Time<br/>");Response.Write("strLocalTimeAndOffset_o: " + strLocalTimeAndOffset_o + "<br/>");Response.Write("strLocalTimeAndOffset_s: " + strLocalTimeAndOffset_s + "<br/>");Response.Write("strLocalTimeAndOffset_custom: " + strLocalTimeAndOffset_custom + "<br/>");
}

输出

UTCstrUtcTime_o: 2012-09-17T22:02:51.4021600ZstrUtcTime_s: 2012-09-17T22:02:51strUtcTime_custom: 2012-09-17T22:02:51Z
Local TimestrLocalTimeAndOffset_o: 2012-09-17T15:02:51.4021600-07:00strLocalTimeAndOffset_s: 2012-09-17T15:02:51strLocalTimeAndOffset_custom: 2012-09-17T22:02:51Z

来源:

如果您在SharePoint 2010或更高版本下开发,您可以使用

using Microsoft.SharePoint;using Microsoft.SharePoint.Utilities;...string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now)
System.DateTime.UtcNow.ToString("o")

=>

val it : string = "2013-10-13T13:03:50.2950037Z"

您可以使用下一个代码获取“Z”(ISO8601UTC):

Dim tmpDate As DateTime = New DateTime(Now.Ticks, DateTimeKind.Utc)Dim res as String = tmpDate.toString("o") '2009-06-15T13:45:30.0000000Z


原因如下:

ISO 8601有一些不同的格式:

日期类型

2009-06-15T13:45:30.0000000-07:00

Utc时间类型

2009-06-15T13:45:30.0000000Z

日期时间类型。未指定

2009-06-15T13:45:30.0000000


. NET为我们提供了一个包含以下选项的枚举:

'2009-06-15T13:45:30.0000000-07:00Dim strTmp1 As String = New DateTime(Now.Ticks, DateTimeKind.Local).ToString("o")
'2009-06-15T13:45:30.0000000ZDim strTmp2 As String = New DateTime(Now.Ticks, DateTimeKind.Utc).ToString("o")
'2009-06-15T13:45:30.0000000Dim strTmp3 As String = New DateTime(Now.Ticks, DateTimeKind.Unspecified).ToString("o")

说明:如果您将Visual Studio 2008“watch实用程序”应用于toString("o")对象类型部分,您可能会得到不同的结果,我不知道它是否是bug,但在这种情况下,如果您正在调试,使用String变量会有更好的结果。

来源:标准日期和时间格式字符串(MSDN)

这些答案中的大多数都有毫秒/微秒,这显然不受ISO 8601的支持。正确的答案是:

System.DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssK");// orSystem.DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");

参考文献:

您有几个选项,包括“往返(“O”)格式说明符”。

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);Console.WriteLine(date1.ToString("O"));Console.WriteLine(date1.ToString("s", System.Globalization.CultureInfo.InvariantCulture));

产出

2008-03-01T07:00:00.00000002008-03-01T07:00:00

但是,DateTime+TimeZone可能会出现博客文章. NET中的DateTime和DateTimeOffset:良好做法和常见缺陷中描述的其他问题:

DateTime中有无数的陷阱,旨在给你的代码错误:

1.-带有DateTimeKind.未指定的DateTime值是坏消息。

2.-DateTime在进行比较时不关心UTC/Local。

3.-DateTime值不知道标准格式字符串。

4.-使用DateTime解析具有UTC标记的字符串并不能保证UTC时间。

有趣的是,自定义格式“yyyy-MM-ddTHH: mm: ssK”(没有ms)是最快的格式方法。

同样有趣的是,“S”格式在Classic上很慢,在Core上很快。

当然数字非常接近,一些行之间的差异是微不足道的(带有后缀_Verify的测试与没有该后缀的测试相同,证明结果的可重复性)

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0Core   : .NET Core 4.6.25009.03, 64bit RyuJIT

Method |  Job | Runtime |       Mean |     Error |    StdDev |     Median |        Min |        Max | Rank |  Gen 0 | Allocated |--------------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|CustomDev1 |  Clr |     Clr | 1,089.0 ns | 22.179 ns | 20.746 ns | 1,079.9 ns | 1,068.9 ns | 1,133.2 ns |    8 | 0.1086 |     424 B |CustomDev2 |  Clr |     Clr | 1,032.3 ns | 19.897 ns | 21.289 ns | 1,024.7 ns | 1,000.3 ns | 1,072.0 ns |    7 | 0.1165 |     424 B |CustomDev2WithMS |  Clr |     Clr | 1,168.2 ns | 16.543 ns | 15.474 ns | 1,168.5 ns | 1,149.3 ns | 1,189.2 ns |   10 | 0.1625 |     592 B |FormatO |  Clr |     Clr | 1,563.7 ns | 31.244 ns | 54.721 ns | 1,532.5 ns | 1,497.8 ns | 1,703.5 ns |   14 | 0.2897 |     976 B |FormatS |  Clr |     Clr | 1,243.5 ns | 24.615 ns | 31.130 ns | 1,229.3 ns | 1,200.6 ns | 1,324.2 ns |   13 | 0.2865 |     984 B |FormatS_Verify |  Clr |     Clr | 1,217.6 ns | 11.486 ns | 10.744 ns | 1,216.2 ns | 1,205.5 ns | 1,244.3 ns |   12 | 0.2885 |     984 B |CustomFormatK |  Clr |     Clr |   912.2 ns | 17.915 ns | 18.398 ns |   916.6 ns |   878.3 ns |   934.1 ns |    4 | 0.0629 |     240 B |CustomFormatK_Verify |  Clr |     Clr |   894.0 ns |  3.877 ns |  3.626 ns |   893.8 ns |   885.1 ns |   900.0 ns |    3 | 0.0636 |     240 B |CustomDev1 | Core |    Core |   989.1 ns | 12.550 ns | 11.739 ns |   983.8 ns |   976.8 ns | 1,015.5 ns |    6 | 0.1101 |     423 B |CustomDev2 | Core |    Core |   964.3 ns | 18.826 ns | 23.809 ns |   954.1 ns |   935.5 ns | 1,015.6 ns |    5 | 0.1267 |     423 B |CustomDev2WithMS | Core |    Core | 1,136.0 ns | 21.914 ns | 27.714 ns | 1,138.1 ns | 1,099.9 ns | 1,200.2 ns |    9 | 0.1752 |     590 B |FormatO | Core |    Core | 1,201.5 ns | 16.262 ns | 15.211 ns | 1,202.3 ns | 1,178.2 ns | 1,225.5 ns |   11 | 0.0656 |     271 B |FormatS | Core |    Core |   993.5 ns | 19.272 ns | 24.372 ns |   999.4 ns |   954.2 ns | 1,029.5 ns |    6 | 0.0633 |     279 B |FormatS_Verify | Core |    Core | 1,003.1 ns | 17.577 ns | 16.442 ns | 1,009.2 ns |   976.1 ns | 1,024.3 ns |    6 | 0.0674 |     279 B |CustomFormatK | Core |    Core |   878.2 ns | 17.017 ns | 20.898 ns |   877.7 ns |   851.4 ns |   928.1 ns |    2 | 0.0555 |     215 B |CustomFormatK_Verify | Core |    Core |   863.6 ns |  3.968 ns |  3.712 ns |   863.0 ns |   858.6 ns |   870.8 ns |    1 | 0.0550 |     215 B |

代码:

    public class BenchmarkDateTimeFormat{public static DateTime dateTime = DateTime.Now;
[Benchmark]public string CustomDev1(){var d = dateTime.ToUniversalTime();var sb = new StringBuilder(20);
sb.Append(d.Year).Append("-");if (d.Month <= 9)sb.Append("0");sb.Append(d.Month).Append("-");if (d.Day <= 9)sb.Append("0");sb.Append(d.Day).Append("T");if (d.Hour <= 9)sb.Append("0");sb.Append(d.Hour).Append(":");if (d.Minute <= 9)sb.Append("0");sb.Append(d.Minute).Append(":");if (d.Second <= 9)sb.Append("0");sb.Append(d.Second).Append("Z");var text = sb.ToString();return text;}
[Benchmark]public string CustomDev2(){var u = dateTime.ToUniversalTime();var sb = new StringBuilder(20);var y = u.Year;var d = u.Day;var M = u.Month;var h = u.Hour;var m = u.Minute;var s = u.Second;sb.Append(y).Append("-");if (M <= 9)sb.Append("0");sb.Append(M).Append("-");if (d <= 9)sb.Append("0");sb.Append(d).Append("T");if (h <= 9)sb.Append("0");sb.Append(h).Append(":");if (m <= 9)sb.Append("0");sb.Append(m).Append(":");if (s <= 9)sb.Append("0");sb.Append(s).Append("Z");var text = sb.ToString();return text;}
[Benchmark]public string CustomDev2WithMS(){var u  = dateTime.ToUniversalTime();var sb = new StringBuilder(23);var y  = u.Year;var d  = u.Day;var M  = u.Month;var h  = u.Hour;var m  = u.Minute;var s  = u.Second;var ms = u.Millisecond;sb.Append(y).Append("-");if (M <= 9)sb.Append("0");sb.Append(M).Append("-");if (d <= 9)sb.Append("0");sb.Append(d).Append("T");if (h <= 9)sb.Append("0");sb.Append(h).Append(":");if (m <= 9)sb.Append("0");sb.Append(m).Append(":");if (s <= 9)sb.Append("0");sb.Append(s).Append(".");sb.Append(ms).Append("Z");var text = sb.ToString();return text;}[Benchmark]public string FormatO(){var text = dateTime.ToUniversalTime().ToString("o");return text;}[Benchmark]public string FormatS(){var text = string.Concat(dateTime.ToUniversalTime().ToString("s"),"Z");return text;}
[Benchmark]public string FormatS_Verify(){var text = string.Concat(dateTime.ToUniversalTime().ToString("s"), "Z");return text;}
[Benchmark]public string CustomFormatK(){var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");return text;}
[Benchmark]public string CustomFormatK_Verify(){var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");return text;}}

https://github.com/dotnet/BenchmarkDotNet被使用

要像2018-06-22T13:04:16这样的格式,可以在API的URI中传递:

public static string FormatDateTime(DateTime dateTime){return dateTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture);}
DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz");
DateTime.Now.ToString("O");

注意:根据您正在进行的转换,您将使用第一行(最喜欢它)或第二行。

请确保仅在本地时间应用格式,因为“zzz”是UTC转换的时区信息。

图片

我很惊讶没有人建议:

System.DateTime.UtcNow.ToString("u").Replace(' ','T')
# Using PowerShell Core to demo
# Lowercase "u" format[System.DateTime]::UtcNow.ToString("u")> 2020-02-06 01:00:32Z
# Lowercase "u" format with replacement[System.DateTime]::UtcNow.ToString("u").Replace(' ','T')> 2020-02-06T01:00:32Z

通用可排序日期时间模式几乎可以让你一直得到你想要的(这更像是rfc3339的表示)。


添加:我决定使用答案https://stackoverflow.com/a/43793679/653058中的基准来比较它的执行情况。

tl: dr;这是昂贵的一端,但在我蹩脚的旧笔记本电脑上仍然只有650纳秒多一点:-)

执行:

[Benchmark]public string ReplaceU(){var text = dateTime.ToUniversalTime().ToString("u").Replace(' ', 'T');return text;}

结果:

// * Summary *
BenchmarkDotNet=v0.11.5, OS=Windows 10.0.19002Intel Xeon CPU E3-1245 v3 3.40GHz, 1 CPU, 8 logical and 4 physical cores.NET Core SDK=3.0.100[Host]     : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJITDefaultJob : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT

|               Method |     Mean |     Error |    StdDev ||--------------------- |---------:|----------:|----------:||           CustomDev1 | 562.4 ns | 11.135 ns | 10.936 ns ||           CustomDev2 | 525.3 ns |  3.322 ns |  3.107 ns ||     CustomDev2WithMS | 609.9 ns |  9.427 ns |  8.356 ns ||              FormatO | 356.6 ns |  6.008 ns |  5.620 ns ||              FormatS | 589.3 ns |  7.012 ns |  6.216 ns ||       FormatS_Verify | 599.8 ns | 12.054 ns | 11.275 ns ||        CustomFormatK | 549.3 ns |  4.911 ns |  4.594 ns || CustomFormatK_Verify | 539.9 ns |  2.917 ns |  2.436 ns ||             ReplaceU | 615.5 ns | 12.313 ns | 11.517 ns |
// * Hints *OutliersBenchmarkDateTimeFormat.CustomDev2WithMS: Default     -> 1 outlier  was  removed (668.16 ns)BenchmarkDateTimeFormat.FormatS: Default              -> 1 outlier  was  removed (621.28 ns)BenchmarkDateTimeFormat.CustomFormatK: Default        -> 1 outlier  was  detected (542.55 ns)BenchmarkDateTimeFormat.CustomFormatK_Verify: Default -> 2 outliers were removed (557.07 ns, 560.95 ns)
// * Legends *Mean   : Arithmetic mean of all measurementsError  : Half of 99.9% confidence intervalStdDev : Standard deviation of all measurements1 ns   : 1 Nanosecond (0.000000001 sec)
// ***** BenchmarkRunner: End *****

使用Newtonsoft. Json,您可以

JsonConvert.SerializeObject(DateTime.UtcNow)

示例:https://dotnetfiddle.net/O2xFSl

正如在其他答案中提到的,DateTime在设计上有问题。

NodaTime

我建议使用NodaTime来管理日期/时间值:

  • 当地时间,日期,日期时间
  • 全球时间
  • 带时区的时间
  • 期间
  • 持续时间

格式

因此,要创建和格式化ZonedDateTime,您可以使用以下代码片段:

var instant1 = Instant.FromUtc(2020, 06, 29, 10, 15, 22);
var utcZonedDateTime = new ZonedDateTime(instant1, DateTimeZone.Utc);utcZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);// 2020-06-29T10:15:22Z

var instant2 = Instant.FromDateTimeUtc(new DateTime(2020, 06, 29, 10, 15, 22, DateTimeKind.Utc));
var amsterdamZonedDateTime = new ZonedDateTime(instant2, DateTimeZoneProviders.Tzdb["Europe/Amsterdam"]);amsterdamZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);// 2020-06-29T12:15:22Z

对我来说,NodaTime代码看起来很冗长。但类型真的很有用。它们有助于正确处理日期/时间值。

牛顿软件包

要将NodaTimeNewtonsoft.Json一起使用,您需要添加对NodaTime.Serialization.JsonNet NuGet包的引用并配置JSON选项。

services.AddMvc().AddJsonOptions(options =>{var settings=options.SerializerSettings;settings.DateParseHandling = DateParseHandling.None;settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);});