Wykrywanie wystąpienia „niepoprawnej daty” w JavaScript

1493

Chciałbym powiedzieć różnicę między prawidłowymi i nieprawidłowymi obiektami daty w JS, ale nie mogłem dowiedzieć się, jak:

var d = new Date("foo");
console.log(d.toString()); // shows 'Invalid Date'
console.log(typeof d); // shows 'object'
console.log(d instanceof Date); // shows 'true'

Jakieś pomysły na napisanie isValidDatefunkcji?

  • Ash zaleca się Date.parsedo analizowania ciągów daty, co daje wiarygodny sposób sprawdzenia, czy ciąg daty jest prawidłowy.
  • Jeśli to możliwe, wolę, aby mój interfejs API zaakceptował instancję Date i mógł sprawdzić / potwierdzić, czy jest poprawna, czy nie. Rozwiązanie Borgara to robi, ale muszę to przetestować w różnych przeglądarkach. Zastanawiam się także, czy istnieje bardziej elegancki sposób.
  • Ash kazał mi rozważyć, czy mój interfejs API nie akceptuje Datew ogóle instancji, byłoby to najłatwiejsze do sprawdzenia.
  • Borgar zasugerował przetestowanie Dateinstancji, a następnie przetestowanie Datewartości czasu. Jeśli data jest nieprawidłowa, wartość czasu to NaN. Sprawdziłem za pomocą ECMA-262 i takie zachowanie jest w standardzie, dokładnie tego szukam.
orip
źródło
18
Można usunąć instrukcję if, zmieniając return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
treść
3
@styfle - domyślam się, że jest to preferencja stylu: jaśniejsze jest oddzielenie kontroli typu od logiki równości.
orip
26
Dyskurs @orip jest dokładnie odradzany w pytaniach. Zapoznaj się z odpowiednimi meta tematami, aby poznać uzasadnienie. Umieszczenie odpowiedzi na własne pytanie w samym pytaniu jest niezgodne z zasadami witryny. OTOH, podziękowania za odpowiedzi i „EDYCJA” w odpowiedzi to typowy puch. Jeśli chcesz, aby twoje najwyżej ocenione pytanie identyfikowało cię jako osobę, która nie wie, czym jest SO i jak z niej korzystać i nie chce się tego uczyć - bądź moim gościem.
14
@orip: To nie było „zagubione”; jeśli nadal chcesz zobaczyć historię, pytanie jest wciąż zaśmiecone w historii wersji pytania. Ale to nie należy do pytania. Przy 37 tys. Przedstawicieli powinieneś to wiedzieć.
Wyścigi lekkości na orbicie
6
Łaskawie zakończ wojnę edycji. Edycje tego pytania są omawiane na stronie meta . Proszę nie edytować / wycofać tego postu dalej. Jeśli nie zgadzasz się z poprzednimi zmianami / wycofaniami lub masz jakieś uwagi na ich temat, prosimy pisać w tym wątku meta, a nie tutaj.
Lundin,

Odpowiedzi:

1301

Oto jak bym to zrobił:

if (Object.prototype.toString.call(d) === "[object Date]") {
  // it is a date
  if (isNaN(d.getTime())) {  // d.valueOf() could also work
    // date is not valid
  } else {
    // date is valid
  }
} else {
  // not a date
}

