Regex для підтвердження формату дати дд / мм / рр


172

Мені потрібно перевірити рядок дати для формату dd/mm/yyyyрегулярним виразом.

Цей регулярний вираз підтверджує dd/mm/yyyy, але не недійсні дати, такі як 31/02/4500:

^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}$

Що таке дійсний регулярний вираз для перевірки dd/mm/yyyyформату з підтримкою високосного року?


3
Я думаю, що це може допомогти, якщо ви встановите точне сподівання, оскільки цей регулярний вираз НЕ насправді правильно підтверджує високосні роки; наприклад, в лютому 2013 року немає 29 лютого, але цей регекс стверджує, що таке дійсне: regexr.com?346fp
TML

7
Чому саме з Regex? Є простіші (і точніші) способи ...
Ден Пузей

2
Регулярні вирази призначені для відповідності шаблонів, не перевіряючи числових значень. Знайдіть ймовірний рядок з регулярним виразом, а потім перевірте його числове значення будь-якою мовою вашого хоста (PHP, якою б не була).
Енді Лестер

3
Ця відповідь була додана до FAQ FAQ про регулярне вираження стека в розділі "Загальні завдання на перевірку".
aliteralmind

4
@BurhanKhalid: Ви помиляєтесь. Регулярний вираз є найкращим інструментом для перевірки, оскільки введення HTML5 має атрибут, названий, patternякий приймає звичайний вираз, а браузери автоматично перевіряють регулярний вираз, не використовуючи жодного JavaScript. Просто встановивши регулярний вираз в атрибуті шаблону!
трепет

Відповіді:


329

Згенерований вами регулярний вираз не підтверджує високосні високосні роки, але є той самий, що робиться на тій же посаді . Я змінив його, щоб прийняти dd/mm/yyyy, dd-mm-yyyyабо dd.mm.yyyy.

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

Я трохи перевірив це у посиланні, яке Арун надав у своїй відповіді, а також тут, і, здається, працює.

Редагувати 14 лютого 2019 року. Я видалив кому, яка була в регулярному виразі, яка дозволяла дати, наприклад, дати 29-0,-11


9
Епічний гегекс! Наскільки легко це можна змінити відповідно до формату? Наприклад, yyyy-mm-dd та mm-dd-yyyy. Я розумів це, маючи це на увазі, але це виходить за рамки моїх навичок регексу.
mrswadge

7
Крім DD/MM/YYYYцього, цей регулярний вираз також приймає те, DD/MM/YYщо я не впевнений, що це було в початковому намірі афіші. Якщо ви не хочете підтримувати "YY", видаліть усі необов'язкові ?кількісні показники.
користувач1485864

2
@PurveshDesai замінити кожен 0?на 0, а також видалити останню появу ?.
Офір Лузон

4
@MaraisRossouw, Ви праві, протягом 4-х значного року фактично є 3, ?які слід видалити: замініть всі (?:1[6-9]|[2-9]\d)?на (?:1[6-9]|[2-9]\d).
Офір Лусон

2
Відмовляючись просто сказати це: WOW і звичайно дякую
Jero Dungog

266

Я продовжив регулярний вираз, поданий @Ofir Luzon для форматів dd-mmm-YYYY, dd / mmm / YYYY, dd.mmm.YYYY відповідно до моєї вимоги. Будь-хто інший з такою ж вимогою може звернутися до цього

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

і перевірено для деяких тестових випадків тут http://regexr.com/39tr1 .

Для кращого розуміння цього регулярного виразу зверніться до цього зображення: введіть тут опис зображення


1
Так, як ти це створив? :)
Бритви

Я створив його в Інтернеті за допомогою якогось веб-сайту, і тепер я також не пам'ятаю веб-сайт, з якого я створив це зображення. Я додам посилання, коли я згадаю :)
Алок Чаддхарі

4
@ user3733831 8888- це можливий рік. Я очікую дожити до приблизно такого віку.
Дан Ніссенбаум

1
Чудово працює навіть у високосні роки. Я також додав підтримку коротких іспанських імен місяця.
Fer R

2
@AlokChaudhary, діаграма була сформована за допомогою debuggex.com
Taha BASRI

69

Зверніть увагу:

Ваш регепс не працює роками, "які кратні 4 і 100, але не 400". Роки, які проходять тест, не є високосними. Наприклад: 1900, 2100, 2200, 2300, 2500 і т. Д. Іншими словами, він ставить усі роки з форматом \ d \ d00 в той самий клас високосних років, що невірно. - MuchToLearn

