Jak sprawdzić datę w Javie [zamknięte]


84

Ciekawe, że najbardziej oczywisty sposób tworzenia Dateobiektów w Javie został uznany za przestarzały i wydaje się być „zastąpiony” przez nie tak oczywisty w użyciu łagodny kalendarz.

Jak sprawdzić, czy data podana jako kombinacja dnia, miesiąca i roku jest prawidłową datą?

Na przykład 2008-02-31 (jak w rrrr-mm-dd) byłby nieprawidłową datą.


Jeśli ktoś ma podobne pytanie, zastanów się, czy potrzebujesz obsługi kalendarza innego niż gregoriański.
MSalters

@JasonC Całkowicie się z tobą zgadzam, połączenie ich wygląda na najlepszy sposób.
acm

Odpowiedzi:


36

Obecnym sposobem jest użycie klasy kalendarza. Ma metodę setLenient , która zweryfikuje datę i zgłoszenie oraz wyjątek, jeśli jest poza zakresem, jak w przykładzie.

Zapomniałem dodać: Jeśli otrzymasz wystąpienie kalendarza i ustawisz czas na podstawie daty, w ten sposób uzyskasz walidację.

Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
    cal.getTime();
}
catch (Exception e) {
  System.out.println("Invalid date");
}

2
nie myśl, że to dokładnie działa tak, jak jest. Calendar.setTime pobiera java.util.Date, więc konwersja ze stringów już się dokonała, zanim otrzymałeś obiekt "yourDate".
spóźnić

33
3 problemy z przykładowym kodem: 1. Po pobraniu instancji Kalendarza należy wywołać cal.setLenient (false). W przeciwnym razie data taka jak 31 lutego 2007 będzie uważana za ważną. 2. Cal.setTime () nie zgłasza wyjątku. Musisz wywołać cal.getTime () po wywołaniu setTime (), które zgłasza wyjątek w nieprawidłowej dacie. 3. Literówka: brak znaku „}” przed haczykiem.
Liron Yahdav

Jest to również wolniejsze niż inne podejścia. Zobacz stackoverflow.com/questions/2149680/…
despot

5
FYI, kłopotliwe stare klasy daty i godziny, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastępowane przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek firmy Oracle .
Basil Bourque,

3
nie sprawdza dat takich jak 31 luty
shikha singh

78

Klucz to df.setLenient (false); . To więcej niż wystarczające w prostych przypadkach. Jeśli szukasz bardziej niezawodnych (wątpię) i / lub alternatywnych bibliotek, takich jak czas joda, spójrz na odpowiedź użytkownika „tardate”

final static String DATE_FORMAT = "dd-MM-yyyy";

public static boolean isDateValid(String date) 
{
        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
}

2
Spróbuj z „09-04-201a”. Stworzy szaloną randkę.
ceklock

@ceklock tak to działa, bez względu na to, czy używasz, setLenientczy nie: SimpleDateFormatzawsze będzie analizować, dopóki wzorzec nie zostanie dopasowany i zignoruje resztę ciągu, w ten sposób otrzymasz 201rok.
Daniel Naber

@ceklock Właśnie zająłem się tym w moim rozwiązaniu . Może to zaoszczędzić komuś minutę lub dwie.
Sufian

1
Włączenie obsługi wyjątków wiąże się z dużym spadkiem wydajności, więc jest to prawdopodobnie zły projekt, JEŚLI spodziewasz się zniekształconych danych wejściowych podczas normalnej pracy (np. Sprawdzanie poprawności danych wejściowych użytkownika). Ale jeśli metoda jest używana do podwójnego sprawdzenia danych wejściowych, które mają być prawidłowe przez cały czas (z wyjątkiem błędów), jest w porządku.
Aaron

2
FYI, strasznie kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek firmy Oracle .
Basil Bourque

48

Jak pokazuje @Maglob, podstawowym podejściem jest przetestowanie konwersji z łańcucha do daty przy użyciu SimpleDateFormat.parse . W ten sposób zostaną wykryte nieprawidłowe kombinacje dnia i miesiąca, takie jak 2008-02-31.

