Jak sprawdzić poprawność DateTime w C #?

118

Wątpię, że jestem jedynym, który wymyślił to rozwiązanie, ale jeśli masz lepsze, napisz je tutaj. Chcę po prostu zostawić to pytanie tutaj, aby ja i inni mogli je później przeszukać.

Musiałem stwierdzić, czy w polu tekstowym została wpisana prawidłowa data i to jest kod, który wymyśliłem. Uruchamiam to, gdy fokus opuszcza pole tekstowe.

try
{
    DateTime.Parse(startDateTextBox.Text);
}
catch
{
    startDateTextBox.Text = DateTime.Today.ToShortDateString();
}
Matt
źródło
1
<sarcasm> sądząc po odpowiedziach, myślę, że powinienem użyć TryParse </sarcasm> Dzięki za świetne odpowiedzi. Nawet nie myślałem o TryParse
Matt
2
Przykład łatwego do wygooglowania pytania, które gdyby ktoś zadał dzisiaj, byłoby niesprawiedliwie zamknięte z powodu „niewystarczającej ilości badań”.
miłość na żywo
1
tutaj jest łatwy sposób na zrobienie tego bez używania specjalnych funkcji: < stackoverflow.com/questions/14917203/… >
Zameer
2
Praca z DateTimes jest zawsze uciążliwa. Dzięki
Gonzo345

Odpowiedzi:

269
DateTime.TryParse

Uważam, że jest to szybsze i oznacza, że ​​nie musisz używać brzydkich prób / chwytów :)

na przykład

DateTime temp;
if(DateTime.TryParse(startDateTextBox.Text, out temp))
{
  // Yay :)
}
else
{
  // Aww.. :(
}
qui
źródło
2
Popraw mnie, jeśli się mylę, ale czy w C # (w przeciwieństwie do, powiedzmy, JavaScript) gałąź if / else nie wymaga nawiasów klamrowych? Nie zrozum mnie źle, nie próbuję analizować, to fantastyczna odpowiedź i daję jej +1, ponieważ mi to pomogło, ale pomyślałem, że ponieważ nigdy nie wiesz, jacy są nowi przyszli użytkownicy, przeglądając już opublikowane odpowiedzi, to mógł ich zmylić. Oczywiście, jeśli masz problemy z nawiasami klamrowymi w C #, to pytanie byłoby najmniejszym z twoich zmartwień ...
VoidKing,
2
@VoidKing Masz rację co do nawiasów klamrowych, ale jeśli masz tylko 1 instrukcję w tym bloku, nie musisz ich używać. Dotyczy to również niektórych innych języków, ale widzę, jak może to wprowadzać w błąd nowszych programistów.
D.Galvez,
2
@ D.Galvez Przepraszam, że spóźniłem się na imprezę, ale czy najlepiej jest uwzględnić nawiasy, nawet jeśli jest tylko jedno stwierdzenie? To może być tylko sytuacja, w której osobiste preferencje jest najważniejsze - w takim przypadku Uważam tym , żeby być całkiem miły po prostu dla czytelności i spójności.
Nick
2
Niewiele wiedziałem 6 lat temu, że taka debata o nawiasach będzie miała miejsce.
qui
Możliwe jest skrócenie inicjalizacji zmiennej za pomocą if(DateTime.TryParse(startDateTextBox.Text, out var temp)):)
Alexandre Daubricourt
61

Nie używaj wyjątków do kontroli przepływu. Użyj DateTime.TryParse i DateTime.TryParseExact . Osobiście wolę TryParseExact z określonym formatem, ale wydaje mi się, że są chwile, kiedy TryParse jest lepsze. Przykładowe użycie na podstawie oryginalnego kodu:

DateTime value;
if (!DateTime.TryParse(startDateTextBox.Text, out value))
{
    startDateTextox.Text = DateTime.Today.ToShortDateString();
}