Так воно працює належним чином лише для [1901 - 2099] (Whew) 😊

dd / MM / yyyy:

Перевіряє, чи не високосний рік. Діють роки з 1900 по 9999 рік. Тільки дд / ММ / рр

(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)

7
Ця відповідь працює лише з dd / MM / yyyy. Тому правильна відповідь.
Родріго

2
@SylvainB Я виправив це
gdZeus

2
@gdZeus Дякуємо за доставку навіть через два роки! Страшно думати, що незавершене рішення так довго було підтверджене тут.
SylvainB

Щоб зробити це швидше, ви можете зробити групи негрупуючими. regexr.com/3esom ^ (? :(? :(? :( ?: 0 [1-9] | 1 [0-9] | 2 [0-8]) [\ /] (?: 0 [1- 9] | 1 [012])) | (? :( ?: 29 | 30 | 31) [\ /] (?: 0 [13578] | 1 [02])) | (? :( ?: 29 | 30 ) [\ /] (?: 0 [4,6,9] | 11))) [\ /] (?: 19 | [2-9] [0-9]) \ d \ d) | (?: 29 [\ /] 02 [\ /] (?: 19 | [2-9] [0-9]) (?: 00 | 04 | 08 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96)) $
Метт Вукоманович

Я припускаю, що виявив помилку: 29/02/2100не існує (2100 НЕ високосний рік), але все ж прийнятий за даною схемою.
KnorxThieus

17

спробуйте це.

^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$

ви можете перевірити регулярне вираження на http://www.regular-expressions.info/javascriptexample.html легко.


2
цей регулярний вираз не підтверджує дату місяця, як 30-02-2001... все одно дякую за відповідь :)
Nalaka526

12

Я підозрюю, що наступне настільки ж точне, як і можна було очікувати, не знаючи, коли локальна система користувача перейшла з юліанських на григоріанські календарі.

Він приймає або "-", "/", або нічого, як роздільник між роком, місяцем та днем, незалежно від порядку.

MMddyyyy:

^(((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))[-/]?[0-9]{4}|02[-/]?29[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

ddMMyyyy:

^(((0[1-9]|[12][0-9]|30)[-/]?(0[13-9]|1[012])|31[-/]?(0[13578]|1[02])|(0[1-9]|1[0-9]|2[0-8])[-/]?02)[-/]?[0-9]{4}|29[-/]?02[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

yyyyMMdd:

^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-/]?02[-/]?29)$

За винятком порядку, всі вони є точними до Юліанського календаря (високосний рік кожні чотири роки) до 1700 року, коли Григоріанський календар відходить від Юліанського. У ньому є два питання:

  1. Він приймає рік 0000, якого не існує у багатьох, але не у всіх стандартах. Зауважте, що ISO 8601 приймає рік 0000 (еквівалентно 1 BCE).
  2. Він не пропускає 10-13 днів, які були втрачені, коли Григоріанський календар увійшов у дію. Однак це залежить від місцевості. Наприклад, Римо-католицька церква пропустила 10 днів, з 5 по 14 жовтня 1582 р., Але Греція (остання, яка перейшла) пропустила 16 лютого по 28 лютого 1923 року, 13 днів, враховуючи високосні 1700 року, 1800 і 1900.

Це було перевірено на виконання календаря Java з року 0001 до 9999 року, єдиною невідповідністю було вищезгадані 10 днів 1582 року.


Зворотна таблиця "РРРРММДД" не відповідає [01 | 02 | 03 | 05 | 06 | 07 | 09 | 10 | 11 | 13 | 14 | 15] 00-02-29 Виправлено регулярний вираз: ^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048])00)[-/]?02[-/]?29)$. Тестований на python: repl.it/repls/DependentBestChapters
kpr

10

Для тих, хто дивиться на них і заплутається повністю, ось уривок з мого сценарію. На жаль, все, що це робиться, - це відповідність дійсних цифр у введенні часу дати, і 31 лютого буде позначено як дійсне, але, як так багато хто сказала, регулярно вираження не є найкращим інструментом для проведення цього тесту.

Щоб відповідати даті у форматі "yyyy-MM-dd hh: mm" (Або, в будь-якому порядку, будь ласка)