Jednak w praktyce rzadko to wystarcza, ponieważ SimpleDateFormat.parse jest niezwykle liberalny. Istnieją dwa zachowania, które mogą Cię niepokoić:

Nieprawidłowe znaki w ciągu daty Zaskakujące jest, że data 2008-02-2x „przejdzie” jako poprawna data, na przykład w formacie locale = „rrrr-MM-dd”. Nawet jeśli isLenient == false.

Lata: 2, 3 lub 4 cyfry? Możesz także wymusić czterocyfrowe lata zamiast zezwalania na domyślne zachowanie SimpleDateFormat (które będzie interpretować „12-02-31” inaczej w zależności od tego, czy Twój format to „rrrr-MM-dd” czy „rr-MM-dd” )

Ścisłe rozwiązanie z biblioteką standardową

Tak więc pełny test ciągu do daty mógłby wyglądać następująco: połączenie dopasowania wyrażenia regularnego, a następnie wymuszona konwersja daty. Sztuczka z wyrażeniem regularnym polega na tym, aby była przyjazna dla lokalizacji.

  Date parseDate(String maybeDate, String format, boolean lenient) {
    Date date = null;

    // test date string matches format structure using regex
    // - weed out illegal characters and enforce 4-digit year
    // - create the regex based on the local format string
    String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
    reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
    if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {

      // date string matches format structure, 
      // - now test it can be converted to a valid date
      SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
      sdf.applyPattern(format);
      sdf.setLenient(lenient);
      try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
    } 
    return date;
  } 

  // used like this:
  Date date = parseDate( "21/5/2009", "d/M/yyyy", false);

Zwróć uwagę, że wyrażenie regularne zakłada, że ​​ciąg formatu zawiera tylko znaki dnia, miesiąca, roku i separatora. Poza tym format może być w dowolnym formacie regionalnym: „d / MM / rr”, „rrrr-MM-dd” i tak dalej. Ciąg formatu dla bieżącej lokalizacji można uzyskać w następujący sposób:

Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();

Joda Time - lepsza alternatywa?

Słyszałem ostatnio o czasie joda i pomyślałem, że mógłbym porównać. Dwa punkty:

  1. W przeciwieństwie do SimpleDateFormat wydaje się lepsze, jeśli chodzi o ścisłe przestrzeganie nieprawidłowych znaków w ciągu daty
  2. Nie widzę jeszcze sposobu, aby wymusić z nim 4-cyfrowe lata (ale myślę, że w tym celu możesz utworzyć własny DateTimeFormatter )

Jest dość prosty w użyciu:

import org.joda.time.format.*;
import org.joda.time.DateTime;

org.joda.time.DateTime parseDate(String maybeDate, String format) {
  org.joda.time.DateTime date = null;
  try {
    DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
    date =  fmt.parseDateTime(maybeDate);
  } catch (Exception e) { }
  return date;
}

Skończyło się na alternatywie jody i sam sprawdziłem, czy wartość pasuje do długości wzoru ...
Xtreme Biker

Aktualizacja: Straszliwe starych klas starszych ( Date, SimpleDateFormatetc.) są obecnie wypierane przez nowoczesne java.time klas. Podobnie projekt Joda-Time jest w trybie konserwacji i zaleca migrację do klas java.time .
Basil Bourque

39

Możesz użyć SimpleDateFormat

Na przykład coś takiego:

boolean isLegalDate(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setLenient(false);
    return sdf.parse(s, new ParsePosition(0)) != null;
}

2
Jednym z problemów z tym podejściem jest to, że zaakceptuje 0003-0002-001.
despota

1
Inną kwestią jest to, że ustawienie 13 w miesiącu zwraca datę, w której miesiąc to 01 w następnym roku.
8bitjunkie

FYI, strasznie kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek firmy Oracle .
Basil Bourque

30

tl; dr

Użyj trybu ścisłego on java.time.DateTimeFormatterdo analizowania LocalDate. Pułapka na DateTimeParseException.

LocalDate.parse(                   // Represent a date-only value, without time-of-day and without time zone.
    "31/02/2000" ,                 // Input string.
    DateTimeFormatter              // Define a formatting pattern to match your input string.
    .ofPattern ( "dd/MM/uuuu" )
    .withResolverStyle ( ResolverStyle.STRICT )  // Specify leniency in tolerating questionable inputs.
)

