it-swarm.com.de

Zeichenfolge in DateTime in C # analysieren

Ich habe Datum und Uhrzeit in einer Zeichenfolge, die wie folgt formatiert ist:

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

Wie kann ich es nach System.DateTime parsen?

Ich möchte Funktionen wie DateTime.Parse() oder DateTime.ParseExact() verwenden, um das Format des Datums manuell festlegen zu können.

133
Hooch

DateTime.Parse() wird versuchen, das Format des angegebenen Datums herauszufinden, und es macht normalerweise gute Arbeit. Wenn Sie garantieren können, dass Daten immer in einem bestimmten Format vorliegen, können Sie ParseExact() verwenden:

string s = "2011-03-21 13:26";

DateTime dt = 
    DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);

(Beachten Sie jedoch, dass es normalerweise sicherer ist, eine der TryParse-Methoden zu verwenden, falls ein Datum nicht im erwarteten Format vorliegt.)

Achten Sie beim Erstellen der Formatzeichenfolge auf Benutzerdefinierte Datums- und Zeitformatzeichenfolgen , und achten Sie insbesondere auf die Anzahl der Buchstaben und die Groß- und Kleinschreibung (d. H. "MM" und "mm" bedeuten sehr unterschiedliche Dinge).

Eine weitere nützliche Ressource für Zeichenfolgen im C # -Format ist die String-Formatierung in C # .

221
Mitch Wheat

Wie ich später erläutere, würde ich immer die Methoden TryParse und TryParseExact bevorzugen. Da sie etwas sperrig sind, habe ich eine Erweiterungsmethode geschrieben, die das Parsen erheblich vereinfacht:

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

Im Gegensatz zu Parse, ParseExact usw. wird hier keine Ausnahme ausgelöst, und Sie können über prüfen

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

ob die Konvertierung erfolgreich war (in diesem Fall hat dt einen Wert, auf den Sie über dt.Value zugreifen können) oder nicht (in diesem Fall ist es null).

Das erlaubt sogar die Verwendung eleganter Shortcuts wie dem "Elvis" -Operator ?., zum Beispiel:

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

Hier können Sie auch year.HasValue verwenden, um zu überprüfen, ob die Konvertierung erfolgreich war, und wenn sie nicht erfolgreich war, enthält yearnull, andernfalls den Jahresanteil des Datums. Es wird keine Ausnahme ausgelöst, wenn die Konvertierung fehlgeschlagen ist.


Lösung: Die Erweiterungsmethode .ToDate ()

Versuchen Sie es in .NetFiddle

public static class Extensions
{
    // Extension method parsing a date string to a DateTime?
    // dateFmt is optional and allows to pass a parsing pattern array
    // or one or more patterns passed as string parameters
    public static DateTime? ToDate(this string dateTimeStr, params 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"});
      // or simpler: 
      // var dt = "2011-03-21 13:26".ToDate("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();
      }
      // Commented out below because it can be done shorter as shown below.
      // For older C# versions (older than C#7) you need it like that:
      // DateTime? result = null;
      // DateTime dt;
      // if (DateTime.TryParseExact(dateTimeStr, dateFmt,
      //    CultureInfo.InvariantCulture, style, out dt)) result = dt;
      // In C#7 and above, we can simply write:
      var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
                   style, out var dt) ? dt : null as DateTime?;
      return result;
    }
}

Einige Informationen zum Code

Sie fragen sich vielleicht, warum ich InvariantCulture verwendet habe, um TryParseExact aufzurufen: Dies soll die Funktion dazu zwingen, Formatmuster immer auf die gleiche Weise zu behandeln (andernfalls könnte "." In Englisch als Dezimaltrennzeichen interpretiert werden, während es ist ein Gruppentrennzeichen oder ein Datumstrennzeichen in Deutsch). Wir erinnern uns, dass wir die kulturbasierten Format-Strings bereits einige Zeilen zuvor abgefragt haben, damit das hier in Ordnung ist.

Update: .ToDate() (ohne Parameter) verwendet jetzt standardmäßig alle gängigen Datums-/Zeitmuster der aktuellen Kultur des Threads.
Beachten Sie , dass wir result und dt zusammen benötigen, da TryParseExact nicht zulässt um DateTime? zu verwenden, das wir zurückgeben wollen. In C # Version 7 können Sie die Funktion ToDate wie folgt ein wenig vereinfachen:

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

oder, wenn du es noch kürzer magst:

 // in C#7 only: Declaration of result as a "one-liner" ;-)
 var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
              style, out var dt) ? dt : null as DateTime?;

in diesem Fall benötigen Sie die beiden Deklarationen DateTime? result = null; und DateTime dt; überhaupt nicht - Sie können dies in einer Codezeile tun. (Es wäre auch erlaubt, out DateTime dt anstelle von out var dt zu schreiben, wenn Sie das vorziehen).

Ich habe den Code mit dem Schlüsselwort params weiter vereinfacht: Jetzt brauchen Sie die 2 nicht mehrnd überladene Methode nicht mehr.


Anwendungsbeispiel

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

Wie Sie sehen, fragt dieses Beispiel nur dt.HasValue ab, um festzustellen, ob die Konvertierung erfolgreich war oder nicht. Als zusätzlichen Bonus können Sie in TryParseExact streng DateTimeStyles angeben, damit Sie genau wissen, ob eine richtige Datums-/Uhrzeitzeichenfolge übergeben wurde oder nicht.


Weitere Anwendungsbeispiele