Aktualizacja [2018-05-31] : Jeśli nie interesują Cię obiekty Date z innych kontekstów JS (zewnętrzne okna, ramki lub ramki iframe), ta prostsza forma może być preferowana:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}
Borgar
źródło
21
Instancja przerw między ramkami. Pisanie kaczką też może działać dobrze: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Ponieważ pytanie dotyczy ogólnej funkcji użyteczności, wolę być bardziej rygorystyczny.
Borgar,
11
@Borgar, właśnie znalazłem moją odpowiedź: „Problemy pojawiają się, jeśli chodzi o skrypty w środowiskach DOM z wieloma ramkami. W skrócie, obiekty Array utworzone w jednym ramce iframe nie współużytkują [[Prototyp]] z tablicami utworzonymi w innym ramce iframe Ich konstruktory są różnymi obiektami, więc zarówno instancja, jak i kontrole konstruktora kończą się niepowodzeniem. ”
Ash
64
ty nawet nie trzeba d.getTimepo prostuisNan(d)
TecHunter
8
Można to uprościć w ten sposób:d instanceof Date && !isNaN(d.getTime())
Zorgatone,
5
Dziękuję za odpowiedź, ale chciałbym podkreślić komentarze @Borgar i @blueprintChris: 1na przykład parsując cyfrę , nadal miałbym prawidłową datę, Mon Jan 01 2001 00:00:00która faktycznie jest datą, jednak dla celów mojej aplikacji jest to całkowicie bezużyteczne . Dlatego przynajmniej w moim przypadku potrzebna jest dodatkowa weryfikacja danych wejściowych. Ta odpowiedź potwierdza dateObjectnie Date!
dnhyde
264

Zamiast używać new Date()należy użyć:

var timestamp = Date.parse('foo');

if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse()zwraca znacznik czasu, liczbę całkowitą reprezentującą liczbę milisekund od 01 / Jan / 1970. Zwróci, NaNjeśli nie będzie mógł przeanalizować podanego ciągu daty.

Popiół
źródło
119
-1 Nie wiem, dlaczego ma tyle głosów, Date.parsezależy od implementacji i zdecydowanie nie można ufać, że analizuje ogólne ciągi dat. W popularnych przeglądarkach nie ma jednego formatu, który zostałby poprawnie przeanalizowany, a tym bardziej wszystkich używanych (choć format ISO8601 określony w ES5 powinien być w porządku).
RobG
1
Jeśli używasz tego new Date('foo'), jest to w zasadzie równoważne z tą Date.parse('foo')metodą. Widzieć: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… To, co powiedział @RobG, dotyczy również tego.
golddragon007
2
Ten test nie powiedzie się w Chrome. Na przykład Date.parse („AAA-0001”) w Chrome daje mi numer.
Nick
nie udało się ... wykryć wszystkie wartości liczbowe
Hos Mercury
109

Możesz sprawdzić ważność Dateobiektu dza pomocą

d instanceof Date && isFinite(d)

Aby uniknąć problemów między ramkami, można wymienić instanceofczek na

Object.prototype.toString.call(d) === '[object Date]'

Wezwanie do getTime() jak w odpowiedzi borgar jest to niepotrzebne, jak isNaN()i isFinite()zarówno niejawnie konwertowane na liczby.

Christoph
źródło
Spróbuj tego w chrome - Object.prototype.toString.call (nowa data („2013-07-09T19: 07: 9Z”)). Zwróci „[data obiektu]”. Według ciebie zatem „2013-07-09T19: 07: 9Z” powinien być prawidłową datą. Ale to nie jest. Możesz to zweryfikować, ponownie w chrome, wykonując var dateStr = nowa data („2013-07-09T19: 07: 9Z”); dateStr Zwróci nieprawidłową datę.
Tintin
2
@Tintin: po co to isFinite()jest - toString.call()to tylko instanceofczęść czeku
Christoph
Czy porównywanie z „[data obiektu]” będzie działać z przeglądarkami nieanglojęzycznymi? Wątpię.
kristianp
2
@kristianp faktycznie tak będzie i prawdopodobnie jest nawet częścią specyfikacji ECMAScript. Ale tak, wydaje się brzydka.
binki,
Dla mnie pierwsze podejście tutaj jest najlepsza opcja, choć nie jestem pewien, czy jest jakaś zaleta w świecie rzeczywistym z użyciem isFiniteponad isNaN(zarówno działać dobrze z Date(Infinity)). Ponadto, jeśli chcesz warunek przeciwny, robi się nieco prostsze: if (!(date instanceof Date) || isNaN(date)).
Andrew
86

