如何在 VB.Net 中将 ISO 8601 持续时间转换为 TimeSpan?
题
是否有一个标准库方法可以转换具有标准 ISO 8601 持续时间(也用于 XSD 中)的持续时间的字符串 duration
type) 格式转换为 .NET TimeSpan 对象?
例如,P0DT1H0M0S 表示一小时的持续时间,将转换为 New TimeSpan(0,1,0,0,0)。
确实存在反向转换器,其工作原理如下:xml.xmlconvert.tostring(new TimesPan(0,1,0,0,0))上述表达式将返回P0DT1H0M0S。
解决方案
这将从 xs:duration 转换为 TimeSpan:
System.Xml.XmlConvert.ToTimeSpan("P0DT1H0M0S")
看 http://msdn.microsoft.com/en-us/library/system.xml.xmlconvert.totimespan.aspx
其他提示
需要注意一点 - XmlConvert.ToTimeSpan() 在处理月份和年份时有点有趣。TimeSpan 类没有月份或年份成员,可能是因为它们的长度不同。但是,ToTimeSpan() 很乐意接受其中包含月份或年份值的持续时间字符串,并且 猜测 在一段时间内,而不是抛出异常。观察:
PS C:\Users\troll> [Reflection.Assembly]::LoadWithPartialName("System.Xml")
GAC Version Location
--- ------- --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System.Xml.dll
PS C:\Users\troll> [System.Xml.XmlConvert]::ToTimeSpan("P1M")
Days : 30
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 0
Ticks : 25920000000000
TotalDays : 30
TotalHours : 720
TotalMinutes : 43200
TotalSeconds : 2592000
TotalMilliseconds : 2592000000
PS C:\Users\troll> [System.Xml.XmlConvert]::ToTimeSpan("P1Y")
Days : 365
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 0
Ticks : 315360000000000
TotalDays : 365
TotalHours : 8760
TotalMinutes : 525600
TotalSeconds : 31536000
TotalMilliseconds : 31536000000
PS C:\Users\troll>
正如 @ima dirty troll 所说,TimeSpan 总是将年翻译为 365 天,将月份翻译为 30 天。
TimeSpan ts = System.Xml.XmlConvert.ToTimeSpan("P5Y");
DateTime now = new DateTime(2008,2,29);
Console.WriteLine(now + ts); // 27/02/2013 0:00:00
要解决它,您应该单独添加每个字段,而不是使用时间板。
DateTime now = new DateTime (2008, 2, 29);
string duration = "P1Y";
Regex expr =
new Regex (@"(-?)P((\d{1,4})Y)?((\d{1,4})M)?((\d{1,4})D)?(T((\d{1,4})H)?((\d{1,4})M)?((\d{1,4}(\.\d{1,3})?)S)?)?", RegexOptions.Compiled | RegexOptions.CultureInvariant);
bool positiveDuration = false == (input [0] == '-');
MatchCollection matches = expr.Matches (duration);
var g = matches [0];
Func<int,int> getNumber = x => {
if (g.Groups.Count < x || string.IsNullOrEmpty (g.Groups [x].ToString ())) {
return 0;
}
int a = int.Parse (g.Groups [x].ToString ());
return PositiveDuration ? a : a * -1;
};
now.AddYears (getNumber (3));
now.AddMonths (getNumber (5));
now.AddDays (getNumber (7));
now.AddHours (getNumber (10));
now.AddMinutes (getNumber (12));
now.AddSeconds (getNumber (14));
Console.WriteLine (now); // 28/02/2012 0:00:00
不隶属于 StackOverflow