myCSharp.de - DIE C# und .NET Community (https://www.mycsharp.de/wbb2/index.php)
- Entwicklung (https://www.mycsharp.de/wbb2/board.php?boardid=3)
-- Basistechnologien und allgemeine .NET-Klassen (https://www.mycsharp.de/wbb2/board.php?boardid=23)
--- Validierung DateTime-Formatzeichenfolge (https://www.mycsharp.de/wbb2/thread.php?threadid=121939)


Geschrieben von inflames2k am 11.06.2019 um 16:46:
  Validierung DateTime-Formatzeichenfolge
Hallo,

für eine Anwendung soll dem Benutzer erlaubt werden manuell das Datumsformat anzugeben. Nach Eingabe würden wir dies gern validieren ob es sich um eine gültige Formatzeichenfolge handelt.

Wie wäre hier die beste herangehensweise?

Meine Überlegung war:Ich bin mir nicht sicher, ob das so passt. Gibt es eine bessere / sauberere Lösung?


Geschrieben von T-Virus am 11.06.2019 um 17:27:
 
Ich denke mal mit DateTime.TryParseExact dürftet ihr gut fahren.
Wenn der Bneutzer dann auch einen gültigen Format String angibt, wäre es möglich dies damit zu parsen.
Hier müsstet ihr aber auch prüfen ob ein Format gültig ist.
Dazu müsste der Benutzer auch die Möglichkeit haben sich z.B. die aktuelle Zeit mit seinem Format als Vorschau anzeigen zu lassen.
Und er bräuchte auch eine Legende um zu wissen was wie eingegeben werden kann.

Hier würde ich empfehlen ein Test Projekt anzulegen und per WinForms mal etwas rumspielen um zu schauen was möglich ist.

T-Virus


Geschrieben von inflames2k am 13.06.2019 um 14:14:
 
Da fangen meine Probleme ja schon an. Es handelt sich beim Projekt um einen Converter von Eingangsdaten in das Csv-Format.

Nur für Datumswerte soll eine Formatierungszeichenfolge über die Oberfläche festgelegt werden können. - Die Validierung der Zeichenfolge gestaltet sich aber ziemlich schwierig.

Mein beschriebener Ablauf hat irgendwie merkwürdige auswüchse.

C#-Code (Beispiel mit DateTime.TryParse und eigentlich gültiger Formatzeichenfolge):
            DateTime dt = DateTime.MinValue;

            string dtAsString = dt.ToString("yyyyMMdd");

            if (!DateTime.TryParse(dtAsString, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
                 Console.WriteLine("invalid format");
            else
                Console.WriteLine(dt.ToString());
          // Ergebnis => Invalid Format obwohl gültig

Liefert eine Exception => ungültiges Datumsformat. - Bei DateTime.TryParse kann leider kein Format mitgegeben werden.

Bei TryParseExact wirds aber erst richtig lustig. Vergebe ich dort nämlich ein ungültiges Format kommt das aktuelle Datum als Ergebnis raus und es gibt keinen Fehler / keine Exception.

C#-Code (Beispiel mit DateTime.TryParseExact und ungültiger Formatzeichenfolge):
            DateTime dt = DateTime.MinValue;

            string dtAsString = dt.ToString("ab");

            if (!DateTime.TryParseExact(dtAsString, "ab", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
                 Console.WriteLine("invalid format");
            else
                Console.WriteLine(dt.ToString()); // 13.06.2019 ? wtf???


Geschrieben von Abt am 13.06.2019 um 14:20:
 
Ist in der Dokumentation beantwortet.

Zitat von https://docs.microsoft.com/en-us/dotnet/api/system.datetime.parseexact?redirectedfrom=MSDN&view=netframework-4. 8#System_DateTime_ParseExact_System_String_System_String_System_IFormatProv
ider_:
If format defines a date with no time element and the parse operation succeeds, the resulting DateTime value has a time of midnight (00:00:00). If format defines a time with no date element and the parse operation succeeds, the resulting DateTime value has a date of DateTime.Now.Date.

"yyyyMMdd" ist kein gültiges Dateformat irgendeiner Culture. Der Parser kann auch gar nicht erkennen, was an welcher Stelle zu finden ist.
Rein vom Format wäre yyyyMMdd mit ddMMyyyy identisch. Culture Formate haben immer Bindestriche für Datumswerte und Doppelpunkte von Uhrzeiten.

Du hast ein Custom Format, das man auch so explizit angeben muss.

PS: die korrekte Verwendung von Zeitstempeln in Dateien und Datenbanken ist übrigens DateTimeOffset.

PPS: auch TryParseExact nimmt Formate an.


Geschrieben von inflames2k am 13.06.2019 um 14:38:
 
Zitat von Abt:
PPS: auch TryParseExact nimmt Formate an.

Japp, leider aber jede beliebige und erklärt sie für gültig. - Sofern es bei DateTime.ToString() nicht schon wegbricht.

DateTime.ToString("a") => Exception
DateTime.ToString("ab") => Ergebis: "ab"

Und "ab" kann ich leider auch wieder mit TryParseExact sauber parsen. Wird zwar je nach DateTimeStyles zu 01.01.0000 bzw. 13.06.2019 aber ist ja beides quatsch.

Ich glaube ich habe das Prinzip so langsam verstanden. - Solang die EIngangszeichenfolge dem Format entspricht ist es gültig. Unabhängig davon ob das Format Sinn macht oder nicht. - Eine Validierung wird damit sehr schwierig, da ja eben auch "Stunde: {0:hh}" ein durchaus gültiger String zur Formatierung ist.

Insofern hat sich das soweit erst einmal erledigt. Entweder wir definieren zuvor, was alles zulässig ist oder lassen die Validierung ganz weg.


Geschrieben von Abt am 13.06.2019 um 14:56:
 
Zitat von inflames2k:
Japp, leider aber jede beliebige und erklärt sie für gültig. - Sofern es bei DateTime.ToString() nicht schon wegbricht.

Les die Dokumentation. Da ist erklärt, warum.
.NET verhält sich hier absolut korrekt zur Dokumentation

Zitat von inflames2k:
DateTime.ToString("a") => Exception
DateTime.ToString("ab") => Ergebis: "ab"

Auch das ist vollständig in der Dokumentation aufgeführt.

Zitat von https://docs.microsoft.com/en-us/dotnet/api/system.datetime.tostring?view=netframework-4.8:
The length of format is 1, and it is not one of the format specifier characters defined for DateTimeFormatInfo.

Du solltest Dir die Basics für DateTime Format anschauen - und mal bei Unklarheiten in die Doku schauen.
Bisher gibt es in Deinem Code kein Anhaltspunkt, der nicht auf den ersten beiden Seiten von DateTime Format beantwortet wäre.

Auf Dein Edit:

Zitat:
Entweder wir definieren zuvor, was alles zulässig ist oder lassen die Validierung ganz weg.

Es gibt hier einen Standard: ISO 8601. Das DateTime Format ist dafür "o"

Auch das steht in der Dokumentation:

Zitat von https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#the-round-trip-o-o-format-specifier:
The "O" or "o" standard format specifier represents a custom date and time format string using a pattern that preserves time zone information and emits a result string that complies with ISO 8601.


Geschrieben von inflames2k am 13.06.2019 um 15:12:
 
Hallo Abt,

das ist mir ja alles klar. Ist ja aber auch nicht mein eigentliches Problem. Ich will ja nicht prüfen ob Datum X gütig ist. Das weiß ich an der Stelle.

Ich möchte prüfen ob die eingegebene Formatzeichenfolge gültig ist. - Und das ist sie eigentlich immer sobald sie mindestens 2 Stellig ist.

Insofern sieht die einzig sinnvolle Validierung so aus, dass geprüft wird ob bei DateTime.ToString(format) eine Exception geworfen wird oder nicht.


Geschrieben von Abt am 13.06.2019 um 15:15:
 
Zitat von inflames2k:
Und das ist sie eigentlich immer sobald sie mindestens 2 Stellig ist.

Nope, mind. 2 stellig und ein gültiger Identifier.

Es ist aber nicht möglich mit 100% Gewissheit zu erkennen, welche Zahlenkombination welches Format erfüllt.
19071907 kann yyyyddMM sein, aber auch ddMMyyy (und da gibt es unendlich Kombinationen).

Daher braucht der Parser zwingend beim Datum den (i.d.R.) Bindestrich, um den Aufbau zu erkennen.
Und das geht simpel mit DateTime.TryParse(), das kein Fallback hat.


Geschrieben von inflames2k am 13.06.2019 um 15:22:
 
Hier wiederspreche ich klar, dass die Formatzeichenfolge 2 stellig sein und einen gültigen Identifier besitzen muss. Zumindest was die Implementierung angeht. Denn "[[" ist sowohl bei ToString() als auch bei TryParseExact gültig.

Um noch mal ganz klar zu Erläutern was mein Ziel ist:

Über eine Konfigurationsoberfläche kann eine Formatzeichenfolge eingegeben werden. Meinetwegen "dd.MM.yyyy". Beim Speichern der Konfiguration soll geprüft werden ob "dd.MM.yyyy" eine gültige Formatzeichenfolge ist. Es liegt an der Stelle also kein Datum vor, dass irgendwie formatiert werden soll und keine Zeichenfolge die in ein DateTime umgewandelt werden soll.

Wenn es nur um die Prüfung ginge ob eine Zeichenfolge ein bestimmtes Datumsformat besitzt hätte ich ja keine Probleme. Das ist alles fein beschrieben. Aber ist ja eben nicht mein Problem.


Geschrieben von Abt am 13.06.2019 um 15:37:
 
Zitat von inflames2k:
Zumindest was die Implementierung angeht. Denn "[[" ist sowohl bei ToString() als auch bei TryParseExact gültig.

Nein ist es nicht. TryParse liefert ein False und TryParseExact korrektweise den in der Doku beschriebenen Fallback-Wert.
Und nur weil der Fallback-Fall zutrifft, ist es noch lang nicht gültig - steht auch in der Doku.

ToString liefert Dir keinen Fehler, weil dieser in der Dokumentation genannter Fall eintritt:

Zitat von https://docs.microsoft.com/de-de/dotnet/standard/base-types/custom-date-and-time-format-strings:
Any other character - The character is copied to the result string unchanged.

Les einfach mal die Dokumentation dazu - da steht es exakt drin (kA wie oft man Dir das noch sagen muss).
Wir haben sogar die notwendigen Textstellen freundlicherweise aus der Doku raus kopiert...


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 16.09.2019 01:17