Po przeanalizowaniu możesz sprawdzić rozsądną wartość. Na przykład data urodzenia w ciągu ostatnich stu lat.

birthDate.isAfter( LocalDate.now().minusYears( 100 ) )

Unikaj starszych klas daty i godziny

Unikaj używania kłopotliwych starych klas daty i czasu dostarczanych z najwcześniejszymi wersjami Javy. Teraz zastąpione przez klasy java.time .

LocalDate& DateTimeFormatter&ResolverStyle

LocalDateKlasa reprezentuje wartość data-tylko bez time-of-day i bez strefy czasowej.

String input = "31/02/2000";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu" );
try {
    LocalDate ld = LocalDate.parse ( input , f );
    System.out.println ( "ld: " + ld );
} catch ( DateTimeParseException e ) {
    System.out.println ( "ERROR: " + e );
}

java.time.DateTimeFormatterKlasa może być ustawiony do analizowania ciągów z jednym z trzech trybów łagodzenia kar określonych w ResolverStyleenum. Wstawiamy wiersz do powyższego kodu, aby wypróbować każdy z trybów.

f = f.withResolverStyle ( ResolverStyle.LENIENT );

Wyniki:

  • ResolverStyle.LENIENT
    ld: 2000-03-02
  • ResolverStyle.SMART
    ld: 2000-02-29
  • ResolverStyle.STRICT
    BŁĄD: java.time.format.DateTimeParseException: nie można przeanalizować tekstu „31/02/2000”: nieprawidłowa data „31 lutego”

Widzimy, że w ResolverStyle.LENIENTtrybie nieprawidłowa data jest przesuwana do przodu o równoważną liczbę dni. W ResolverStyle.SMARTtrybie (domyślnym) podejmowana jest logiczna decyzja, aby zachować datę w ciągu miesiąca i iść z ostatnim możliwym dniem miesiąca, 29 lutego w roku przestępnym, ponieważ nie ma 31 dnia w tym miesiącu. ResolverStyle.STRICTTryb zgłasza wyjątek twierdząc, że nie ma takiej daty.

Wszystkie trzy są uzasadnione w zależności od problemu biznesowego i zasad. Wygląda na to, że w twoim przypadku chcesz, aby tryb ścisły odrzucał nieprawidłową datę, zamiast ją dostosowywać.


Tabela wszystkich typów dat i godzin w Javie, zarówno nowoczesnych, jak i starszych.


Informacje o java.time

Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date, Calendar, i SimpleDateFormat.

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .

Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani java.sql.*klas.

Skąd wziąć klasy java.time?

Tabela opisująca bibliotekę java.time, która ma być używana z którą wersją Javy lub Androida

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak Interval, YearWeek, YearQuarter, i więcej .


Załóżmy, że projekt jest kompilowany w Javie 8+, wtedy Twoja odpowiedź jest prawidłowa. Używam tych klas również, gdy projekt jest w Javie 8. Ale czasami muszę dotknąć tych brzydkich, starożytnych skryptletów jsp (które nawet nie obsługują java 7). Walidacja dat jest uciążliwa. Dlatego tu jestem. Jednak twoja odpowiedź jest najbardziej poprawnym podejściem ... Wniosek: mam przerąbane.
KarelG

@KarelG Przeczytaj ponownie ten przedostatni akapit dotyczący przeniesienia wstecz do Java 6 i Java 7 . Nie zweryfikowałem tego zachowania w back-porcie, ale sugeruję spróbować.
Basil Bourque

13

java.time

Dzięki interfejsowi API daty i godziny ( klasy java.time ) wbudowanemu w Javę 8 i nowszych wersjach można używać tej LocalDateklasy.

public static boolean isDateValid(int year, int month, int day) {
    boolean dateIsValid = true;
    try {
        LocalDate.of(year, month, day);
    } catch (DateTimeException e) {
        dateIsValid = false;
    }
    return dateIsValid;
}