var dateerrors = false;
var yearReg = '(201[4-9]|202[0-9])';            ///< Allows a number between 2014 and 2029
var monthReg = '(0[1-9]|1[0-2])';               ///< Allows a number between 00 and 12
var dayReg = '(0[1-9]|1[0-9]|2[0-9]|3[0-1])';   ///< Allows a number between 00 and 31
var hourReg = '([0-1][0-9]|2[0-3])';            ///< Allows a number between 00 and 24
var minReg = '([0-5][0-9])';                    ///< Allows a number between 00 and 59
var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');
$('input').filter(function () {return this.id.match(/myhtml_element_with_id_\d+_datetime/);}).each(function (e) {
    if (e > 0) {
        // Don't test the first input. This will use the default
        var val = $(this).val();
        if (val && !val.trim().match(reg)) {
            dateerrors = true;
            return false;
        }
    }
});
if (dateerrors) {
    alert('You must enter a validate date in the format "yyyy-mm-dd HH:MM", e.g. 2019-12-31 19:30');
    return false;
}

Вищеописаний сценарій починається зі створення об'єкта регулярного вираження. Потім він знаходить усі входи, ідентифікатор яких відповідає певній схемі, а потім проходить цикл через них. Я не перевіряю перший вхід, який я знаходжу ( if (e > 0)).

Трохи пояснення:

var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');

^означає початок матчу, тоді як $означає закінчення матчу.

return this.id.match(/myhtml_element_with_id_\d+_datetime/);

\d+означає, що відповідають однаковій чи суміжній послідовності цілих чисел, тому myhtml_element_with_id_56_datetimeі myhtml_element_with_id_2_datetimeбудуть відповідати, але myhtml_element_with_id_5a_datetimeне будуть


8

Ось ще одна версія регулярного вираження, яка відповідає будь-якому з наступних форматів дати та дозволяє пропустити нульові нулі:

Regex: ^[0-3]?[0-9].[0-3]?[0-9].(?:[0-9]{2})?[0-9]{2}$

Матчі:

1/1/11 or 1.1.11 or 1-1-11 : true 01/01/11 or 01.01.11 or 01-01-11 : true 01/01/2011 or 01.01.2011 or 01-01-2011 : true 01/1/2011 or 01.1.2011 or 01-1-2011 : true 1/11/2011 or 1.11.2011 or 1-11-2011 : true 1/11/11 or 1.11.11 or 1-11-11 : true 11/1/11 or 11.1.11 or 11-1-11 : true

Регулярна візуалізація виразів

Демонстраційна демонстрація


4
не працює , якщо у вас є 13/13/2000= Схоже це вірно
Андрій Krasutski

3
39/39/39 - це не побачення. Будь ласка, припиніть голосувати за цю відповідь.
Warren Sergent

6

Тут я написав одне для того, dd/mm/yyyyде роздільником може бути один -.,/рік 0000-9999.

Він стосується високосних років і розроблений для ароматів регулярних виразів, що підтримують динаміки, захоплення груп і зворотній зв'язок. НЕ дійсний для таких як d/m/yyyy. Якщо потрібно, додайте додаткові роздільники до[-.,/]

^(?=\d{2}([-.,\/])\d{2}\1\d{4}$)(?:0[1-9]|1\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\d{4}$

Тест на регекс101 ; як рядок Java:

"^(?=\\d{2}([-.,\\/])\\d{2}\\1\\d{4}$)(?:0[1-9]|1\\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\\d{4}$"

пояснив:

(?x) # modifier x: free spacing mode (for comments)
     # verify date dd/mm/yyyy; possible separators: -.,/
     # valid year range: 0000-9999

^    # start anchor

# precheck xx-xx-xxxx,... add new separators here
(?=\d{2}([-.,\/])\d{2}\1\d{4}$)

(?:  # day-check: non caturing group

  # days 01-28
  0[1-9]|1\d|[2][0-8]| 

  # february 29d check for leap year: all 4y / 00 years: only each 400
  # 0400,0800,1200,1600,2000,...
  29
  (?!.02. # not if feb: if not ...
    (?!
      # 00 years: exclude !0 %400 years
      (?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)

      # 00,04,08,12,... 
      \d{2}(?:[02468][048]|[13579][26])
    )
  )|

  # d30 negative lookahead: february cannot have 30 days
  30(?!.02)|

  # d31 positive lookahead: month up to 31 days
  31(?=.(?:0[13578]|10|12))

) # eof day-check

# month 01-12
.(?:0[1-9]|1[012])

# year 0000-9999
.\d{4}

$ # end anchor

Також див. Поширені запитання щодо SO Regex ; Будь ласка, повідомте мене, якщо це не вдасться.


5

Знайшов р ех тут

^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$

Це правильно підтверджує формат mm/dd/yyyyта дійсні дати (але ні m/d/yyyy).

Деякі тести


1
Працює лише до 2014 року, потрібно змінити | 20 (0 [0-9] | 1 [0-4]))) на | 20 (0 [0-9] | 1 [0-9]))) для підтримки до 2019
Тоні Донг,