Moje rozwiązanie polega na sprawdzeniu, czy otrzymałeś prawidłowy obiekt daty:

Realizacja

Date.prototype.isValid = function () {
    // An invalid date object returns NaN for getTime() and NaN is the only
    // object not strictly equal to itself.
    return this.getTime() === this.getTime();
};  

Stosowanie

var d = new Date("lol");

console.log(d.isValid()); // false

d = new Date("2012/09/11");

console.log(d.isValid()); // true
Ash Clarke
źródło
28
isNaNjest bardziej wyraźnym sposobem na testowanie NaN
orip
1
A jednak zawsze znajdziesz ludzi piszących własne wersje :) documentcloud.github.com/underscore/docs/…
Ash Clarke
4
ponieważ szanuję underscore.js, skłoniło to do pewnych badań. isNaN("a") === true, podczas gdy ("a" !== "a") === false. Warto o tym pomyśleć. +1
orip
8
Testowałem wydajność dla 3 głównych rozwiązań, które tu znalazłem. Gratulacje, jesteś zwycięzcą! jsperf.com/detecting-an-invalid-date
zVictor
2
@Ali To jest prawidłowy obiekt daty. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). Jeśli przekazujesz ciąg do konstruktora daty, musisz przekazać znormalizowany ciąg, aby uzyskać wiarygodny wynik. W szczególności „Łańcuch powinien mieć format rozpoznawany przez metodę Date.parse ()”. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ash Clarke
71

najkrótsza odpowiedź, aby sprawdzić prawidłową datę

if(!isNaN(date.getTime()))
abhirathore2006
źródło
2
Jedynym problemem jest to, że data nie jest typu Data; pojawia się błąd JS.
Andrew
@Andrew musisz utworzyć obiekt Data, a jeśli już masz obiekt, użyjdate && !isNaN(date.getTime())
abhirathore2006
To nadal powoduje błąd JS, jeśli datenie jest typu Data. Na przykład: var date = 4; date && !isNaN(date.getTime());.
Andrew
@Andrew use date instanceof Date && !isNaN(date.getTime())
abhirathore2006
3
Tak, jak inne odpowiedzi sprzed 8 lat. : P stackoverflow.com/a/1353945/2321042
Andrew
45

Możesz po prostu użyć moment.js

Oto przykład:

var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false

Sekcja walidacji w dokumentacji jest dość jasna.

Ponadto następujące flagi analizowania powodują niepoprawną datę:

  • overflow: Przepełnienie pola daty, takiego jak 13. miesiąc, 32. dzień miesiąca (lub 29 lutego w latach bez przestępstwa), 367. dzień roku itp. Przepełnienie zawiera indeks nieprawidłowej jednostki dopasować #invalidAt (patrz poniżej); -1 oznacza brak przepełnienia.
  • invalidMonth: Niepoprawna nazwa miesiąca, taka jak moment („Marbruary”, „MMMM”) ;. Zawiera sam niepoprawny ciąg miesiąca, w przeciwnym razie null.
  • empty: Ciąg wejściowy, który nie zawiera niczego, co można przetwarzać, na przykład moment („to nonsens”) ;. Boolean.
  • Itp.

Źródło: http://momentjs.com/docs/