2
Domyślnie ten kod używa, ResolverStyle.SMARTktóre dostosowuje wynikową wartość do prawidłowej daty, zamiast zgłaszać wyjątek. Więc ten kod nie osiągnie celu pytania. Zobacz moją odpowiedź na przykład i rozwiązanie przy użyciu ResolverStyle.STRICT.
Basil Bourque

7

Alternatywnym rozwiązaniem ścisłym wykorzystującym bibliotekę standardową jest wykonanie następujących czynności:

1) Utwórz ścisły SimpleDateFormat używając swojego wzorca

2) Spróbuj przeanalizować wartość wprowadzoną przez użytkownika przy użyciu obiektu formatu

3) Jeśli się powiedzie, sformatuj ponownie datę wynikającą z (2), używając tego samego formatu daty (z (1))

4) Porównaj ponownie sformatowaną datę z oryginalną wartością wprowadzoną przez użytkownika. Jeśli są równe, to wprowadzona wartość ściśle pasuje do twojego wzorca.

W ten sposób nie musisz tworzyć skomplikowanych wyrażeń regularnych - w moim przypadku musiałem obsługiwać całą składnię wzorców SimpleDateFormat, zamiast ograniczać się do niektórych typów, takich jak dni, miesiące i lata.


To zdecydowanie najlepsza droga, zobacz także przykładowy kod na dreamincode.net/forums/topic/ ...
Victor Ionescu,

7

Opierając się na odpowiedzi Aravinda, aby naprawić problem wskazany przez ceklocka w jego komentarzu , dodałem metodę sprawdzania, dateStringczy nie zawiera żadnych nieprawidłowych znaków.

Oto jak to robię:

private boolean isDateCorrect(String dateString) {
    try {
        Date date = mDateFormatter.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return matchesOurDatePattern(dateString);    //added my method
    }
    catch (ParseException e) {
        return false;
    }
}

/**
 * This will check if the provided string matches our date format
 * @param dateString
 * @return true if the passed string matches format 2014-1-15 (YYYY-MM-dd)
 */
private boolean matchesDatePattern(String dateString) {
    return dateString.matches("^\\d+\\-\\d+\\-\\d+");
}

5

Myślę, że najprościej jest po prostu przekonwertować ciąg na obiekt daty i przekonwertować go z powrotem na ciąg. Podany ciąg daty jest prawidłowy, jeśli oba ciągi nadal są zgodne.

public boolean isDateValid(String dateString, String pattern)
{   
    try
    {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        if (sdf.format(sdf.parse(dateString)).equals(dateString))
            return true;
    }
    catch (ParseException pe) {}

    return false;
}

4

Proponuję użyć org.apache.commons.validator.GenericValidatorklasy z Apache.

GenericValidator.isDate(String value, String datePattern, boolean strict);

Uwaga: ścisłe - określa, czy ma być dokładne dopasowanie do wzoru daty.


2

Zakładając, że oba są ciągami znaków (w przeciwnym razie byłyby już prawidłowymi datami), oto jeden sposób:

package cruft;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateValidator
{
    private static final DateFormat DEFAULT_FORMATTER;

    static
    {
        DEFAULT_FORMATTER = new SimpleDateFormat("dd-MM-yyyy");
        DEFAULT_FORMATTER.setLenient(false);
    }

    public static void main(String[] args)
    {
        for (String dateString : args)
        {
            try
            {
                System.out.println("arg: " + dateString + " date: " + convertDateString(dateString));
            }
            catch (ParseException e)
            {
                System.out.println("could not parse " + dateString);
            }
        }
    }

    public static Date convertDateString(String dateString) throws ParseException
    {
        return DEFAULT_FORMATTER.parse(dateString);
    }
}

Oto wynik, który otrzymuję:

java cruft.DateValidator 32-11-2010 31-02-2010 04-01-2011
could not parse 32-11-2010
could not parse 31-02-2010
arg: 04-01-2011 date: Tue Jan 04 00:00:00 EST 2011

Process finished with exit code 0

Jak widać, dobrze radzi sobie w obu przypadkach.


