如何从 ISO 8601 格式创建 .NET DateTime
Posted
技术标签:
【中文标题】如何从 ISO 8601 格式创建 .NET DateTime【英文标题】:How to create a .NET DateTime from ISO 8601 format 【发布时间】:2011-04-03 03:19:02 【问题描述】:我找到了如何将 DateTime 转换为 ISO 8601 格式,但没有关于如何在 C# 中执行相反的操作。
我有2010-08-20T15:00:00Z
,我想把它变成DateTime
对象。
我可以自己分离字符串的各个部分,但对于已经成为国际标准的东西来说,这似乎需要做很多工作。
【问题讨论】:
Convert String to Date in .NET的可能重复 @abatishchev,这就是为什么它不是重复的。 “重复”中的答案不处理 8601。 是的,这不是重复的。这个问题专门针对解析 ISO 8601 格式。 【参考方案1】:此解决方案利用DateTimeStyles 枚举,它也适用于 Z。
DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);
这完美地打印了解决方案。
【讨论】:
DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);
的编辑解决方案似乎运行良好。
有人想详细说明这个DateTimeStyles.RoundtripKind?
MSDN 描述是空白的。
似乎对这个问题进行了编辑以反映更好的答案,但由于@MamtaD 覆盖了原始答案,因此 cmets 变得非常具有误导性。一开始我不确定答案是否正确,因为上面有 cmets,但后来我意识到不正确的答案后来被正确的替换了
对小数位数不起作用。 2018-06-19T14:56:14.123Z
被解析为本地时间,而不是 UTC。我使用 CultureInfo.InvariantCulture
而不是 null。
有关DateTimeStyles.RoundTripKind
的更多信息,请参阅***.com/q/39572395/2014893【参考方案2】:
虽然 MSDN 说“s”和“o”格式反映了标准,但它们似乎只能解析其中的有限子集。如果字符串包含时区规范,尤其是它是一个问题。 (对于基本的 ISO8601 格式或降低精度的格式都不是这样——但这不完全是你的情况。)这就是为什么我在解析 ISO8601 时使用自定义格式字符串的原因。目前我首选的 sn-p 是:
static readonly string[] formats =
// Basic formats
"yyyyMMddTHHmmsszzz",
"yyyyMMddTHHmmsszz",
"yyyyMMddTHHmmssZ",
// Extended formats
"yyyy-MM-ddTHH:mm:sszzz",
"yyyy-MM-ddTHH:mm:sszz",
"yyyy-MM-ddTHH:mm:ssZ",
// All of the above with reduced accuracy
"yyyyMMddTHHmmzzz",
"yyyyMMddTHHmmzz",
"yyyyMMddTHHmmZ",
"yyyy-MM-ddTHH:mmzzz",
"yyyy-MM-ddTHH:mmzz",
"yyyy-MM-ddTHH:mmZ",
// Accuracy reduced to hours
"yyyyMMddTHHzzz",
"yyyyMMddTHHzz",
"yyyyMMddTHHZ",
"yyyy-MM-ddTHHzzz",
"yyyy-MM-ddTHHzz",
"yyyy-MM-ddTHHZ"
;
public static DateTime ParseISO8601String ( string str )
return DateTime.ParseExact ( str, formats,
CultureInfo.InvariantCulture, DateTimeStyles.None );
如果您不介意解析无 TZ 字符串(我愿意),您可以添加一个“s”行来大大扩展涵盖的格式更改的数量。
【讨论】:
使用K
允许您将不同的时区处理组合在一起。我在***.com/a/31246449/400547 有一个更广泛的变体,但它是否过于广泛(接受有效的 ISO 8601 但未在更常见的配置文件中使用的东西)但它确实显示了K
如何将大小减少三分之一。
【参考方案3】:
using System.Globalization;
DateTime d;
DateTime.TryParseExact(
"2010-08-20T15:00:00",
"s",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal, out d);
【讨论】:
在 LinqPad 中产生 False 和 d ~~> "1/1/0001 12:00:00 AM" :( @Reb: "2010-08-20T15:00:00" 和 "s",如果最后没有 "Z" 已更正 :) Z 出现在我所有的样本中(恰好来自各种 GPS 单元和 GPX 文件) 在另一个 ISO 8601 参考文献中发现“Z”代表区域——就像在时区中一样。 Z 实际上代表祖鲁时间或 UTC。 en.wikipedia.org/wiki/ISO_8601#UTC【参考方案4】:这是一个更适合我的(LINQPad 版本):
DateTime d;
DateTime.TryParseExact(
"2010-08-20T15:00:00Z",
@"yyyy-MM-dd\THH:mm:ss\Z",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal,
out d);
d.ToString()
生产
true
8/20/2010 8:00:00 AM
【讨论】:
目前在我的单元测试中使用它来验证我希望成为日期的所有字符串都是 Iso8601 格式。谢谢! 为什么返回的时间戳不是UTC?!相当大地违反了最小惊讶原则,因为“AssumeUniversal”的“不变文化”不应该这样做,因为 DST 在世界范围内的差异如此之大,因此如果您开始运行代码,返回您当地的主要时区可能会引入错误在具有不同设置的服务器上!【参考方案5】:要使TryParseExact
工作,完全匹配ISO 字符串的格式似乎很重要。我猜 Exact 就是 Exact,这个答案对大多数人来说是显而易见的,但无论如何......
就我而言,Reb.Cabin 的回答不起作用,因为我的输入与下面的“值”略有不同。
值:2012-08-10T14:00:00.000Z
在毫秒内有一些额外的 000,可能还有更多。
但是,如果我将一些.fff
添加到如下所示的格式中,一切都很好。
格式字符串:@"yyyy-MM-dd\THH:mm:ss.fff\Z"
在 VS2010 即时窗口中:
DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d);
是的
您可能还必须使用DateTimeStyles.AssumeLocal
,具体取决于您的时间所在的区域...
【讨论】:
这对我有用,但我还必须将AssumeUniversal
更改为 AdjustToUniversal
。【参考方案6】:
这在 LINQPad4 中运行良好:
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z"));
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00"));
Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00"));
【讨论】:
【参考方案7】:DateTime.ParseExact(...)
允许您告诉解析器每个字符代表什么。
【讨论】:
以上是关于如何从 ISO 8601 格式创建 .NET DateTime的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?
如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?
PowerShell中iso8601格式日期和DateTime对象互转实例