Powody preferowania tego podejścia:

  • Jaśniejszy kod (mówi, co chce zrobić)
  • Lepsza wydajność niż łapanie i połykanie wyjątków
  • To nie przechwytuje nieprawidłowo wyjątków - np. OutOfMemoryException, ThreadInterruptedException. (Twój aktualny kod można naprawić, aby tego uniknąć, przechwytując odpowiedni wyjątek, ale użycie TryParse byłoby nadal lepsze).
Jon Skeet
źródło
24

Oto inna odmiana rozwiązania, która zwraca wartość true, jeśli ciąg można przekonwertować na DateTimetyp, lub false w przeciwnym razie.

public static bool IsDateTime(string txtDate)
{
    DateTime tempDate;
    return DateTime.TryParse(txtDate, out tempDate);
}
Brendan Conrad
źródło
3
Witamy w StackOverflow! Proszę spojrzeć na odpowiedzi, które już zostały udzielone, zwłaszcza w przypadku odpowiedzi na pytanie, które ma ponad trzy lata i zostało pomyślnie udzielone. Twoja odpowiedź została już omówiona przez poprzednich respondentów.
Bob Kaufman
3

Problem z używaniem DateTime.TryParsepolega na tym, że nie obsługuje bardzo powszechnego przypadku użycia przy wprowadzaniu danych z datami wprowadzanymi bez separatorów, np 011508.

Oto przykład, jak to wspierać. (To jest z frameworka, który buduję, więc jego podpis jest trochę dziwny, ale podstawowa logika powinna być użyteczna):

    private static readonly Regex ShortDate = new Regex(@"^\d{6}$");
    private static readonly Regex LongDate = new Regex(@"^\d{8}$");

    public object Parse(object value, out string message)
    {
        msg = null;
        string s = value.ToString().Trim();
        if (s.Trim() == "")
        {
            return null;
        }
        else
        {
            if (ShortDate.Match(s).Success)
            {
                s = s.Substring(0, 2) + "/" + s.Substring(2, 2) + "/" + s.Substring(4, 2);
            }
            if (LongDate.Match(s).Success)
            {
                s = s.Substring(0, 2) + "/" + s.Substring(2, 2) + "/" + s.Substring(4, 4);
            }
            DateTime d = DateTime.MinValue;
            if (DateTime.TryParse(s, out d))
            {
                return d;
            }
            else
            {
                message = String.Format("\"{0}\" is not a valid date.", s);
                return null;
            }
        }

    }
Robert Rossney
źródło
Nie martwię się o separatory w moim przypadku, ponieważ używam zamaskowanego pola tekstowego, ale widzę, jak byłoby to przydatne w innych sytuacjach, które mogę napotkać z tą aplikacją.
Matt
Jaki jest powód używania ciągu DateTime bez separatorów?
Siergiej Kovalenko
1
    protected bool ValidateBirthday(String date)
    {
        DateTime Temp;

        if (DateTime.TryParse(date, out Temp) == true &&
      Temp.Hour == 0 &&
      Temp.Minute == 0 &&
      Temp.Second == 0 &&
      Temp.Millisecond == 0 &&
      Temp > DateTime.MinValue)
            return true;
        else
            return false;
    }

// załóżmy, że ciąg wejściowy ma format krótkiej daty.
np. „2013/7/5” zwraca prawdę, a
„2013/2/31” zwraca fałsz.
http://forums.asp.net/t/1250332.aspx/1
// bool booleanValue = ValidateBirthday ("12:55"); zwraca false

