2008-09-15 25 views
13

¿Existe un método de biblioteca estándar que convierta una cadena que tenga una duración en el formato estándar ISO 8601 Duración (también utilizado en XSD para su formato duration) en el objeto .NET TimeSpan?Cómo convertir la duración de ISO 8601 a TimeSpan en VB.Net?

Por ejemplo, P0DT1H0M0S que representa una duración de una hora, se convierte en New TimeSpan (0,1,0,0,0).

Un convertidor inversa existe, que funciona de la siguiente manera: Xml.XmlConvert.ToString (Nueva TimeSpan (0,1,0,0,0)) La expresión anterior devolverá P0DT1H0M0S.

Respuesta

17

Una palabra de menor importancia de la precaución - XmlConvert.ToTimeSpan() es un poco raro cuando se trabaja con meses y años. La clase TimeSpan no tiene miembros de mes o año, probablemente porque su longitud varía. Sin embargo, ToTimeSpan() aceptará felizmente una cadena de duración con valores de mes o año y supongo a una duración, en lugar de lanzar una excepción. Observe:

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

Funfact: Los meses son raros. 'P11M' => 330 días pero' P12M' => 365 días – Trajan

0

Como @ima dirty troll dijo TimeSpan traduce siempre años como 365 días y meses como 30 días.

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

para abordarlo debe agregar cada campo individualmente en lugar de utilizar 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 
+0

No hay una regla que diga que los valores no tienen más de 4 dígitos, por cierto. P10000YT20000H es una duración de xs perfectamente válida, pero su expresión regular no lo aceptaría. – Alex

Cuestiones relacionadas