Parse cadena a DateTime en C #

Tengo fecha y hora en una cadena formateada como esa:

"2011-03-21 13:26" //year-month-day hour:minute 

¿Cómo puedo analizarlo en System.DateTime ?

Quiero usar funciones como DateTime.Parse() o DateTime.ParseExact() si es posible, para poder especificar el formato de la fecha de forma manual.

DateTime.Parse() intentará averiguar el formato de la fecha determinada, y generalmente hace un buen trabajo. Si puede garantizar que las fechas siempre estarán en un formato determinado, entonces puede usar ParseExact() :

 string s = "2011-03-21 13:26"; DateTime dt = DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture); 

(Pero tenga en cuenta que generalmente es más seguro usar uno de los métodos TryParse en caso de que una fecha no esté en el formato esperado)

Asegúrese de marcar Cadenas de Formato de Fecha y Hora Personalizadas cuando construya una cadena de formato, especialmente preste atención al número de letras y mayúsculas y minúsculas (es decir, “MM” y “mm” significan cosas muy diferentes).

Otro recurso útil para cadenas de formato C # es el formato de cadena en C #

Como explicaré más adelante, siempre preferiría los métodos TryParse y TryParseExact . Debido a que son un poco voluminosos de usar, he escrito un método de extensión que hace que el análisis sea mucho más fácil:

 var dtStr = "2011-03-21 13:26"; DateTime? dt = dtStr.toDate("yyyy-MM-dd HH:mm"); 

A diferencia de Parse , ParseExact , etc. no arroja una excepción, y le permite verificar a través de

