Pergunta

Existe um método de biblioteca padrão que converte uma string que tem duração no padrão ISO 8601 Duration (também usado em XSD para sua duration type) no objeto .NET TimeSpan?

Por exemplo, P0DT1H0M0S que representa a duração de uma hora, é convertido em New TimeSpan(0,1,0,0,0).

Existe um conversor reverso que funciona da seguinte maneira:Xml.xmlconvert.toString (novo timespan (0,1,0,0,0)) A expressão acima retornará P0DT1H0M0S.

Foi útil?

Solução

Isso irá converter de xs:duration para TimeSpan:

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

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

Outras dicas

Uma pequena palavra de cautela - XmlConvert.ToTimeSpan() é um pouco engraçado quando se trabalha com meses e anos.A classe TimeSpan não possui membros de mês ou ano, provavelmente porque sua duração varia.No entanto, ToTimeSpan() aceitará alegremente uma string de duração com valores de mês ou ano e adivinhar por duração, em vez de lançar uma exceção.Observar:

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>

Como disse o troll sujo @ima, o TimeSpan sempre traduz anos como 365 dias e meses como 30 dias.

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 resolvê -lo, você deve adicionar cada campo individualmente, em vez de usar o 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top