Yves M.
źródło
6
Najlepsze rozwiązanie, niezwykle łatwe do wdrożenia, działa z dowolnym formatowaniem (moim przypadkiem jest dd / MM / rrrr), zna również lata przestępne i nie przekształca niepoprawnych dat (tj. 29.02.2015) na same ważne (tj. 30.03.2015). Aby sprawdzić datę w formularzu dd / MM / rrrr, właśnie musiałem użyćmoment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin
3
To użycie Moment zostało wycofane :(
James Sumners,
2
To zastosowanie nie zostało amortyzowane. Moment wywoływania (wejście) bez ciągu formatującego jest amortyzowany (chyba że dane wejściowe mają format ISO).
Chet
2
Ta metoda może być bardzo powolna podczas przetwarzania wielu dat. W takich przypadkach lepiej użyć wyrażenia regularnego.
Grid Trekkor
2
Użycie pliku mom.js może być proste, ale stanowi ogromne obciążenie. Ta biblioteka jest OGROMNA. Zanotowałem twoją odpowiedź.
Mick
38

Chciałbym wspomnieć, że widget jQuery UI DatePicker ma bardzo dobrą metodę narzędzia sprawdzania poprawności daty, która sprawdza format i ważność (np. Niedozwolone są daty 01/01/2013).

Nawet jeśli nie chcesz używać widżetu datepicker na swojej stronie jako elementu interfejsu użytkownika, zawsze możesz dodać jego bibliotekę .js do swojej strony, a następnie wywołać metodę sprawdzania poprawności, przekazując do niej wartość, którą chcesz sprawdzić. Aby uczynić życie jeszcze łatwiejszym, jako dane wejściowe potrzebny jest ciąg znaków, a nie obiekt Date JavaScript.

Zobacz: http://api.jqueryui.com/datepicker/

Nie ma go na liście jako metody, ale istnieje - jako funkcja narzędzia. Wyszukaj na stronie „parsowane”, a znajdziesz:

$ .datepicker.parseDate (format, wartość, ustawienia) - Wyodrębnij datę z wartości ciągu o określonym formacie.

Przykładowe użycie:

var stringval = '01/03/2012';
var testdate;

try {
  testdate = $.datepicker.parseDate('mm/dd/yy', stringval);
             // Notice 'yy' indicates a 4-digit year value
} catch (e)
{
 alert(stringval + ' is not valid.  Format must be MM/DD/YYYY ' +
       'and the date value must be valid for the calendar.';
}

(Więcej informacji na temat określania formatów dat można znaleźć na stronie http://api.jqueryui.com/datepicker/#utility-parseDate )

W powyższym przykładzie nie zobaczysz komunikatu ostrzegawczego, ponieważ „01.03.2012” jest datą obowiązującą w kalendarzu w określonym formacie. Jeśli na przykład parametr „stringval” będzie równy „13.04.2013”, otrzymasz komunikat ostrzegawczy, ponieważ wartość „13.04.2013” ​​nie jest ważna w kalendarzu.

Jeśli przekazana wartość ciągu zostanie pomyślnie przeanalizowana, wartością „testdate” będzie obiekt JavaScript Date reprezentujący przekazaną wartość ciągu. Jeśli nie, byłoby niezdefiniowane.

Matt Campbell
źródło
3
Upvote za to, że jest pierwszą odpowiedzią na formaty daty inne niż angielski / lokalny.
siekiera.
26

Naprawdę podobało mi się podejście Christopha (ale nie miałem dość reputacji, aby go zagłosować). Na mój użytek wiem, że zawsze będę miał obiekt Date, dlatego właśnie przedłużyłem datę za pomocą ważnej metody ().

Date.prototype.valid = function() {
  return isFinite(this);
}

Teraz mogę to napisać i jest to o wiele bardziej opisowe niż sprawdzanie isFinite w kodzie ...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
Brooks
źródło
10
Rozszerzasz prototyp? To duży JavaScript nie nie!
Jasdeep Khalsa
Upvoting ponieważ isFinitedziałał dla mnie idealnie. Ale tak, nie ma sensu przedłużać prototypu. !isFinitena Datezłapie fakt, że Datejest Invalid Date. Warto również zauważyć, że mój kontekst znajduje się w węźle.
Staghouse
23
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
faridz
źródło
5
To jest to samo @Borgar napisał 2 lata temu ... Co nowego?
niebieskawy
11
Są to dwie linie zamiast brzydko zagnieżdżonych instrukcji if.
Cypher
17

za pomocą tego skryptu możesz sprawdzić poprawny format pliku txDate.value. jeśli był niepoprawny format Data obejct nie wystąpił i zwrócił null do dt.

 var dt = new Date(txtDate.value)
 if (isNaN(dt))

I jak sugeruje w skrócie @ MiF

 if(isNaN(new Date(...)))
Yuseferi
źródło
isNaN (nowa data (...)) - prosta i krótka metoda
MiF
1
@ Mi tak, aktualizuję moją odpowiedź z twoją sugestią;) dzięki
Yuseferi
16

Korzystam z następującego kodu, aby sprawdzić wartości dla roku, miesiąca i daty.

function createDate(year, month, _date) {
  var d = new Date(year, month, _date);
  if (d.getFullYear() != year 
    || d.getMonth() != month
    || d.getDate() != _date) {
    throw "invalid date";
  }
  return d;
}

Aby uzyskać szczegółowe informacje, patrz Sprawdź datę w javascript

Jingguo Yao
źródło
strnie jest używany.
samis
12

Zbyt wiele skomplikowanych odpowiedzi tutaj, ale wystarczy prosta linia (ES5):

Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;

lub nawet w ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));
Sebastien H.
źródło
1
Z MDN: „Metoda Date.parse () analizuje ciąg znaków reprezentujący datę i zwraca liczbę milisekund od 1 stycznia 1970 r., 00:00:00 UTC lub NaN ...” Więc uruchamianie potencjalnej daty przez to funkcja zwraca liczbę całkowitą lub NaN. Następnie funkcja isNaN () da czysty logiczny komunikat informujący, czy oryginalna wartość była poprawnym obiektem daty, czy nie. To wystarczy, aby wykonać kontrolę na miejscu, ale powyższy przykład dołącza tę metodę do obiektu Date, aby funkcja była łatwo dostępna i czytelna w całym programie.
Max Wilder
jeśli d ma wartość logiczną, otrzymasz 0 lub 1, co nie jest Nan !!
davcup
@davcup właśnie przetestowałem przy użyciu Date.parse(true), poprawnie otrzymuję NaN.
Sebastien H.
12

