Comment convertir la durée ISO 8601 en TimeSpan dans VB.Net?
Question
Existe-t-il une méthode de bibliothèque standard qui convertit une chaîne dont la durée est au format standard ISO 8601 Duration (également utilisé dans XSD pour son type duration
) en objet .NET TimeSpan?
Par exemple, P0DT1H0M0S, qui représente une durée d’une heure, est converti en New TimeSpan (0,1,0,0,0).
Il existe un convertisseur inversé qui fonctionne comme suit: Xml.XmlConvert.ToString (New TimeSpan (0,1,0,0,0)) L’expression ci-dessus renverra P0DT1H0M0S.
La solution
Ceci convertira de xs: duration en TimeSpan:
System.Xml.XmlConvert.ToTimeSpan("P0DT1H0M0S")
Voir http://msdn.microsoft.com /en-us/library/system.xml.xmlconvert.totimespan.aspx
Autres conseils
Un petit mot de prudence - XmlConvert.ToTimeSpan () est un peu drôle quand on travaille avec des mois et des années. La classe TimeSpan n'a pas de membres par mois ou par année, probablement parce que leur durée varie. Cependant, ToTimeSpan () acceptera avec plaisir une chaîne de durée contenant des valeurs de mois ou d'année et devine au lieu d'une exception. Observez:
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>
Comme le dit @ima dirty troll, TimeSpan traduit les années en 365 jours et les mois en 30 jours.
TimeSpan ts = System.Xml.XmlConvert.ToTimeSpan("P5Y");
DateTime now = new DateTime(2008,2,29);
Console.WriteLine(now + ts); // 27/02/2013 0:00:00
Pour y remédier, vous devez ajouter chaque champ individuellement plutôt que que d'utiliser TimeSpan.
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