2011-03-20 12 views
109

he fecha y hora en una cadena con formato como aquél:analizar la cadena de DateTime en C#

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

¿Cómo se puede analizar lo que System.DateTime?

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

+17

Así que ¿por qué no se utiliza DateTime.Parse? –

+7

Yo era uno de los downvoters. Fue porque su pregunta original (http://stackoverflow.com/revisions/3c6789f2-8a6b-4557-bafc-1b8eb4d5f8c4/view-source) indicaba que QUERÍA utilizar DateTime.Parse() pero no indicó por qué no podría usarlo Esto hizo que pareciera una pregunta sin sentido, especialmente porque una simple comprobación habría dejado en claro que el código de cacois era correcto: la cadena "2011-03-21 13:26" no es un problema para DateTime.Parse(). Finalmente, no hizo ninguna mención de ParseExact() en su pregunta original. Esperaste hasta * después de * la respuesta de Mitch para agregar esto en una edición. – anon

+1

Simplemente me encantan esas personas que votan negativamente sin dar ninguna razón en los comentarios. – Hooch

Respuesta

183

DateTime.Parse() intentará averiguar el formato de la fecha indicada, y generalmente hace un buen trabajo. Si usted puede garantizar fechas siempre estará en un formato determinado, puede utilizar 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 por lo general es más seguro utilizar uno de los métodos TryParse en caso de una fecha que no está en el formato esperado)

Asegúrese de marcar Custom Date and Time Format Strings al construir cadenas 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 C# cadenas de formato es String Formatting in C#

+3

Corrección: SIEMPRE es más seguro;) Si llama a un método con una excepción, siempre verifique primero la condición de excepción si es posible. – Gusdor

+2

Diría que es más seguro pasar siempre su cultura. Prefiero tener una excepción que tener "01-02-2013" ser malinterpretado ya sea el 2 de enero o el primero de febrero. – Carra

+1

@Carra: las fechas en formato ISO8601 (es decir, aaaa-mm-dd 'siempre se interpretan de la manera correcta. Es por eso que utilizamos fechas de formato ISO8601 ... –

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

Control hacia fuera este link para otras cadenas de formato!

+1

HH = Horas, ss = segundos .... –

3

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

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

Como te explico más adelante, siempre estarían a favor de los métodos TryParse y TryParseExact. Debido a que son un poco voluminoso de usar, he escrito un método extensión lo que hace el análisis mucho más fácil:

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

A diferencia Parse, etc. ParseExact No lanzar una excepción, y le permite comprobar a través de

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

si la conversión se ha realizado correctamente (en este caso tiene un valor dt se puede acceder a través de dt.Value) o no (en este caso, es null).

que incluso permite utilizar atajos elegantes como el "Elvis" -operator ?., por ejemplo:

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

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

Try it in .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 por defecto a todos los patrones comunes de fecha/hora de la cultura actual del hilo.
Nota que necesitamos la result y dt juntos, porque TryParseExact no permite utilizar DateTime?, que tenemos intención de volver. En C# versión 7 que podría simplificar la función toDate un poco de la 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 le permitiría escribir out DateTime dt en 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 solo consulta dt.HasValue para ver si la conversión fue exitoso o no Como bonificación adicional, TryParseExact permite especificar el número DateTimeStyles estricto para saber exactamente si se ha pasado o no una cadena de fecha/hora adecuada.


N.B. La función sobrecargada le permite pasar una matriz de los formatos válidos utilizados para analizar/convertir las fechas como se muestra here (TryParseExact lo admite directamente), p.

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, con el fin de mantener el código corto, estoy usando solamente la sobrecarga matriz de cadenas de TryParseExact, ya que no funcionaba con un parámetro genérico.

ejemplo Avanzada:
Usted puede utilizar el operador ?? por defecto a un formato de prueba de fallos, 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, el .toDate() sería utilizar formatos de fecha cultura locales comunes, y si todos ellos fracasaron, sería tratar de utilizar el formato "yyyy-MM-dd HH:mm:ss"ISO standard como punto de retorno. 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 decirla razón por la que he escrito esta manera):

estoy prefiriendo TryParseExact en este método de extensión, ya que el manejo de excepción evitar - se puede read in Eric Lippert's article about exceptions por las que debe utilizar TryParse en lugar de Parse, lo cito acerca ese tema: 2)

Esta decisión desafortunado diseño1) [anotación: a dejó el método Parse una excepción] era tan molesto que, por supuesto, el equipo de frameworks implementó TryParse poco después que hace lo correcto.

Lo hace, pero TryParse y TryParseExact ambos son todavía mucho menos cómodo de usar: Te obligan a utilizar una variable no inicializada como un parámetro out que no debe ser anulable y al mismo tiempo va a convertir lo que necesita evalúe el valor de retorno booleano: o tiene que usar una declaración if inmediatamente o tiene que almacenar el valor de retorno en una variable booleana adicional para que pueda hacer la verificación más adelante. Y no puede usar la variable objetivo sin saber si la conversión fue exitosa o no.

En la mayoría de los casos, sólo quiero saber si la conversión se ha realizado correctamente o no (y por supuesto el valor si se ha realizado correctamente), por lo que un objetivo anulable variable de que mantiene toda la información sería deseable y mucho más elegante, porque toda la información se almacena en un solo lugar: es consistente y fácil de usar, y mucho menos propensa a errores.

El método de extensión que he escrito hace exactamente eso (también le muestra qué tipo de código tendrá que escribir cada vez 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 original DateTime.Parse, pero con la capacidad de verificar si la conversión fue exitosa, y sin tirar excepciones.


1) Lo que se quiere decir aquí es que la gestión de excepciones (es decir, un bloque try { ... } catch(Exception ex) { ...}) - lo cual es necesario cuando se está utilizando Analizar porque va a lanzar una excepción si se analiza una cadena no válida - no solo es innecesario en este caso sino que también es molesto y complica tu 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 StackOverflow fellow y trabajaba en Microsoft como principal desarrollador en el equipo compilador de C# para un par de años.

1

También puede utilizar XmlConvert.ToDateString

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

Es bueno para especificar el tipo fecha, como

var anotherParsedDate = DateTime.ParseExact (datestr, "aaaa-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

Cuestiones relacionadas