Widziałem kilka odpowiedzi, które zbliżyły się do tego małego fragmentu.

Sposób JavaScript:

function isValidDate(dateObject){ return new Date(dateObject).toString() !== 'Invalid Date'; }
isValidDate(new Date('WTH'));

Sposób TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
Jason Foglia
źródło
1
Nie jestem pewien, czy coś mi umknęło, ale czy nowa funkcja Date () nie jest dwa razy bezcelowa?
Jon Catmull,
2
Ten ostatni nie ma nic wspólnego z TypeScript. Jest to całkowicie poprawny JS.
hackel
9

Fajne rozwiązanie! Zawarte w mojej bibliotece funkcji pomocniczych, teraz wygląda następująco:

Object.isDate = function(obj) {
/// <summary>
/// Determines if the passed object is an instance of Date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.prototype.toString.call(obj) === '[object Date]';
}

Object.isValidDate = function(obj) {
/// <summary>
/// Determines if the passed object is a Date object, containing an actual date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.isDate(obj) && !isNaN(obj.getTime());
}
Dmytro Szewczenko
źródło
9

To po prostu działało dla mnie

new Date('foo') == 'Invalid Date'; //is true

Jednak to nie zadziałało

new Date('foo') === 'Invalid Date'; //is false
użytkownik1296274
źródło
5
Wierzę, że to zależy od przeglądarki.
barrypicker
@barrypicker Co to znaczy, że zależy od przeglądarki?
Ajil O.
Możesz zrobić: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut
9

Do projektów Angular.js możesz użyć:

angular.isDate(myDate);
Nick Taras
źródło
3
Zwraca wartość true dla testowania obiektu daty, który został zainicjowany z niepoprawną datą.
dchhetri
6

Żadna z tych odpowiedzi nie działała dla mnie (testowana w przeglądarce Safari 6.0) podczas próby sprawdzenia poprawności daty, takiej jak 31.12.2012, jednak działają one dobrze, gdy próbuję daty większej niż 31.

Musiałem więc trochę brutalizować siłę. Zakładając, że data jest w formacie mm/dd/yyyy. Korzystam z odpowiedzi @ Broox:

