Регулярные выражения для дат в Javascript

123
04 декабря 2020, 08:20

Задача Есть инпут, который принимает текст в формате дате в виде ДД.ММ.ГГГГ Есть регулрка для проверки соответствия

var reg = /^\d{1,2}\.\d{1,2}\.\d{4}$/
var inval = input.value;

Чтобы взять день даты, использую регулярку

var day = parseInt(inval.match(/^\d{1,2}/));

Чтобы взять год, использую регулярку

  var year = parseInt(inval.match(/\d{4}$/));

Не получается взять месяц. Регулярка ниже не работает

var month = parseInt(inval.match(/.+\d{1,2}.+/));
Answer 1

Регулярное выражение для проверки даты, которое бы учитывало корректность месяца, даты и года, будет выглядеть сложно.
Поэтому я предлагаю для начала просто проверить на наличие цифр, а затем уже можно проверить значения месяца, даты и года. В любом случае Вы можете просто использовать приведённое регулярное выражение:

var $ = function(id){ return document.getElementById(id); }, 
minYear = 1900, maxYear = 2100, 
// Месяц и дата без ведущих нулей 
// regex = new RegExp("^([1-9][0-9]?)\\.([1-9][0-9]?)\\.([1-2][0-9]{3})$"), 
// Месяц и дата с ведущими нулями 
regex = new RegExp("^([0-9]{2})\\.([0-9]{2})\\.([1-2][0-9]{3})$"); 
 
$('run').addEventListener('click', function(){ 
 
  let inp = $("input").value; 
  if(inp === ""){ 
    $("output").value = "Input is empty"; 
    return; 
  } 
   
  if(regex.test(inp) === false){ 
    $("output").value = inp + ": RegExp check fail"; 
    return; 
  } 
  var reRes = regex.exec(inp), 
      year = parseInt(reRes[3], 10), 
      month = parseInt(reRes[2], 10) - 1, 
      day = parseInt(reRes[1], 10); 
  if(day > 31 || month > 12 || year > maxYear || year < minYear) { 
    $("output").value = "Date format error"; 
    return; 
  } 
  var date = new Date(year, month, day); 
  $("output").value = date.toLocaleString(); 
}, false);
<p>Input</p> 
<input id="input" value="12.12.2019" /> 
<p>Output</p> 
<textarea id="output" cols="100" rows="4"></textarea> 
<p><button id="run">Run</button></p>

Ссылки по теме

  • Регулярные выражения на MDN
  • Онлайн сервис для тестирования RegExp
  • input type="date"
  • поддержка браузерами типа date в input
Answer 2

Для работы с датами удобно использовать moment.js.

Если по-вашему, то каждое число из строки можно взять так: var date = "09.05.2019" [day, month, year] = date.split('.')

Answer 3

Для решения использовал exec();

var inval = input.value;
var regArr = reg.exec(inval);
var day = Number(regArr[1]) // Получаем день;
var month = Number(regArr[2]) // Получаем месяц;
var year = Number(regArr[3]) // Получаем год;
Answer 4

Регулярка для формата d-M-yyyy с разрешённым необязательным лидирующим нулём у дня и месяца, корректно учитывающая длительность месяцев в том числе в високосные годы:

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

Правда написана 6 лет назад, сейчас я бы лучше написал, наверное :)

Код для проверки на VB.NET:

Imports System.Text.RegularExpressions
Module All
Public ReadOnly DateRegex As New Regex("^((((0?[1-9]-(0?[1-9]|1[0-2]))|([12][0-9]-((0?[13-9])|1[0-2]))|(((1[0-9])|(2[0-8]))-0?2)|(30-((0?[13-9])|1[0-2]))|(31-((0?[13578])|10|12)))-[0-9]{4})|(29-0?2-(([0-9]{2}((0[48])|([2468][048])|([13579][26])))|((([02468][048])|([13579][26]))00))))$")
Private Sub Test(Sample As String)
  Console.Write("{0}     ", Sample)
  Dim Temp As Date
  Dim RegexRes As Boolean = DateRegex.IsMatch(Sample)
  Dim ParseRes As Boolean = Date.TryParseExact(Sample, "d-M-yyyy", Nothing, Globalization.DateTimeStyles.None, Temp)
  If RegexRes = ParseRes Then
    Console.CursorLeft = 0
  Else
    Console.WriteLine(" - Error: {0} instead of {1}: {2}", RegexRes, ParseRes, Temp.ToString("d-M-yyyy"))
  End If
End Sub
Sub Main()
  Dim Start As Date, Finish As Date
  Start = Now()
  Console.WriteLine(Start.ToString("'started:  'yyyy_MM_dd HH_mm_ss"))
  For Y As Integer = 1 To 9999
    For M As Integer = 0 To 99
      For D As Integer = 0 To 99
        Test(String.Format("{0}-{1}-{2,4:0000}", D, M, Y))
      Next D
      For D As Integer = 0 To 9
        Test(String.Format("{0,2:00}-{1}-{2,4:0000}", D, M, Y))
      Next D
    Next M
    For M As Integer = 0 To 9
      For D As Integer = 0 To 99
        Test(String.Format("{0}-{1,2:00}-{2,4:0000}", D, M, Y))
      Next D
      For D As Integer = 0 To 9
        Test(String.Format("{0,2:00}-{1,2:00}-{2,4:0000}", D, M, Y))
      Next D
    Next M
  Next Y
  Finish = Now()
  Console.WriteLine(Finish.ToString("'finished: 'yyyy_MM_dd HH_mm_ss"))
  Console.WriteLine("time:     {0}", Finish - Start)
  Console.ReadKey()
End Sub
End Module

PS: Дефис на точку заменить легко, просто не стал, чтоб не накосячить в ответе.

READ ALSO
Отловить событие перед загрузкой html

Отловить событие перед загрузкой html

Делаю 2 типа менюКакое из них загрузится пользователю решается с помощью js относительно ширины экрана

121
Изменить значение cookie по второму клику

Изменить значение cookie по второму клику

Как изменить значение cookie по второму клику по элементу?

93
Нужно составить регулярное выражение

Нужно составить регулярное выражение

Есть <input type="text"/> Хочу добавить в атрибут pattern регулярное выражение, чтоб можно было вводить только цифры и можно было указать минимальное...

116