if (dt.HasValue) { // continue processing } else { // do error handling }

si la conversión fue exitosa (en este caso, dt tiene un valor al que puede acceder a través de dt.Value ) o no (en este caso, es null ).

¿Eso incluso permite usar atajos elegantes como el operador “Elvis” ?. , por ejemplo:

 int? year = dtStr?.toDate("yyyy-MM-dd HH:mm")?.Year; 

Aquí también puede usar year.HasValue para verificar si la conversión fue exitosa, y si no tuvo éxito, el year contendrá null , de lo contrario, la parte del año de la fecha. No hay excepción lanzada si la conversión falló.

Pruébalo en .NetFiddle

 public static class Extensions { public static DateTime? toDate(this string dateTimeStr, string[] dateFmt) { // example: var dt = "2011-03-21 13:26".toDate(new string[]{"yyyy-MM-dd HH:mm", // "M/d/yyyy h:mm:ss tt"}); const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces; if (dateFmt == null) { var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat; dateFmt=dateInfo.GetAllDateTimePatterns(); } DateTime? result = null; DateTime dt; if (DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture, style, out dt)) result = dt; return result; } public static DateTime? toDate(this string dateTimeStr, string dateFmt=null) { // example: var dt="2011-03-21 13:26".toDate("yyyy-MM-dd HH:mm"); // or simply var dt="2011-03-21 13:26".toDate(); // call overloaded function with string array param string[] dateFmtArr = dateFmt == null ? null : new string[] { dateFmt }; return toDate(dateTimeStr, dateFmtArr); } } 

Actualización: .toDate() (sin parámetros) ahora se establece de manera predeterminada en todos los patrones de fecha / hora comunes de la cultura actual de la secuencia.
Tenga en cuenta que necesitamos el result y dt juntos, porque TryParseExact no permite usar DateTime? , que tenemos la intención de devolver En la versión 7 de C # , podría simplificar un poco la función toDate siguiente manera:

  // in C#7 only: "DateTime dt;" - no longer required, declare implicitly if (DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture, style, out var dt)) result = dt; 

(También se podría escribir out DateTime dt lugar de out var dt .)

Ejemplo:

 var dtStr="2011-03-21 13:26"; var dt=dtStr.toDate("yyyy-MM-dd HH:mm"); if (dt.HasValue) { Console.WriteLine("Successful!"); // ... dt.Value now contains the converted DateTime ... } else { Console.WriteLine("Invalid date format!"); } 

Como puede ver, este ejemplo simplemente consulta dt.HasValue para ver si la conversión fue exitosa o no. Como bonificación adicional, TryParseExact permite especificar DateTimeStyles estrictos para que sepa exactamente si se ha pasado o no una cadena de fecha / hora adecuada.


Nota : la función sobrecargada le permite pasar una matriz de formatos válidos utilizados para analizar / convertir fechas como se muestra aquí ( TryParseExact admite directamente), por ejemplo

 string[] dateFmt = {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", "M/d/yyyy h:mm", "M/d/yyyy h:mm", "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"}; var dtStr="5/1/2009 6:32 PM"; var dt=dtStr.toDate(dateFmt); 

Sin embargo, para mantener el código corto, estoy usando solo la sobrecarga de la matriz de cadenas de TryParseExact, porque no funcionaba con un parámetro genérico.

Ejemplo avanzado:
Puedes usar el ?? operador a un formato de seguridad predeterminado, por ejemplo

 var dtStr = "2017-12-30 11:37:00"; var dt = (dtStr.toDate()) ?? dtStr.toDate("yyyy-MM-dd HH:mm:ss"); 

En este caso, .toDate() usaría formatos de fecha de cultura local comunes, y si todos estos fallaran, trataría de usar el formato estándar ISO "yyyy-MM-dd HH:mm:ss" como una alternativa. De esta forma, la función de extensión permite “encadenar” fácilmente diferentes formatos de respaldo.


Finalmente, aquí hay algunos comentarios sobre el fondo (es decir, la razón por la que lo escribí de esta manera):

Estoy prefiriendo TryParseExact en este método de extensión, porque evitas el manejo de excepciones . Puedes leer en el artículo de Eric Lippert las excepciones por las que debes usar TryParse en lugar de Parse, lo cito sobre ese tema: 2)

Esta desafortunada decisión de diseño 1) [anotación: dejar que el método Parse arroje una excepción] fue tan irritante que, por supuesto, el equipo de frameworks implementó TryParse poco después, lo que hace lo correcto.

Lo hace, pero TryParse y TryParseExact ambos todavía son mucho menos que cómodos de usar: te obligan a usar una variable no inicializada como un parámetro de out que no debe ser anulable y mientras estás convirtiendo necesitas evaluar el valor de retorno booleano – o bien tiene que usar una instrucción if inmediatamente o tiene que almacenar el valor devuelto en una variable booleana adicional para que pueda hacer la verificación más adelante. Y no puede usar la variable objective sin saber si la conversión fue exitosa o no.

En la mayoría de los casos, solo desea saber si la conversión fue exitosa o no (y por supuesto, el valor si fue exitosa) , por lo que una variable de destino que se anula y guarde toda la información sería deseable y mucho más elegante, porque toda la información es simplemente almacenado en un solo lugar: es consistente y fácil de usar, y mucho menos propenso a errores.

El método de extensión que he escrito hace exactamente eso (también le muestra qué tipo de código debería escribir siempre si no va a usarlo).

Creo que el beneficio de .toDate(strDateFormat) es que parece simple y limpio, tan simple como se suponía que era el DateTime.Parse original, pero con la capacidad de verificar si la conversión fue exitosa y sin lanzar excepciones.


1) Lo que se quiere decir aquí es el manejo de excepciones (es decir, un bloque try { ... } catch(Exception ex) { ...} ), que es necesario cuando usa Parse porque generará una excepción si no es válido la cadena se analiza, no solo es innecesaria en este caso, sino que también es molesta y complica el código. TryParse evita todo esto a medida que se muestra la muestra del código que he proporcionado.


2) Eric Lippert es un famoso miembro de StackOverflow y trabajó en Microsoft como desarrollador principal en el equipo comstackdor de C # durante un par de años.

 var dateStr = @"2011-03-21 13:26"; var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture); 

¡Mira este enlace para ver otras cadenas de formato!

DateTime.Parse () debería funcionar bien para ese formato de cadena. Referencia:

http://msdn.microsoft.com/en-us/library/1k1skd40.aspx#Y1240

¿Lanza una FormatException por ti?

Pon el valor de una cadena legible por humanos en .NET DateTime con un código como este:

 DateTime.ParseExact("April 16, 2011 4:27 pm", "MMMM d, yyyy h:mm tt", null); 

También puede usar XmlConvert.ToDateString

 var dateStr = "2011-03-21 13:26"; var parsedDate = XmlConvert.ToDateTime(dateStr, "yyyy-MM-dd hh:mm"); 

Es bueno especificar el tipo de fecha, el código es:

 var anotherParsedDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd hh:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); 

Más detalles sobre las diferentes opciones de análisis http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html

La respuesta simple y directa ->

 using System; namespace DemoApp.App { public class TestClassDate { public static DateTime GetDate(string string_date) { DateTime dateValue; if (DateTime.TryParse(string_date, out dateValue)) Console.WriteLine("Converted '{0}' to {1}.", string_date, dateValue); else Console.WriteLine("Unable to convert '{0}' to a date.", string_date); return dateValue; } public static void Main() { string inString = "05/01/2009 06:32:00"; GetDate(inString); } } } /** * Output: * Converted '05/01/2009 06:32:00' to 5/1/2009 6:32:00 AM. * */