Chung_TheWebDeveloper
źródło
1
private void btnEnter_Click(object sender, EventArgs e)
{
    maskedTextBox1.Mask = "00/00/0000";
    maskedTextBox1.ValidatingType = typeof(System.DateTime);
    //if (!IsValidDOB(maskedTextBox1.Text)) 
    if (!ValidateBirthday(maskedTextBox1.Text))
        MessageBox.Show(" Not Valid");
    else
        MessageBox.Show("Valid");
}
// check date format dd/mm/yyyy. but not if year < 1 or > 2013.
public static bool IsValidDOB(string dob)
{ 
    DateTime temp;
    if (DateTime.TryParse(dob, out temp))
        return (true);
    else 
        return (false);
}
// checks date format dd/mm/yyyy and year > 1900!.
protected bool ValidateBirthday(String date)
{
    DateTime Temp;
    if (DateTime.TryParse(date, out Temp) == true &&
        Temp.Year > 1900 &&
       // Temp.Hour == 0 && Temp.Minute == 0 &&
        //Temp.Second == 0 && Temp.Millisecond == 0 &&
        Temp > DateTime.MinValue)
        return (true);
    else
        return (false);
}
Julius
źródło
1

Wszystkie odpowiedzi są całkiem świetne, ale jeśli chcesz użyć jednej funkcji, może to zadziałać.

private bool validateTime(string dateInString)
{
    DateTime temp;
    if (DateTime.TryParse(dateInString, out temp))
    {
       return true;
    }
    return false;
}
Sayed Muhammad Idrees
źródło
1
Co powiesz na zwrócenie wyniku DateTime.TryParse () zamiast bloku „if”? Ponadto, twoje IDE narzekałoby na nigdy nie używane temp, które możesz zadeklarować w wywołaniu funkcji bezpośrednio jako „out DateTime temp”.
Siergiej Kovalenko
0

Możesz także zdefiniować DateTimeformat dla konkretnegoCultureInfo

public static bool IsDateTime(string tempDate)
{
    DateTime fromDateValue;
    var formats = new[] { "MM/dd/yyyy", "dd/MM/yyyy h:mm:ss", "MM/dd/yyyy hh:mm tt", "yyyy'-'MM'-'dd'T'HH':'mm':'ss" };
    return DateTime.TryParseExact(tempDate, formats, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out fromDateValue);
}
Yanga
źródło
-1
protected static bool CheckDate(DateTime date)
{
    if(new DateTime() == date)      
        return false;       
    else        
        return true;        
} 
Hasan_H
źródło
2
Chociaż ten kod może rozwiązać problem, w tym wyjaśnienie, jak i dlaczego to rozwiązuje problem, naprawdę pomogłoby poprawić jakość twojego posta i prawdopodobnie zaowocowałoby większą liczbą pozytywnych głosów. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a nie tylko osoba, która zapyta teraz. Proszę edytować swoje odpowiedzi, aby dodać wyjaśnień i dać wskazówkę co zastosować ograniczenia i założenia.
Brian
Pytanie brzmi, jak zweryfikować wartość, stringktóra może zawierać DateTImewartość lub nie . Sprawdzasz, czy dany DateTimema wartości domyślne (odpowiadające 0001-01-01T00:00:00.0000000). Jak to odpowiada na pytanie?
dbc
-3
DateTime temp;
try
{
    temp = Convert.ToDateTime(grd.Rows[e.RowIndex].Cells["dateg"].Value);
    grd.Rows[e.RowIndex].Cells["dateg"].Value = temp.ToString("yyyy/MM/dd");
}
catch 
{   
    MessageBox.Show("Sorry The date not valid", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop,MessageBoxDefaultButton.Button1,MessageBoxOptions .RightAlign);
    grd.Rows[e.RowIndex].Cells["dateg"].Value = null;
}
Ashraf Khalifah
źródło
1
Musisz sprawdzić ważność try catch. Możesz więc użyć try catch do sprawdzania wszystkich typów zmiennych i tworzenia prawidłowych funkcji globalnych i kontrolowania wszystkiego w projekcie. pozdrawiam ..... Ashraf khalifah
Ashraf Khalifah
-3
DateTime temp;
try
{
    temp = Convert.ToDateTime(date);
    date = temp.ToString("yyyy/MM/dd");
}
catch 
{
    MessageBox.Show("Sorry The date not valid", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop,MessageBoxDefaultButton.Button1,MessageBoxOptions .RightAlign);
    date = null;
}
Ashraf Khalifah
źródło