@duffymo druga instrukcja nie rzuca wyjątku ... :(
maximus

@Pangea Niezupełnie .... spróbuj tej daty "31-01-2010" to nie zgłosi żadnego wyjątku .......... Po prostu uruchom to na swoim komputerze i zobacz ... nie praca ....
sasidhar

Mój błąd. Usunąłem swój komentarz. Ale drugie stwierdzenie jest dla mnie wyjątkiem. @duffymo - którego JVM używasz?
Aravind Yarram

@ Pangea używam jdk1.6.0_23 Próbowałem tego nawet z tym joda-time.sourceforge.net, ale nawet to nie działało ....
sasidhar

1
Rozumiem, że to tylko prosty test, ale aby upewnić się, że ludzie nie kopiują tego dosłownie, chcę powiedzieć, że „DateFormat” NIE JEST BEZPIECZNY. Dlatego zawsze twórz ją jako zmienną lokalną lub używaj jej z wątkiem lokalnym.
Aravind Yarram

2

To działa świetnie dla mnie. Podejście zasugerowane powyżej przez Bena.

private static boolean isDateValid(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    try {
        Date d = asDate(s);
        if (sdf.format(d).equals(s)) {
            return true;
        } else {
            return false;
        }
    } catch (ParseException e) {
        return false;
    }
}

1
nie można rozpoznać asDate. Co to jest?
Susheel

2

wygląda na to, że SimpleDateFormat nie sprawdza ściśle wzorca nawet po ustawieniu setLenient (false); jest na nim stosowana metoda, więc użyłem poniższej metody do sprawdzenia, czy wprowadzona data jest poprawną datą, czy nie zgodnie z podanym wzorcem.

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public boolean isValidFormat(String dateString, String pattern) {
    boolean valid = true;
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    try {
        formatter.parse(dateString);
    } catch (DateTimeParseException e) {
        valid = false;
    }
    return valid;
}

1

Dwa komentarze na temat użycia SimpleDateFormat.

powinien być zadeklarowany jako instancja statyczna, jeśli zadeklarowany jako dostęp statyczny, powinien być zsynchronizowany, ponieważ nie jest bezpieczny wątkowo

IME, który jest lepszy niż tworzenie instancji dla każdej analizy daty.


słuszna uwaga Tom. Zaktualizowałem podany przykład, aby zapewnić konsekwentne używanie instancji statycznej.
spóźnić się

Używanie zsynchronizowanej funkcji może nie być skalowane w przypadku niektórych projektów. Poleciłbym umieszczenie SimpleDateFormat w zmiennej ThreadLocal zamiast zmiennej statycznej, do której można uzyskać dostęp za pośrednictwem zsynchronizowanej funkcji.
user327961

0

Powyższe metody parsowania daty są fajne, właśnie dodałem nowe sprawdzanie w istniejących metodach, które dwukrotnie sprawdzają przekonwertowaną datę z oryginalną datą za pomocą formatera, więc działa to dla prawie każdego przypadku, jak zweryfikowałem. np. 02/29/2013 to nieprawidłowa data. Podana funkcja analizuje datę zgodnie z aktualnymi akceptowalnymi formatami daty. Zwraca prawdę, jeśli data nie została pomyślnie przeanalizowana.

 public final boolean validateDateFormat(final String date) {
        String[] formatStrings = {"MM/dd/yyyy"};
        boolean isInvalidFormat = false;
        Date dateObj;
        for (String formatString : formatStrings) {
            try {
                SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateInstance();
                sdf.applyPattern(formatString);
                sdf.setLenient(false);
                dateObj = sdf.parse(date);
                System.out.println(dateObj);
                if (date.equals(sdf.format(dateObj))) {
                    isInvalidFormat = false;
                    break;
                }
            } catch (ParseException e) {
                isInvalidFormat = true;
            }
        }
        return isInvalidFormat;
    }

0

Oto, co zrobiłem dla środowiska Node bez zewnętrznych bibliotek:

Date.prototype.yyyymmdd = function() {
   var yyyy = this.getFullYear().toString();
   var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
   var dd  = this.getDate().toString();
   return zeroPad([yyyy, mm, dd].join('-'));  
};

function zeroPad(date_string) {
   var dt = date_string.split('-');
   return dt[0] + '-' + (dt[1][1]?dt[1]:"0"+dt[1][0]) + '-' + (dt[2][1]?dt[2]:"0"+dt[2][0]);
}

function isDateCorrect(in_string) {
   if (!matchesDatePattern) return false;
   in_string = zeroPad(in_string);
   try {
      var idate = new Date(in_string);
      var out_string = idate.yyyymmdd();
      return in_string == out_string;
   } catch(err) {
      return false;
   }

   function matchesDatePattern(date_string) {
      var dateFormat = /[0-9]+-[0-9]+-[0-9]+/;
      return dateFormat.test(date_string); 
   }
}

A oto jak z niego korzystać:

isDateCorrect('2014-02-23')
true

0
// to return valid days of month, according to month and year
int returnDaysofMonth(int month, int year) {
    int daysInMonth;
    boolean leapYear;
    leapYear = checkLeap(year);
    if (month == 4 || month == 6 || month == 9 || month == 11)
        daysInMonth = 30;
    else if (month == 2)
        daysInMonth = (leapYear) ? 29 : 28;
    else
        daysInMonth = 31;
    return daysInMonth;
}

// to check a year is leap or not
private boolean checkLeap(int year) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}

