Sprawdź, czy ciąg znaków jest wartością daty

207

Jaki jest łatwy sposób sprawdzenia, czy wartość jest prawidłową datą, dozwolony jest dowolny znany format daty.

Na przykład mam wartości 10-11-2009, 10/11/2009, 2009-11-10T07:00:00+0000które powinny być uznane za wartości dat, a wartości 200, 10, 350, które nie powinny być uznawane jako wartość daty. Jaki jest najprostszy sposób, aby to sprawdzić, jeśli jest to w ogóle możliwe? Ponieważ znaczniki czasu byłyby również dozwolone.

Thizzer
źródło

Odpowiedzi:

41

Czy Date.parse()wystarczy?

Zobacz odpowiednią stronę dokumentacji MDN .

Asmor
źródło
24
Zachowaj ostrożność, ponieważ w lutym nadal będzie zwracany zwrot z nieprawidłowych dat, na przykład:
31.02.2013
58
Kolejny powód do ostrożności - liczby parsowane są jako daty. Date.parse("4.3")jest 986270400000.
Mogsdad
Próbowałem skrzypce w obu powyższych przypadkach „przestroga”: console.log (Date.parse („2013-02-31”)); console.log (Date.parse („4.3”)); i w obu przypadkach (w firefoxie) zwrócił NaN, więc dla mnie Date.parse wydaje się OK (i tak prewaliduję dla myślników i poprawnej długości przed analizą).
Cloudranger
55
Przepraszamy @Asmor, to nie jest poprawna odpowiedź. Date.parse parsuje dowolny ciąg z liczbą, w której jest umieszczony.
jwerre
11
Date.parse („My Name 8”) nadchodzi jako 99662040000, co jest błędne. Użyłem tego i teraz cierpię.
Rohith,
250

Aktualizacja 2015

To stare pytanie, ale inne nowe pytania, takie jak:

zostaną zamknięte jako duplikaty tego, więc myślę, że ważne jest, aby tutaj dodać kilka świeżych informacji. Piszę to, ponieważ przestraszyłem się, myśląc, że ludzie faktycznie kopiują i wklejają część opublikowanego tutaj kodu i używają go w produkcji.

Większość odpowiedzi tutaj albo używa skomplikowanych wyrażeń regularnych, które pasują tylko do niektórych bardzo specyficznych formatów i faktycznie robią to niepoprawnie (np. Dopasowują 32 stycznia, ale nie pasują do faktycznej daty ISO zgodnie z reklamą - zobacz demo ) lub próbują przekazać cokolwiek do Datekonstruktora i życzę wszystkiego najlepszego.

Korzystanie z momentu

Jak wyjaśniłem w tej odpowiedzi obecnie dostępna jest do tego biblioteka: Moment.js

Jest to biblioteka do analizowania, sprawdzania poprawności, manipulowania i wyświetlania dat w JavaScript, która ma znacznie bogatszy interfejs API niż standardowe funkcje obsługi dat JavaScript.

Jest zminimalizowany / gzipowany do 12kB i działa w Node.js i innych miejscach:

bower install moment --save # bower
npm install moment --save   # npm
Install-Package Moment.js   # NuGet
spm install moment --save   # spm
meteor add momentjs:moment  # meteor

Korzystając z aplikacji Moment, możesz bardzo precyzyjnie określić poprawne daty. Czasami bardzo ważne jest dodanie wskazówek na temat oczekiwanego formatu. Na przykład data taka jak 22.06.2015 wygląda na prawidłową datę, chyba że użyjesz formatu DD / MM / RRRR, w którym to przypadku datę tę należy odrzucić jako niepoprawną. Istnieje kilka sposobów, dzięki którym możesz powiedzieć Momentowi, jakiego formatu się spodziewasz, na przykład:

moment("06/22/2015", "MM/DD/YYYY", true).isValid(); // true
moment("06/22/2015", "DD/MM/YYYY", true).isValid(); // false

trueArgument jest nie tak Moment nie będzie próbował analizować wejście jeśli nie dokładnie zgodne z jednym z formatów określonych (powinien to być domyślne zachowanie moim zdaniem).

Możesz użyć formatu dostarczonego wewnętrznie:

moment("2015-06-22T13:17:21+0000", moment.ISO_8601, true).isValid(); // true

I możesz użyć wielu formatów jako tablicy:

var formats = [
    moment.ISO_8601,
    "MM/DD/YYYY  :)  HH*mm*ss"
];
moment("2015-06-22T13:17:21+0000", formats, true).isValid(); // true
moment("06/22/2015  :)  13*17*21", formats, true).isValid(); // true
moment("06/22/2015  :(  13*17*21", formats, true).isValid(); // false

Zobacz: DEMO .

Inne biblioteki

Jeśli nie chcesz używać Moment.js, istnieją również inne biblioteki:

Aktualizacja 2016

Stworzyłem moduł immoment , który jest jak (podzbiorem) Moment, ale bez niespodzianek spowodowanych mutacją istniejących obiektów (zobacz dokumentację więcej informacji ).

Aktualizacja 2018

Dzisiaj polecam korzystanie z Luxonu do manipulacji datą / czasem zamiast Moment, co (w przeciwieństwie do Moment) sprawia, że ​​wszystkie obiekty są niezmienne, więc nie ma żadnych nieprzyjemnych niespodzianek związanych z ukrytą mutacją dat.

Więcej informacji

Zobacz też:

Seria artykułów Roba Gravelle'a na temat bibliotek parsujących daty JavaScript:

Dolna linia

Oczywiście każdy może próbować wyważać otwartych drzwi, napisać wyrażenie regularne (ale proszę faktycznie czytać ISO 8601 i RFC 3339, zanim to zrobić) lub wywołanie buit w konstruktorów z losowych danych do wiadomości Błąd składni jak 'Invalid Date'(czy jesteś pewien, że ta wiadomość jest dokładnie tak samo na wszystkich platformach? We wszystkich lokalizacjach? W przyszłości?) lub możesz użyć przetestowanego rozwiązania i poświęcić swój czas na jego ulepszenie, a nie na nowo. Wszystkie wymienione tu biblioteki są wolnym oprogramowaniem typu open source.

rsp
źródło
4
jak dokładnie należy tego używać? moment("whatever 123").isValid()zwraca true.
krivar
4
@krivar Najlepiej używać tego w ten sposób: moment("06/22/2015", "DD/MM/YYYY", true).isValid();z jawnie podanym formatem oczekiwanej daty i argumentem trueoznaczającym ścisłe sprawdzenie. Zaktualizowałem swoją odpowiedź, dodając więcej informacji i lepsze przykłady.
rsp
2
To samo, ale sprawdzam poprawność danych wprowadzanych przez użytkownika i nie znam oczekiwanego formatu daty ...
Jan Van der Haegen
3
@JanVanderHaegen Jeśli można założyć, że 3/4/5 jest prawidłową datą, podobnie jak 1 kwietnia 2015 r., Zaleciłbym dodanie tych formatów (i potencjalnie znacznie więcej) do jawnej listy obsługiwanych formatów. Zauważ, że 3/4/5, o którym wspomniałeś, jest dwuznaczny bez wyraźnego formatu.
rsp
3
To może być najlepsza i najlepiej utrzymana odpowiedź, jaką widziałem w SO
Phil3992
63

W ten sposób rozwiązałem ten problem w aplikacji, nad którą teraz pracuję:

zaktualizowane na podstawie opinii krillgar:

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}
Neil Girardi
źródło
5
Musiałem zwrócić (nowa data (data)). ToString ()! == „Nieprawidłowa data” dla węzła. Zauważ też, że? prawda: fałsz jest zbędny. wystarczy samo zwrócenie wyrażenia.
domenukk
W IE8 new Date(date)nie podaje „niepoprawnej daty”.
krillgar
13
To nie jest dobra odpowiedź. new Date(date) !== "Invalid Date"będzie zawsze powrócić prawda od lewa wyrażenie zwróci obiekt Date z TIMEVALUE z NaN , która nigdy nie może być ===na sznurku. Używanie ==„działa” z powodu konwersji typu. Ale ponieważ parsowanie ciągów daty jest nadal w dużej mierze zależne od implementacji, polegając na tym, że parsujemy losowe formaty, które są poważnie wadliwe.
RobG
4
nowa data („469”) powoduje, że w wtorek 01 469 00:00:00 GMT + 0200 (EET)
Dan Ochiana
3
Jest to podobne do fałszywie przyjętej poprawnej odpowiedzi. isDate('Mac OS X 10.14.2')zwraca tutaj wartość true.
BradStell,
24

