Cómo crear un .NET DateTime a partir del formato ISO 8601

He encontrado cómo convertir un DateTime en un formato ISO 8601 , pero nada sobre cómo hacer el reverso en C #.

Tengo 2010-08-20T15:00:00Z , y quiero convertirlo en un objeto DateTime .

Podría separar las partes de la cuerda, pero parece mucho trabajo para algo que ya es un estándar internacional.

Esta solución hace uso de la enumeración DateTimeStyles , y también funciona con Z.

 DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind); 

Esto imprime la solución perfectamente.

 using System.Globalization; DateTime d; DateTime.TryParseExact( "2010-08-20T15:00:00", "s", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out d); 

Aunque MSDN dice que los formatos “s” y “o” reflejan el estándar, parece que solo pueden analizar un subconjunto limitado de este. Especialmente es un problema si la cadena contiene la especificación de zona horaria. (Ni tampoco para formatos básicos ISO8601, o formatos de precisión reducidos, sin embargo, este no es exactamente su caso). Es por eso que uso cadenas de formato personalizadas cuando se trata de analizar ISO8601. Actualmente, mi fragmento preferido es:

 static readonly string[] formats = { // Basic formats "yyyyMMddTHHmmsszzz", "yyyyMMddTHHmmsszz", "yyyyMMddTHHmmssZ", // Extended formats "yyyy-MM-ddTHH:mm:sszzz", "yyyy-MM-ddTHH:mm:sszz", "yyyy-MM-ddTHH:mm:ssZ", // All of the above with reduced accuracy "yyyyMMddTHHmmzzz", "yyyyMMddTHHmmzz", "yyyyMMddTHHmmZ", "yyyy-MM-ddTHH:mmzzz", "yyyy-MM-ddTHH:mmzz", "yyyy-MM-ddTHH:mmZ", // Accuracy reduced to hours "yyyyMMddTHHzzz", "yyyyMMddTHHzz", "yyyyMMddTHHZ", "yyyy-MM-ddTHHzzz", "yyyy-MM-ddTHHzz", "yyyy-MM-ddTHHZ" }; public static DateTime ParseISO8601String ( string str ) { return DateTime.ParseExact ( str, formats, CultureInfo.InvariantCulture, DateTimeStyles.None ); } 

Si no te importa analizar cadenas TZ-less (sí), puedes agregar una línea “s” para ampliar en gran medida la cantidad de alteraciones de formato cubiertas.

Aquí hay uno que funciona mejor para mí (versión LINQPad ):

 DateTime d; DateTime.TryParseExact( "2010-08-20T15:00:00Z", @"yyyy-MM-dd\THH:mm:ss\Z", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out d); d.ToString() 

produce

 true 8/20/2010 8:00:00 AM 

Parece importante que coincida exactamente con el formato de la cadena ISO para que funcione TryParseExact . Supongo que Exact is Exact y esta respuesta es obvia para la mayoría, pero de todos modos …

En mi caso, la respuesta de Reb.Cabin no funciona ya que tengo una entrada ligeramente diferente según mi “valor” a continuación.

Valor: 2012-08-10T14:00:00.000Z

Hay algunos miles extra por milisegundos y puede haber más.

Sin embargo, si agrego algunos .fff al formato que se muestra a continuación, todo está bien.

Cadena de formato: @"yyyy-MM-dd\THH:mm:ss.fff\Z"

En la ventana Inmediato VS2010:

 DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d); 

cierto

Puede que tenga que usar DateTimeStyles.AssumeLocal también dependiendo de la zona en la que esté su tiempo …

Esto funciona bien en LINQPad4:

 Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z")); Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00")); Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00")); 

DateTime.ParseExact(...) permite decirle al analizador qué representa cada personaje.