0

Tutaj chciałbym sprawdzić format daty:

 public static boolean checkFormat(String dateTimeString) {
    return dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}") || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}")
            || dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}") || dateTimeString
            .matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z") ||
            dateTimeString.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}Z");
}

Mamy teraz nowoczesne klasy java.time do tej pracy. Pisanie skomplikowanych wyrażeń regularnych prawdopodobnie nie jest najlepszym sposobem wykorzystania czasu. Zobacz jedną linijkę w mojej odpowiedzi .
Basil Bourque

0
        public static String detectDateFormat(String inputDate, String requiredFormat) {
        String tempDate = inputDate.replace("/", "").replace("-", "").replace(" ", "");
        String dateFormat;

        if (tempDate.matches("([0-12]{2})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMddyyyy";
        } else if (tempDate.matches("([0-31]{2})([0-12]{2})([0-9]{4})")) {
            dateFormat = "ddMMyyyy";
        } else if (tempDate.matches("([0-9]{4})([0-12]{2})([0-31]{2})")) {
            dateFormat = "yyyyMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([0-12]{2})")) {
            dateFormat = "yyyyddMM";
        } else if (tempDate.matches("([0-31]{2})([a-z]{3})([0-9]{4})")) {
            dateFormat = "ddMMMyyyy";
        } else if (tempDate.matches("([a-z]{3})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMMddyyyy";
        } else if (tempDate.matches("([0-9]{4})([a-z]{3})([0-31]{2})")) {
            dateFormat = "yyyyMMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([a-z]{3})")) {
            dateFormat = "yyyyddMMM";
        } else {
            return "Pattern Not Added";
//add your required regex
        }
        try {
            String formattedDate = new SimpleDateFormat(requiredFormat, Locale.ENGLISH).format(new SimpleDateFormat(dateFormat).parse(tempDate));

            return formattedDate;
        } catch (Exception e) {
            //
            return "";
        }

    }

0

Dzięki „starszemu” formatowi daty możemy sformatować wynik i porównać go ze źródłem.

    public boolean isValidFormat(String source, String pattern) {
    SimpleDateFormat sd = new SimpleDateFormat(pattern);
    sd.setLenient(false);
    try {
        Date date = sd.parse(source);
        return date != null && sd.format(date).equals(source);
    } catch (Exception e) {
        return false;
    }
}

Ten plik wykonywalny mówi „false” do źródła = 01.01.04 ze wzorcem „01 .01.2004”


-1

setLenient to false, jeśli lubisz ścisłą weryfikację

public boolean isThisDateValid(String dateToValidate, String dateFromat){

    if(dateToValidate == null){
        return false;
    }

    SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
    sdf.setLenient(false);

    try {

        //if not valid, it will throw ParseException
        Date date = sdf.parse(dateToValidate);
        System.out.println(date);

    } catch (ParseException e) {

        e.printStackTrace();
        return false;
    }

    return true;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.