5

Наступним виразом приємно і легко маніпулювати:

((((0[13578]|1[02])(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)((\/|-|.)(0[1-9]|1[0-9]|2[0-8]))))(\/|-|.)(19([6-9][0-9])|20(0[0-9]|1[0-4])))|((02)(\/|-|.)(29)(\/|-|.)(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26])))

Він перевіряється відповідно до формату MM / dd / YYYY і дозволяє підтримувати високосний рік з 1960 по 2016 рік. Якщо вам потрібна розширена підтримка високосного року, вам потрібно лише маніпулювати цією частиною виразу:

(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]))

Сподіваюся, це вам дуже допомогло


3

Ще одна відповідь, яка підтверджує день (дд) залежно від місяця (мм) та року (рр. Рр.) (Тобто також підтверджує 29 лютого у високосні роки) та дозволяє проводити роки від 0001 до 9999 (0000 в недійсному році згідно з григоріанським) календар)

^(?:(?:(?:0[1-9]|[12]\d|3[01])/(?:0[13578]|1[02])|(?:0[1-9]|[12]\d|30)/(?:0[469]|11)|(?:0[1-9]|1\d|2[0-8])/02)/(?!0000)\d{4}|(?:(?:0[1-9]|[12]\d)/02/(?:(?!0000)(?:[02468][048]|[13579][26])00|(?!..00)\d{2}(?:[02468][048]|[13579][26]))))$

1
не підтверджується 18/05/0017

1

Я працюю з API, який приймає лише формат MM / DD / РРРР. Я не міг знайти жодної іншої публікації, яка б пройшла високосні роки, як і відповідь Офіра , тому я її переробив і перепублікував тут для всіх, хто може знадобитися.

/^(?:(?:(?:0[13578]|1[02])(\/)31)\1|(?:(?:0[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:02(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/

0
((((0[13578]|1[02])\/(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)\/(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)(\/(0[1-9]|1[0-9]|2[0-8]))))\/(19([6-9][0-9])|20([0-9][0-9])))|((02)\/(29)\/(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

буде підтверджувати MM/DD/YYYYформат 1960до2028

якщо вам потрібно продовжити підтримку високосного року, тоді додайте

19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048]|3[26]|4[048])))

це теж робота

^((((0[13578]|1[02])[/](0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)[/](0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)([/](0[1-9]|1[0-9]|2[0-8]))))[/](19([6-9][0-9])|20([0-9][0-9])))|((02)[/](29)[/](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

якщо ви можете змінити формат , mm-dd-yyyyніж замінити , [/]щоб [-] також перевірити онлайн http://regexr.com/


0

Для дати MM / DD / РРРР ви можете використовувати

^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$

Він перевіряє належні дні та молі.

Зауважте, що ви можете перевірити свій регулярний вираз на

regex101

що рекомендую :)

Веселіться!


0
^(((([13578]|0[13578]|1[02])[-](0[1-9]|[1-9]|1[0-9]|2[0-9]|3[01]))|(([469]|0[469]|11)[-]([1-9]|1[0-9]|2[0-9]|3[0]))|((2|02)([-](0[1-9]|1[0-9]|2[0-8]))))[-](19([6-9][0-9])|20([0-9][0-9])))|((02)[-](29)[-](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

цей регулярний вираз підтвердить дати у форматі:

12-30-2016 (мм-дд-р-р-р) або 12-3-2016 (мм-д-р-р-рг) або 1-3-2016 (м-д-р-р-рг) або 1-30-2016 (м-дд-р-р-р-р)


0

Я знаю, що це дотична відповідь на запитання, але якщо наміром питання є "як я підтверджую дату?", То чому б не спробувати дозволити мові програмування зробити всю важку роботу (якщо ви використовуєте мову, може)?

наприклад в php

$this_date_object = date_create($this_date);

if ($this_date_object == false )
    {

        // process the error

    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.