Date.prototype.valid = function() {
    return isFinite(this);
}    

function validStringDate(value){
    var d = new Date(value);
    return d.valid() && value.split('/')[0] == (d.getMonth()+1);
}

validStringDate("2/29/2012"); // true (leap year)
validStringDate("2/29/2013"); // false
validStringDate("2/30/2012"); // false
Dex
źródło
(nowa data (30.02.2014)). valid () zwraca wartość true
Andre Figueiredo
1
Minęło trochę czasu, odkąd odpowiedziałem na to pytanie, ale możesz potrzebować obu warunków powrotu, w tym&& value.split('/')[0] == (d.getMonth()+1);
Dex
Używanie new Date('string date')jest równoważne z Date.parse('string date'), patrz: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/..., więc możesz otrzymać fałszywe wartości true lub false.
golddragon007
5

Żadne z powyższych rozwiązań nie działało dla mnie, ale działało

function validDate (d) {
        var date = new Date(d);
        var day = ""+date.getDate();
        if( day.length == 1)day = "0"+day;
        var month = "" +( date.getMonth() + 1);
        if( month.length == 1)month = "0"+month;
        var year = "" + date.getFullYear();

        return ((month + "/" + day + "/" + year) == d);
    }

powyższy kod sprawdzi, kiedy JS zamienia 31.03.2012 na 03.02.2012, że nie jest ważny

Jan
źródło
3
Ok, ale sprawdza się, czy ciąg znaków jest datą w formacie M / D / Y, a nie „różnicą między prawidłowymi i niepoprawnymi obiektami daty”. To nie jest tak naprawdę to pytanie.
Borgar,
powodem, dla którego jest sprawdzany względem formatu, jest sprawdzenie, czy data uległa zmianie po jego przeanalizowaniu
John
Czy OP nie prosi o metodę zwracającą wartość logiczną, a nie sformatowany ciąg?
barrypicker
1
Przykładowy kod zwraca wartość logiczną, formatowanie odgrywa rolę w testowaniu niektórych nieprawidłowych przypadków.
Jan
5
IsValidDate: function(date) {
        var regex = /\d{1,2}\/\d{1,2}\/\d{4}/;
        if (!regex.test(date)) return false;
        var day = Number(date.split("/")[1]);
        date = new Date(date);
        if (date && date.getDate() != day) return false;
        return true;
}
Michael Goldshmidt
źródło
4

Napisałem tę funkcję. Przekaż mu parametr ciągu, który określi, czy jest to poprawna data, czy nie, na podstawie tego formatu „dd / MM / rrrr”.

tutaj jest test

input: „hahaha”, output: false.

wejście: „29/2/2000”, wyjście: prawda.

wejście: „29/2/2001”, wyjście: fałsz.

function isValidDate(str) {
    var parts = str.split('/');
    if (parts.length < 3)
        return false;
    else {
        var day = parseInt(parts[0]);
        var month = parseInt(parts[1]);
        var year = parseInt(parts[2]);
        if (isNaN(day) || isNaN(month) || isNaN(year)) {
            return false;
        }
        if (day < 1 || year < 1)
            return false;
        if(month>12||month<1)
            return false;
        if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31)
            return false;
        if ((month == 4 || month == 6 || month == 9 || month == 11 ) && day > 30)
            return false;
        if (month == 2) {
            if (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0 && (year % 100) == 0)) {
                if (day > 29)
                    return false;
            } else {
                if (day > 28)
                    return false;
            }      
        }
        return true;
    }
}
Yaseen
źródło
4

