Given a DateTime object, how do I get an ISO 8601 date in string format?
鉴于:
1 | DateTime.UtcNow |
如何获得一个字符串,该字符串以符合ISO 8601的格式表示相同的值?
请注意,ISO 8601定义了许多类似的格式。我要找的具体格式是:
1 | yyyy-MM-ddTHH:mm:ssZ |
02
这给你一个类似于2008-09-22t13:57:31.2311892-04:00的日期。
另一种方法是:
1 | DateTime.UtcNow.ToString("o"); |
给你2008-09-22t14:01:54.9571247Z
要获取指定的格式,可以使用:
1 | DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") |
日期时间格式选项
1 | DateTime.UtcNow.ToString("s") |
返回类似2008-04-10t06:30:00的值
1 | string.Concat(DateTime.UtcNow.ToString("s"),"Z") |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private void TimeFormats() { DateTime localTime = DateTime.Now; DateTime utcTime = DateTime.UtcNow; DateTimeOffset localTimeAndOffset = new DateTimeOffset(localTime, TimeZoneInfo.Local.GetUtcOffset(localTime)); //UTC string strUtcTime_o = utcTime.ToString("o"); string strUtcTime_s = utcTime.ToString("s"); string strUtcTime_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK"); //Local string strLocalTimeAndOffset_o = localTimeAndOffset.ToString("o"); string strLocalTimeAndOffset_s = localTimeAndOffset.ToString("s"); string strLocalTimeAndOffset_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK"); //Output Response.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/>"); } |
产量
1 2 3 4 5 6 7 8 9 | UTC strUtcTime_o: 2012-09-17T22:02:51.4021600Z strUtcTime_s: 2012-09-17T22:02:51 strUtcTime_custom: 2012-09-17T22:02:51Z Local Time strLocalTimeAndOffset_o: 2012-09-17T15:02:51.4021600-07:00 strLocalTimeAndOffset_s: 2012-09-17T15:02:51 strLocalTimeAndOffset_custom: 2012-09-17T22:02:51Z |
资料来源:
标准日期和时间格式字符串(msdn)
自定义日期和时间格式字符串(msdn)
1 | System.DateTime.UtcNow.ToString("o") |
= >
1 | val it : string ="2013-10-13T13:03:50.2950037Z" |
您可以使用以下代码获得"Z"(ISO 8601 UTC):
1 2 | Dim tmpDate As DateTime = New DateTime(Now.Ticks, DateTimeKind.Utc) Dim res as String = tmpDate.toString("o") '2009-06-15T13:45:30.0000000Z |
< BR>
这就是为什么:
ISO 8601有一些不同的格式:
日期时间类型.本地
1 | 2009-06-15T13:45:30.0000000-07:00 |
日期时间类型.utc
1 | 2009-06-15T13:45:30.0000000Z |
日期时间类型。未指定
1 | 2009-06-15T13:45:30.0000000 |
< BR>
.NET为我们提供了一个具有以下选项的枚举:
1 2 3 4 5 6 7 8 | '2009-06-15T13:45:30.0000000-07:00 Dim strTmp1 As String = New DateTime(Now.Ticks, DateTimeKind.Local).ToString("o") '2009-06-15T13:45:30.0000000Z Dim strTmp2 As String = New DateTime(Now.Ticks, DateTimeKind.Utc).ToString("o") '2009-06-15T13:45:30.0000000 Dim strTmp3 As String = New DateTime(Now.Ticks, DateTimeKind.Unspecified).ToString("o") |
注意:如果将Visual Studio 2008"Watch实用程序"应用于ToString("O")部分,可能会得到不同的结果,我不知道这是否是bug,但在这种情况下,如果正在调试,则使用字符串变量可以获得更好的结果。
来源:标准日期和时间格式字符串(msdn)
如果您必须使用日期时间到iso 8601,那么toString("o")应该生成您要查找的内容。例如,
1 | 2015-07-06T12:08:27 |
但是,datetime+timezone可能会出现其他问题,如.net中的blog post datetime和datetimeoffset中所述:良好实践和常见缺陷:
DateTime has countless traps in it that are designed to give your code bugs:
1.- DateTime values with DateTimeKind.Unspecified are bad news.
2.- DateTime doesn't care about UTC/Local when doing comparisons.
3.- DateTime values are not aware of standard format strings.
4.- Parsing a string that has a UTC marker with DateTime does not guarantee a UTC time.
我只想用
1 | XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.RoundtripKind); |
它将自动保留时区。
这些答案中的大多数都有毫秒/微秒,这显然不受ISO 8601的支持。正确答案是:
1 2 3 | System.DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssK"); // or System.DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK"); |
参考文献:
- ISO 8601规范
- "K"说明符
要将datetime.utcnow转换为yy-mm-ddthh:mm:ssz的字符串表示形式,可以使用带有自定义格式字符串的datetime结构的toString()方法。在将自定义格式字符串与日期时间一起使用时,必须记住需要使用单引号来转义分隔符。
下面将返回所需的字符串表示:
1 | DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", DateTimeFormatInfo.InvariantInfo) |
The
"s" standard format specifier represents a custom date and time format string that is defined by the DateTimeFormatInfo.SortableDateTimePattern property. The pattern reflects a defined standard (ISO 8601), and the property is read-only. Therefore, it is always the same, regardless of the culture used or the format provider supplied. The custom format string is"yyyy'-'MM'-'dd'T'HH':'mm':'ss" .When this standard format specifier is used, the formatting or parsing operation always uses the invariant culture.
-来自MSDN
1 2 3 | DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz"); DateTime.Now.ToString("O"); |
注意:根据您在末尾所做的转换,您将使用第一行(最喜欢它)或第二行。
请确保仅在本地时间应用格式,因为"zzz"是用于UTC转换的时区信息。
有趣的是,自定义格式"yyyy-mm-ddthh:mm:ssk"(不带ms)是最快的格式方法。
有趣的是,"S"格式在经典上慢,在核心上快…
当然,数字非常接近,某些行之间的差异是不显著的(后缀为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393 Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4 Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0 Clr : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0 Core : .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 | |
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 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中传递:
1 2 3 4 | public static string FormatDateTime(DateTime dateTime) { return dateTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture); } |
如果您在SharePoint 2010或更高版本下开发,则可以使用
1 2 3 4 | using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; ... string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now) |
令人惊讶的是没有人建议:
1 | System.DateTime.UtcNow.ToString("u").Replace(' ','T') |
UniversalSortableDateTimePattern让您几乎可以随心所欲(这更像是一个RFC3339表示)。
使用newtonsoft.json,您可以
1 | JsonConvert.SerializeObject(DateTime.UtcNow) |
示例:https://dotnetfiddle.net/o2xfsl