如何将 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 即可获得答案。对于有问题的原始字符串P72H
和P2M2W5D
,问题在于该字符串必须符合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 架构的一部分。 P2M5D
和 P2M19D
一样有效,我假设这是您在字符串中使用 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 时间戳?
如何配置 web api 的 json 序列化器将日期时间转换为 ISO 8601 格式?