关于.net:如何在VB.Net中将ISO 8601持续时间转换为TimeSpan?

关于.net:如何在VB.Net中将ISO 8601持续时间转换为TimeSpan?

How to Convert ISO 8601 Duration to TimeSpan in VB.Net?

是否存在一种标准库方法,该方法可以将具有标准ISO 8601持续时间(在XSD中也以duration类型使用)的持续时间的字符串转换为.NET TimeSpan对象?

例如,代表一个小时的持续时间的P0DT1H0M0S被转换为New TimeSpan(0,1,0,0,0)。

确实存在一个反向转换器,其工作方式如下:
Xml.XmlConvert.ToString(New TimeSpan(0,1,0,0,0))
上面的表达式将返回P0DT1H0M0S。


这将从xs:duration转换为TimeSpan:

1
System.Xml.XmlConvert.ToTimeSpan("P0DT1H0M0S")

请参阅http://msdn.microsoft.com/en-us/library/system.xml.xmlconvert.totimespan.aspx


一个小小的警告词-XmlConvert.ToTimeSpan()在处理数月和数年时有点有趣。 TimeSpan类没有月或年成员,可能是因为其长度不同。 但是,ToTimeSpan()会很乐意接受一个带有月或年值的持续时间字符串,并猜测一个持续时间,而不是抛出异常。 观察:

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
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肮脏的巨魔所说,TimeSpan总是将年转换为365天,将月转换为30天。

1
2
3
TimeSpan ts = System.Xml.XmlConvert.ToTimeSpan("P5Y");
DateTime now = new DateTime(2008,2,29);
Console.WriteLine(now + ts); // 27/02/2013 0:00:00

为了解决这个问题,您应该单独添加每个字段
比使用TimeSpan。

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
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


推荐阅读