Date.prototype.toISOStringrzuca RangeError(przynajmniej w Chromium i Firefox) w nieprawidłowe daty. Możesz użyć go jako środka sprawdzania poprawności i może nie być potrzebny isValidDatejako taki (EAFP). W przeciwnym razie jest to:

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}
saaj
źródło
1
Wydaje się, że jest to jedyna funkcja, która generuje błąd zgodnie z definicją ECMA-262. 15.9.5.43 Date.prototype.toISOString () Ta funkcja zwraca wartość String reprezentującą instancję w czasie reprezentowaną przez ten obiekt Date. Format ciągu to format ciągu daty i godziny zdefiniowany w 15.9.1.15. Wszystkie pola są obecne w ciągu. Strefą czasową jest zawsze UTC, oznaczony sufiksem Z. Jeśli wartość czasu tego obiektu nie jest liczbą skończoną, zgłaszany jest wyjątek RangeError.
Henry Liu
3

Zainspirowany podejściem Borgara upewniłem się, że kod nie tylko potwierdza datę, ale faktycznie upewnia się, że data jest prawdziwą datą, co oznacza, że ​​daty takie jak 31/09/2011 i 29/02/2011 są niedozwolone.

function(dateStr) {
    s = dateStr.split('/');
    d = new Date(+s[2], s[1]-1, +s[0]);
    if (Object.prototype.toString.call(d) === "[object Date]") {
        if (!isNaN(d.getTime()) && d.getDate() == s[0] && 
            d.getMonth() == (s[1] - 1)) {
            return true;
        }
    }
    return "Invalid date!";
}
Raz
źródło
Ale ... metody powyżej (@ Borgar i inne) już sprawdzają ten typ ważności ... Nie mogę uzyskać problemu.
niebieskawy
Borgar nie - zobacz swój komentarz do swojej odpowiedzi.
EML
1
To rozwiązanie działa tylko wtedy, gdy twój kraj używa dd/MM/yyyynotacji. Zwraca także, truegdy jest ważny, a 'Invalid date!'jeśli nie, lepiej zwrócić tylko 1 typ.
A1rPun
3

Połączyłem najlepsze wyniki wydajności, które znalazłem wokół tego sprawdzenia, czy dany obiekt:

Wynik jest następujący:

function isValidDate(input) {
  if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
    return false;

  var time = input.getTime();
  return time === time;
};
zVictor
źródło
2

Obiekt daty na ciąg jest prostszym i niezawodnym sposobem na wykrycie, czy oba pola są poprawne. np. jeśli wpiszesz to „-------” w polu wprowadzania daty. Niektóre z powyższych odpowiedzi nie będą działać.

jQuery.validator.addMethod("greaterThan", 

    function(value, element, params) {
        var startDate = new Date($(params).val());
        var endDate = new Date(value);

        if(startDate.toString() === 'Invalid Date' || endDate.toString() === 'Invalid Date') {
            return false;
        } else {
            return endDate > startDate;
        }
    },'Must be greater than {0}.');
kam
źródło
2

Wybrana odpowiedź jest doskonała i ja jej również używam. Jeśli jednak szukasz sposobu na sprawdzenie poprawności wprowadzania daty użytkownika, powinieneś mieć świadomość, że obiekt Date bardzo uporczywie przekształca argumenty konstrukcyjne w niepoprawne. Poniższy kod testu jednostkowego ilustruje ten punkt:

QUnit.test( "valid date test", function( assert ) {
  //The following are counter-examples showing how the Date object will 
  //wrangle several 'bad' dates into a valid date anyway
  assert.equal(isValidDate(new Date(1980, 12, 15)), true);
  d = new Date();
  d.setFullYear(1980);
  d.setMonth(1);
  d.setDate(33);
  assert.equal(isValidDate(d), true);
  assert.equal(isValidDate(new Date(1980, 100, 150)), true);
  //If you go to this exterme, then the checker will fail
  assert.equal(isValidDate(new Date("This is junk")), false);
  //This is a valid date string
  assert.equal(isValidDate(new Date("November 17, 1989")), true);
  //but is this?
  assert.equal(isValidDate(new Date("November 35, 1989")), false);  
  //Ha!  It's not.  So, the secret to working with this version of 
  //isValidDate is to pass in dates as text strings... Hooboy
  //alert(d.toString());
});
dolphus333
źródło
2
function isValidDate(strDate) {
    var myDateStr= new Date(strDate);
    if( ! isNaN ( myDateStr.getMonth() ) ) {
       return true;
    }
    return false;
}