new Date(date) === 'Invalid Date'działa tylko w Firefox i Chrome. IE8 (ten, który mam na moim komputerze do celów testowych) daje NaN.

Jak stwierdzono w przyjętej odpowiedzi, Date.parse(date)zadziała również dla liczb. Aby obejść ten problem, możesz również sprawdzić, czy nie jest to liczba (jeśli to coś chcesz potwierdzić).

var parsedDate = Date.parse(date);

// You want to check again for !isNaN(parsedDate) here because Dates can be converted
// to numbers, but a failed Date parse will not.
if (isNaN(date) && !isNaN(parsedDate)) {
    /* do your work */
}
krillgar
źródło
2
Zdaję sobie sprawę, że to kilka lat później, ale isNanto nie jest funkcja; niepoprawna wielkość liter w pierwszej instancji.
Tim Lewis,
Nie działa. Jeśli datetak Foostreet 1, twój stan jest oceniany jako prawdziwy.
Fabian Picone
9

Co powiesz na coś takiego? Sprawdza, czy jest to obiekt Date, czy ciąg daty:

function isDate(value) {
    var dateFormat;
    if (toString.call(value) === '[object Date]') {
        return true;
    }
    if (typeof value.replace === 'function') {
        value.replace(/^\s+|\s+$/gm, '');
    }
    dateFormat = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
    return dateFormat.test(value);
}

Powinienem wspomnieć, że to nie sprawdza ciągów sformatowanych w ISO, ale przy odrobinie pracy w RegExp powinieneś być dobry.

Jwerre
źródło
7

Żadna z odpowiedzi tutaj nie dotyczy sprawdzania, czy data jest nieprawidłowa, na przykład 31 lutego. Ta funkcja rozwiązuje ten problem, sprawdzając, czy zwrócony miesiąc jest równoważny z oryginalnym miesiącem i upewniając się, że podano prawidłowy rok.

//expected input dd/mm/yyyy or dd.mm.yyyy or dd-mm-yyyy
function isValidDate(s) {
  var separators = ['\\.', '\\-', '\\/'];
  var bits = s.split(new RegExp(separators.join('|'), 'g'));
  var d = new Date(bits[2], bits[1] - 1, bits[0]);
  return d.getFullYear() == bits[2] && d.getMonth() + 1 == bits[1];
} 
Tak, mówi Przywróć Monikę
źródło
Ponieważ pytanie nie polega na sprawdzeniu, czy łańcuch jest „prawidłową” datą, a jedynie na sprawdzeniu, czy łańcuch reprezentuje format daty.
Thizzer
@Thizzer dobry punkt. Nie miałbym nic przeciwko naprawianiu, ale po ponownym przeczytaniu twojego pytania jestem zdumiony, ponieważ mówisz, że 10 nie powinno sprawdzać poprawności, ale że znaczniki czasu powinny być dozwolone.
porządku, mówi Przywróć Monikę
xD nawet tego nie zauważył, pytanie z moich wcześniejszych dni z datą / znacznikami czasu. Spróbuję edytować pytanie później dzisiaj.
Thizzer
dlaczego miesiąc-1, a następnie miesiąc + 1?
Kapil Raghuwanshi
@KapilRaghuwanshi daty javascript używają miesiąca opartego na zerach, więc musisz odjąć 1, aby utworzyć prawidłową datę i dodać 1, aby sprawdzić, czy jest ona odpowiednikiem oryginalnego miesiąca
mówi ok. Przywróć Monikę
5

Użyj wyrażenia regularnego, aby je zweryfikować.

isDate('2018-08-01T18:30:00.000Z');

isDate(_date){
        const _regExp  = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
        return _regExp.test(_date);
    }
lpradhap
źródło
4

Odnosząc się do wszystkich powyższych komentarzy, doszedłem do rozwiązania.

Działa to, jeśli Dateprzekazany jest w formacie ISO lub trzeba manipulować w przypadku innych formatów.

