Analyser la chaîne à DateTime en C #

J’ai la date et l’heure dans une chaîne formatée comme celle-ci:

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

Comment puis-je l’parsingr sur System.DateTime ?

Je veux utiliser des fonctions comme DateTime.Parse() ou DateTime.ParseExact() si possible, pour pouvoir spécifier le format de la date manuellement.

DateTime.Parse() essaiera de déterminer le format de la date donnée, et il fait généralement du bon travail. Si vous pouvez garantir que les dates seront toujours dans un format donné, vous pouvez utiliser ParseExact() :

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

(Mais notez qu’il est généralement plus prudent d’utiliser l’une des méthodes TryParse au cas où une date n’est pas au format attendu)

Assurez-vous de vérifier les chaînes de format de date et d’heure personnalisées lors de la construction de la chaîne de format, faites particulièrement attention au nombre de lettres et à la casse (par exemple, “MM” et “mm” signifient des choses très différentes).

Une autre ressource utile pour les chaînes de format C # est le formatage de chaînes en C #

Comme je l’explique plus tard, je privilégierais toujours les méthodes TryParse et TryParseExact . Comme ils sont un peu encombrants à utiliser, j’ai écrit une méthode d’extension qui facilite l’parsing:

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

Contrairement à Parse , ParseExact etc., il ne lance pas d’exception et vous permet de vérifier via

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

si la conversion a réussi (dans ce cas, dt a une valeur accessible via dt.Value ) ou non (dans ce cas, elle est null ).

Cela permet même d’utiliser des raccourcis élégants comme le “Elvis” -operator ?. , par exemple:

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

Ici, vous pouvez également utiliser year.HasValue pour vérifier si la conversion a réussi et si elle n’a pas abouti, year contiendra null , sinon la partie année de la date. Il n’y a pas d’exception levée si la conversion a échoué.

Essayez-le dans .NetFiddle

 public static class Extensions { public static DateTime? toDate(this ssortingng dateTimeStr, ssortingng[] dateFmt) { // example: var dt = "2011-03-21 13:26".toDate(new ssortingng[]{"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 ssortingng dateTimeStr, ssortingng 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 ssortingng array param ssortingng[] dateFmtArr = dateFmt == null ? null : new ssortingng[] { dateFmt }; return toDate(dateTimeStr, dateFmtArr); } } 

Update: .toDate() (sans parameters) .toDate() désormais par défaut tous les modèles de date / heure courants de la culture actuelle du thread.
Notez que nous avons besoin du result et de dt ensemble, car TryParseExact ne permet pas d’utiliser DateTime? , que nous avons l’intention de retourner. Dans C # Version 7, vous pouvez simplifier un peu la fonction toDate comme suit:

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

(Il serait également autorisé à écrire out DateTime dt au lieu de out var dt .)

Exemple:

 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!"); } 

Comme vous pouvez le voir, cet exemple interroge uniquement dt.HasValue pour voir si la conversion a réussi ou non. Comme bonus supplémentaire, TryParseExact permet de spécifier des DateTimeStyles ssortingctes afin que vous sachiez exactement si une chaîne de date / heure correcte a été passée ou non.


NB La fonction surchargée vous permet de passer un tableau de formats valides utilisés pour parsingr / convertir les dates, comme indiqué ici ( TryParseExact supporte directement cela), par exemple

 ssortingng[] 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); 

Cependant, pour que le code rest court, j’utilise uniquement la surcharge du tableau de chaînes de TryParseExact, car celle-ci ne fonctionnait pas avec un paramètre générique.

Exemple avancé:
Vous pouvez utiliser le ?? opérateur par défaut à un format de sécurité, par exemple

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

Dans ce cas, le .toDate() utiliserait les formats de date de culture locaux communs, et si tous ces .toDate() échouaient, il essaierait d’utiliser le format standard ISO "yyyy-MM-dd HH:mm:ss" comme solution de secours. De cette façon, la fonction d’extension permet de “chaîner” différents formats de repli facilement.


Enfin, voici quelques commentaires sur l’arrière-plan (c’est la raison pour laquelle je l’ai écrit de cette façon):

Je préfère TryParseExact dans cette méthode d’extension, car vous évitez la gestion des exceptions – vous pouvez lire l’article d’Eric Lippert sur les exceptions pour lesquelles vous devriez utiliser TryParse plutôt que Parse, je le cite à ce sujet: 2)

Cette décision de conception malheureuse 1) [annotation: laisser la méthode Parse lancer une exception] était tellement frustrante que l’équipe de frameworks a bien sûr mis en place TryParse peu après, ce qui est la bonne chose.

Cela fonctionne, mais TryParse et TryParseExact sont tous les deux beaucoup moins confortables à utiliser: ils vous obligent à utiliser une variable non initialisée comme paramètre de out qui ne doit pas être nullable et que vous devez évaluer la valeur de retour booléenne lors de la conversion – soit vous devez utiliser une instruction if immédiatement ou vous devez stocker la valeur de retour dans une variable booléenne supplémentaire pour pouvoir effectuer la vérification ultérieurement. Et vous ne pouvez pas simplement utiliser la variable cible sans savoir si la conversion a réussi ou non.

Dans la plupart des cas, vous voulez simplement savoir si la conversion a été réussie ou non (et bien sûr la valeur si elle a réussi) , une variable cible nullable qui conserve toutes les informations serait souhaitable et beaucoup plus élégante, car toutes les informations sont juste stocké dans un endroit: c’est cohérent et facile à utiliser, et beaucoup moins enclin aux erreurs.

La méthode d’extension que j’ai écrite fait exactement cela (cela vous montre également quel type de code vous devriez écrire à chaque fois si vous ne l’utilisez pas).

Je pense que l’avantage de .toDate(strDateFormat) est qu’il semble simple et propre – aussi simple que le DateTime.Parse original était supposé être – mais avec la possibilité de vérifier si la conversion était réussie et sans lancer d’exceptions.


1) Ce que cela signifie ici est cette gestion des exceptions (c.-à-d. Un bloc try { ... } catch(Exception ex) { ...} ) – ce qui est nécessaire lorsque vous utilisez Parse car ssortingng est analysé – est non seulement inutile dans ce cas, mais aussi ennuyeux et compliquant votre code. TryParse évite tout cela comme le montre l’exemple de code que j’ai fourni.


2) Eric Lippert est un membre célèbre de StackOverflow et a travaillé pendant quelques années chez Microsoft en tant que développeur principal de l’équipe de compilation C #.

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

Consultez ce lien pour d’autres chaînes de format!

DateTime.Parse () devrait fonctionner correctement pour ce format de chaîne. Référence:

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

Jette-t-il une exception FormatException pour vous?

Mettez la valeur d’une chaîne lisible par l’homme dans un .NET DateTime avec le code suivant:

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

Vous pouvez également utiliser XmlConvert.ToDateSsortingng

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

Il est bon de spécifier le type de date, le code est le suivant:

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

Plus de détails sur les différentes options d’parsing http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html

La réponse simple et directe ->

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