Nazwij to tak

isValidDate(""2015/5/2""); // => true
isValidDate(""2015/5/2a""); // => false
kiranvj
źródło
2

Gotowa funkcja oparta na najwyżej ocenianej odpowiedzi:

  /**
   * Check if date exists and is valid.
   *
   * @param {String} dateString Date in YYYY-mm-dd format.
   */
  function isValidDate(dateString) {
  var isValid = false;
  var date;

  date =
    new Date(
      dateString);

  if (
    Object.prototype.toString.call(
      date) === "[object Date]") {

    if (isNaN(date.getTime())) {

      // Date is unreal.

    } else {
      // Date is real if month and day match each other in date and string (otherwise may be shifted):
      isValid =
        date.getUTCMonth() + 1 === dateString.split("-")[1] * 1 &&
        date.getUTCDate() === dateString.split("-")[2] * 1;
    }
  } else {
    // It's not a date.
  }

  return isValid;
}
Strefa
źródło
2

Proste i eleganckie rozwiązanie:

const date = new Date(`${year}-${month}-${day} 00:00`)
const isValidDate = (Boolean(+date) && date.getDate() == day)

źródła:

[1] https://medium.com/@esganzerla/simple-date-validation-with-javascript-caea0f71883c

[2] Niepoprawna data podana w nowej dacie () w JavaScript

Przezwisko
źródło
1
date.getDate() == dayjest niewystarczający do ustalenia, czy data jest ważna. Oryginalny format daty zwróci nieprawidłową datę w niektórych implementacjach, niezależnie od tego, czy data jest poprawna, czy nie. Również „1970-01-01 00:00”, jeśli poprawnie przeanalizowane, zwróci false (tj. Boolean(+new Date("1970-01-01"))Zwróci false).
RobG
OSTRZEŻENIE: To nie zadziała w Safari
Vigrant
Będzie działał w Safari, jeśli użyjesz formatu const date = new Date(year, month, day); Uwaga: miesiąc jest w ten sposób indeksowany jako 0, więc może być konieczne odjęcie jednego, aby poprawnie wyrównać.
Vigrant
1

Myślę, że część tego jest długim procesem. Możemy to skrócić, jak pokazano poniżej:

 function isValidDate(dateString) {
        debugger;
        var dateStringSplit;
        var formatDate;

        if (dateString.length >= 8 && dateString.length<=10) {
            try {
                dateStringSplit = dateString.split('/');
                var date = new Date();
                date.setYear(parseInt(dateStringSplit[2]), 10);
                date.setMonth(parseInt(dateStringSplit[0], 10) - 1);
                date.setDate(parseInt(dateStringSplit[1], 10));

                if (date.getYear() == parseInt(dateStringSplit[2],10) && date.getMonth()+1 == parseInt(dateStringSplit[0],10) && date.getDate() == parseInt(dateStringSplit[1],10)) {
                    return true;
                }
                else {
                    return false;
                }

            } catch (e) {
                return false;
            }
        }
        return false;
    }
użytkownik889209
źródło
3
Pytanie dotyczy tego, jak znaleźć nieprawidłowe wystąpienia daty, a nie ciągi, a poza tym: kto twierdzi, że data nie może być ograniczona przez coś innego niż ukośnik?
Jon z
1

W przypadku elementów daty opartych na int 1:

var is_valid_date = function(year, month, day) {
    var d = new Date(year, month - 1, day);
    return d.getFullYear() === year && (d.getMonth() + 1) === month && d.getDate() === day
};

Testy:

    is_valid_date(2013, 02, 28)
&&  is_valid_date(2016, 02, 29)
&& !is_valid_date(2013, 02, 29)
&& !is_valid_date(0000, 00, 00)
&& !is_valid_date(2013, 14, 01)
Denis Ryżkow
źródło