var isISO = "2018-08-01T18:30:00.000Z";

if (new Date(isISO) !== "Invalid Date" && !isNaN(new Date(isISO))) {
    if(isISO == new Date(isISO).toISOString()) {
        console.log("Valid date");
    } else {
        console.log("Invalid date");
    }
} else {
    console.log("Invalid date");
}

Możesz grać tutaj na JSFiddle.

Nikhil Zurunge
źródło
1
To rozwiązanie działało dla mnie najlepiej, ponieważ ciągi dat obsługiwane przez moją aplikację mają format YYYY-MM-DD, więc dołączenie T00:00:00.000Ztego rozwiązania i sprawdzenie poprawności ciągów jest proste .
przyspieszyć
w przypadku javascript to działa, ale jak używać go w maszynopisie.?
Sae
3

Oto ulepszona funkcja, która używa tylko Date.parse():

function isDate(s) {
    if(isNaN(s) && !isNaN(Date.parse(s)))
        return true;
    else return false;
}

Uwaga: Date.parse () przeanalizuje liczby: na przykład Date.parse(1)zwróci datę. Sprawdzamy więc, czy snie jest to liczba, czy jest to data.

A-Sharabiani
źródło
1
to nie działa, ponieważ zdanie „testu 2” minie jako prawdziwa data. testowany w najnowszej wersji chrome
user1751287
2

Zrobiłbym to

var myDateStr= new Date("2015/5/2");

if( ! isNaN ( myDateStr.getMonth() )) {
    console.log("Valid date");
}
else {
    console.log("Invalid date");
}

Graj tutaj

kiranvj
źródło
2
To nie działa w obecnym Chrome, prawdopodobnie w innych przeglądarkach. Zmieniłem podany ciąg znaków EXAMPLE STRING 12345i zwraca on „Ważna data”.
1

Oto minimalistyczna wersja.

var isDate = function (date) {
    return!!(function(d){return(d!=='Invalid Date'&&!isNaN(d))})(new Date(date));
}
Pan Polywhirl
źródło
1
Nadal nie działa w moim przykładzie:isDate("  1")
Tomas
@ Tom Należy sprawdzić, czy wartość zawiera znaki spacji przed określeniem, czy jest to data. Twój problem to szczególny przypadek, którym logika kontrolera musi się zająć.
Pan Polywhirl,
1
Sprawdzanie, czy znaki białych znaków nie są wymagane, ponieważ ciąg 1 stycznia 2020 r. Jest prawidłową datą zawierającą białe znaki. Twoja metoda nie bierze tego pod uwagę.
Kirstin Walsh
1

Ta funkcja na żądanie działa idealnie, zwraca wartość true dla prawidłowej daty. Pamiętaj, aby zadzwonić, używając daty w formacie ISO (rrrr-mm-dd lub rrrr / mm / dd):

function validateDate(isoDate) {

    if (isNaN(Date.parse(isoDate))) {
        return false;
    } else {
        if (isoDate != (new Date(isoDate)).toISOString().substr(0,10)) {
            return false;
        }
    }
    return true;
}
Peter DK
źródło
1
To dobrze, ale nie odpowiada całkowicie na pytanie. W szczególności nie działa w przypadku „2009-11-10T07: 00: 00 + 0000”, jednego z podanych przykładów.
amadan
Nie sądzę, że to działa tak, jak powinno się sprawdzić Data („2016-12-30T08: 00: 00.000Z”) // false
Jose Browne
Bez względu na to, czy to działa, można to uprościć jakoreturn !isNaN(Date.parse(isoDate)) || isoDate == new Date(isoDate).toISOString().substr(0,10);
Michel Jung,
1

Wiem, że to stare pytanie, ale stanąłem przed tym samym problemem i zauważyłem, że żadna z odpowiedzi nie zadziałała prawidłowo - konkretnie wycięto liczby (12003445 itd.) Z dat, co jest pierwotnym pytaniem. Oto dość niekonwencjonalna metoda, o której mogłem pomyśleć i wydaje się, że działa. Proszę wskazać, czy istnieją przypadki, w których się nie powiedzie.

if(sDate.toString() == parseInt(sDate).toString()) return false;

