如何将 ISO8601 TimeSpan 转换为 C# TimeSpan?

Posted

技术标签:

【中文标题】如何将 ISO8601 TimeSpan 转换为 C# TimeSpan?【英文标题】:How do I convert an ISO8601 TimeSpan to a C# TimeSpan? 【发布时间】:2012-09-10 01:52:47 【问题描述】:

当我尝试执行以下操作(例如)时,我收到了System.FormatException

TimeSpan ts = XmlConvert.ToTimeSpan("P72H");

我已经调查了ISO8601 Standard,它似乎是正确的,但无论我做什么,我都无法让它在不抛出异常的情况下解析小时数。

谢谢!

编辑:

异常详情:

System.FormatException was unhandled by user code
HResult=-2146233033
Message=The string 'P72H' is not a valid TimeSpan value.
Source=System.Xml

【问题讨论】:

@Oded 这不是关于 .NET 字符串格式的问题。 @Oded 明确一点,我没有从类型不匹配中得到异常,我是从 XmlConvert.ToTimeSpan 方法中得到的。这是一个关于将 ISO8601 标准持续时间字符串转换为 C# 可用格式的问题。 @Magnus P72H 表示持续时间为 72 小时 【参考方案1】:

您需要在字符串中添加时间分隔符。试试这个:

TimeSpan ts = XmlConvert.ToTimeSpan("PT72H");

查看持续时间规范 - http://www.w3.org/TR/xmlschema-2/#duration

3.2.6.1 词法表示 持续时间的词法表示是 [ISO 8601] 扩展格式 PnYn MnDTnH nMnS,其中 nY 表示年数,nM 表示月数,nD 表示天数,'T' 是日期/时间分隔符,nH 表示数字小时数,nM 分钟数和 nS 秒数。秒数可以包含任意精度的十进制数字。

基于 cmets 编辑/更新

由于W 是 ISO 8601 标准的一部分,为什么字符串 P2M2W5D 不会被视为有效的 TimeSpan 存在一些问题,所以我想添加此更新,以便如果有人遇到它他们不必通读 cmets 即可获得答案。对于有问题的原始字符串P72HP2M2W5D,问题在于该字符串必须符合W3C XML Schema(请参阅XmlConvert.ToTimeSpan 的文档)。当我们查看 W3C XML Schema(上面的链接)时,它引用了 ISO 8601 标准,特别是第 5.5.3.2.1 节,它给出了W 在 XML Schema 中不是有效字符的原因:

由于周没有明确的结转点(52 或 53),因此周应 不能在这些应用程序中使用

【讨论】:

@Pheonixblade9 - 因为D是天,所以在指示时间的时候需要加上时间分隔符T 来自 ISO8601 Wikipedia URL:“为了解决歧义,“P1M”是一个月的持续时间,“PT1M”是一分钟的持续时间(注意时间指示符 T,它在时间之前价值)。” P4D 没有歧义,它不包含任何时间分量,但“T”对于具有时间分量的值是必需的。 因为“W”不是 ISO8601 架构的一部分。 P2M5DP2M19D 一样有效,我假设这是您在字符串中使用 2W 的意图。 @AlexandruMărculescu - 抱歉,当我回复您的评论并忘记标记您时,我已经筋疲力尽了。您的问题是 W 不是 ISO8601 架构的一部分。如果您的意思是“周”,只需将 2W 转换为 14D 就可以了。 @CristiDiaconescu - 抱歉,我的评论不清楚(请注意关于困倦程度的后续评论)实际问题是字符串必须符合 W3C XML Schema(请参阅MSDN XmlConvert.ToTimeSpan)然后答案中的链接。)您会发现 W3C XML Schema 然后引用回 ISO 标准,特别是第 5.5.3.2.1 节,其中指出“由于周没有定义的结转点(52 或 53),周应该不能在这些应用程序中使用”【参考方案2】:

您一定遗漏了标准中的某些内容。以下:

System.Xml.XmlConvert.ToString(TimeSpan.FromHours(12))

给我字符串PT12H。所以似乎时间部分需要以T 为前缀。以下解析正确:

System.Xml.XmlConvert.ToTimeSpan("PT25H")

(到一个TimeSpan,字符串化为1.01:00:00。)

【讨论】:

【参考方案3】:

System.Xml.XmlConvert.ToTimeSpan("PnYnMnDTnHnMnS") 请使用以下格式。 P - 指示符必须放在日期格式之前。 nY - 年数,例如:2Y nM - 月数 例如:4M nD - 天数 例如:6D T - 必须放在时间格式之前的指示符 nH - 小时数 例如:8H nM - 分钟数 例如:12M nS - 秒数 例如:14S

    System.Xml.XmlConvert.ToTimeSpan("P2Y4M6DT8H12M14S")

这里,与月和分混淆的部分用相同的字母表示,但指示符的用法使它们分开以便于理解。

【讨论】:

以上是关于如何将 ISO8601 TimeSpan 转换为 C# TimeSpan?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Shell 将 ISO 8601 时间戳转换为 Unix 时间戳?

如何将 Excel 中的日期转换为 ISO 8601 格式

将 ISO 8601 转换为 unix 时间戳

如何配置 web api 的 json 序列化器将日期时间转换为 ISO 8601 格式?

将 ISO 8601 日期时间字符串转换为 **Date** 对象时,如何将日期时间重新定位到当前时区?

如何在 PHP 中将日期时间转换为 ISO 8601