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.
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 # .
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 year
null
, 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 if
Anweisung 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.
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!
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?
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);
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
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.
* */
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;