To jest linia do usunięcia liczb. Zatem cała funkcja może wyglądać następująco:

function isDate(sDate) {  
  if(sDate.toString() == parseInt(sDate).toString()) return false; 
  var tryDate = new Date(sDate);
  return (tryDate && tryDate.toString() != "NaN" && tryDate != "Invalid Date");  
}

console.log("100", isDate(100));
console.log("234", isDate("234"));
console.log("hello", isDate("hello"));
console.log("25 Feb 2018", isDate("25 Feb 2018"));
console.log("2009-11-10T07:00:00+0000", isDate("2009-11-10T07:00:00+0000"));

peekolo
źródło
1
console.log("hello 1 ", isDate("hello 1 "));zwraca wartość true
Jan
masz rację! masz rozwiązanie? Do tej pory wydaje mi się, że żadna z odpowiedzi tutaj nie dotyczyła właściwie pytania!
peekolo,
„100%”, procent, zwraca prawdę
toddmo
0

czy można sprawdzić, czy funkcja związana z datą jest dostępna dla obiektu w celu ustalenia, czy jest to obiekt Data, czy nie?

lubić

var l = new Date();
var isDate = (l.getDate !== undefined) ? true; false;
Kishore Relangi
źródło
0

Tak właśnie to robię. Nie obejmie to wszystkich formatów. Musisz odpowiednio dostosować. Mam kontrolę nad formatem, więc działa dla mnie

function isValidDate(s) {
            var dt = "";
            var bits = [];
            if (s && s.length >= 6) {
                if (s.indexOf("/") > -1) {
                    bits = s.split("/");
                }
                else if (s.indexOf("-") > -1) {
                    bits = s.split("-");
                }
                else if (s.indexOf(".") > -1) {
                    bits = s.split(".");
                }
                try {
                    dt = new Date(bits[2], bits[0] - 1, bits[1]);
                } catch (e) {
                    return false;
                }
                return (dt.getMonth() + 1) === parseInt(bits[0]);
            } else {
                return false;
            }
        }
kheya
źródło
-1

Ok, to stare pytanie, ale znalazłem inne rozwiązanie, sprawdzając je tutaj. Dla mnie działa sprawdzenie, czy funkcja getTime () jest obecna w obiekcie date:

const checkDate = new Date(dateString);

if (typeof checkDate.getTime !== 'function') {
  return;
}
m.steini
źródło
-1

document.getElementById('r1').innerHTML = dayjs('sdsdsd').isValid()

document.getElementById('r2').innerHTML = dayjs('2/6/20').isValid()
<script src="https://unpkg.com/[email protected]/dayjs.min.js"></script>

<p>'sdsdsd' is a date: <span id="r1"></span></p>
<p>'2/6/20' is a date: <span id="r2"></span></p>

Lekka biblioteka jest gotowa dla Ciebie: Day.js

Brak klucza
źródło
1
Jest to w zasadzie reklama na StackOverflow, powstrzymaj się od tego.
c4sh
-4
SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
sdf.setLenient(false);

Domyślnie jest ustawiona na PRAWDA. Zatem nawet ciągi w niewłaściwym formacie zwracają dobre wartości.

Użyłem czegoś takiego:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
formatter.setLenient(false);
String value = "1990/13/23"; 

try {
      Date date = formatter.parse(value);
      System.out.println(date);
    }catch (ParseException e) 
  {
    System.out.println("its bad");
  }
Anupam Mahapatra
źródło
5
... javascript ?!
artparks
-5

Spróbuj tego:

if (var date = new Date(yourDateString)) {
    // if you get here then you have a valid date       
}
Andrew Hare
źródło
6
To mi nie działa. Po pierwsze warunek warunku nie jest analizowany, ale jeśli go usuniesz i spróbujesz czegoś takiego: if (data = nowa data („śmieci”)) {alert (data); } Nawet jeśli data jest śmieciem, alert nadal będzie wykonywany, ponieważ funkcja Data zwróci „Nieprawidłowa data” (przynajmniej w Firefox), więc warunek zostanie spełniony. Myślę, że jeśli niektóre przeglądarki zwrócą wartość null w niepoprawną datę, to będzie działać w tych przeglądarkach. Może tu występować niespójność przeglądarki.
Cloudranger