Die überladene Funktion ermöglicht es Ihnen, ein Array von gültigen Formaten zu übergeben, die zum Parsen/Konvertieren von Datumsangaben verwendet werden, wie gezeigt hier sowie (TryParseExact unterstützt dies direkt), z.

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);

Wenn Sie nur wenige Vorlagenmuster haben, können Sie auch schreiben:

var dateStr = "2011-03-21 13:26";
var dt = dateStr.ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");

Fortgeschrittene Beispiele

Sie können den Operator ?? verwenden, um standardmäßig ein ausfallsicheres Format zu verwenden, z.

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

In diesem Fall würde die .ToDate() gemeinsame lokale Kultur-Datumsformate verwenden, und wenn alle diese fehlschlagen, würde sie versuchen, das ISO-Standard -Format "yyyy-MM-dd HH:mm:ss" als Fallback zu verwenden. Auf diese Weise können mit der Erweiterungsfunktion verschiedene Fallback-Formate einfach "verkettet" werden.

Sie können sogar die Erweiterung in LINQ verwenden und dies ausprobieren (siehe .NetFiddle oben):

var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
(new[] { "15-01-2019", "15.01.2019" }).Select(s => s.ToDate(patterns)).Dump(); 

dadurch werden die Daten im Array mithilfe der Muster im Handumdrehen konvertiert und in der Konsole abgelegt.


Hintergrundinformationen zu TryParseExact

Zum Schluss noch ein paar Anmerkungen zum Hintergrund (d. H. Der Grund, warum ich das so geschrieben habe):

Ich bevorzuge TryParseExact in dieser Erweiterungsmethode, weil Sie die Ausnahmebehandlung vermeiden - Sie können lesen Sie in Eric Lipperts Artikel über Ausnahmen nach warum Sie TryParse anstelle von Parse verwenden sollten, zitiere ich ihn zu diesem Thema:2)

Diese unglückliche Designentscheidung 1) [Anmerkung: Die Parse-Methode eine Ausnahme auslösen zu lassen] war so ärgerlich, dass natürlich das Framework-Team kurz danach TryParse implementierte , was das Richtige tut.

Dies ist der Fall, aber TryParse und TryParseExact sind beide immer noch weitaus weniger benutzerfreundlich: Sie zwingen Sie, eine nicht initialisierte Variable als out -Parameter zu verwenden, die nicht nullwertfähig sein darf, und zwar während Sie Bei der Konvertierung müssen Sie den booleschen Rückgabewert auswerten. Entweder müssen Sie sofort eine ifAnweisung verwenden, oder Sie müssen den Rückgabewert in einer zusätzlichen booleschen Variablen speichern, damit Sie die Prüfung später durchführen können. Und Sie können die Zielvariable nicht einfach verwenden, ohne zu wissen, ob die Konvertierung erfolgreich war oder nicht.

In den meisten Fällen möchten Sie nur wissen , ob die Konvertierung erfolgreich war oder nicht (und natürlich den Wert, wenn sie erfolgreich war) , also ein Eine nullfähige Zielvariable , die alle Informationen enthält, wäre wünschenswert und viel eleganter - da die gesamte Information nur an einem Ort gespeichert wird: Das ist konsistent und einfach zu verwenden und viel weniger fehleranfällig .

Die von mir geschriebene Erweiterungsmethode macht genau das (sie zeigt Ihnen auch, welche Art von Code Sie jedes Mal schreiben müssten, wenn Sie ihn nicht verwenden würden).

Ich glaube, der Vorteil von .ToDate(strDateFormat) ist, dass es einfach und sauber aussieht - so einfach wie das Original DateTime.Parse sollte - aber mit der Fähigkeit zu überprüfen, ob die Konvertierung erfolgreich war und ohne Ausnahmen.


1) Gemeint ist hier die Ausnahmebehandlung (dh ein try { ... } catch(Exception ex) { ...}-Block) - die erforderlich ist, wenn Sie Parse verwenden, da sie eine Ausnahme auslöst, wenn ein ungültige Zeichenfolge wird analysiert - ist in diesem Fall nicht nur unnötig, sondern auch ärgerlich und kompliziert Ihren Code. TryParse vermeidet dies alles, wie das von mir bereitgestellte Codebeispiel zeigt.


2) Eric Lippert ist ein berühmter StackOverflow-Mitarbeiter und arbeitete einige Jahre bei Microsoft als Hauptentwickler im C # -Compiler-Team.

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

Schauen Sie sich diese link für andere Formatzeichenketten an!

13
Rob

DateTime.Parse () sollte für dieses String-Format gut funktionieren. Referenz:

http://msdn.Microsoft.com/de-de/library/1k1skd40.aspx#Y1240

Gibt es eine FormatException für Sie?

5
cacois

Geben Sie den Wert einer lesbaren Zeichenfolge in einen .NET DateTime-Code mit folgendem Code ein:

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

Sie können auch XmlConvert.ToDateString verwenden

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

Es ist gut, die Art des Datums anzugeben. Der Code lautet:

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

Weitere Informationen zu den verschiedenen Parsing-Optionen http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html

2
Amir Shenouda

Die einfache und unkomplizierte Antwort ->

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.
 * */
2

Versuchen Sie den folgenden Code 

Month = Date = DateTime.Now.Month.ToString();   
Year = DateTime.Now.Year.ToString(); 
ViewBag.Today = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(Int32.Parse(Month)) + Year;
0
Adil Ayoub