Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Validierung DateTime-Formatzeichenfolge
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2327

Themenstarter:

Validierung DateTime-Formatzeichenfolge

beantworten | zitieren | melden

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:
  • Formatierung aktuelles Datum mit Formatzeichenfolge
  • DateTime.TryParseExact auf den erhaltenen String
  • Wenn true => gültige Formatzeichenfolge
  • Wenn false => ungültige Formatzeichenfolge


Ich bin mir nicht sicher, ob das so passt. Gibt es eine bessere / sauberere Lösung?
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1768
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

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
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2327

Themenstarter:

beantworten | zitieren | melden

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.


            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.


            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???
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15526
Herkunft: BW

beantworten | zitieren | melden

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_IFormatProvider_
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.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2327

Themenstarter:

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von inflames2k am .
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15526
Herkunft: BW

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2327

Themenstarter:

beantworten | zitieren | melden

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.
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15526
Herkunft: BW

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2327

Themenstarter:

beantworten | zitieren | melden

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.
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15526
Herkunft: BW

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers