How to Formulate Pattern to Limit Date

Asked

Viewed 164 times

2

I am developing a site where the user needs to search for routes of drivers of capacity, and in this research I want to limit the dates that he can use for example, at least the current day and at most 2 years ahead.

I know I can use "Pattern" to specify, but so far what I can do with this feature is:

pattern="\d{1,2}/\d{1,2}/\d{4}"

But that’s not enough.

Another problem I’m facing is when are the <input type="date"> which are the standard HTML mask type, but which has a very boring flaw.

First it works perfectly the first two parts which are from dd/mm but the third part that is the year it does not work right, instead of limiting to 4 digits, ie, 12/12/2000, It allows 6 digits in year type 12/12/200000 and I don’t know how to fix it, because in the fields I leave like text the mask works perfectly, but in this type date can’t.

inserir a descrição da imagem aqui

I no longer know what to do because use the field "type="text" with mask is not quite what I wanted for the performance of the site.

2 answers

2


In a input type="date", it is possible to limit the minimum and maximum values. For example, to accept only 4-digit years, you can set the maximum value to 31 December 9999 (remembering that the date must be in the format set by ISO 8601 standard):

<input type="date" max="9999-12-31" name="data">


But in question it is said that one wants "at least the current day and at most 2 years ahead". So the minimum and maximum values are dynamic, so you should set them via Javascript. Ex:

function pad(valor) { // completa com zeros à esquerda, caso necessário
    return valor.toString().padStart(2, '0');
}

function formata(data) {
    return `${data.getFullYear()}-${pad(data.getMonth() + 1)}-${pad(data.getDate())}`;
}

const campo = document.querySelector('#campoData');

window.addEventListener('DOMContentLoaded', function() {
    var data = new Date(); // data de hoje
    campo.min = formata(data);
    // 2 anos à frente
    data.setFullYear(data.getFullYear() + 2);
    campo.max = formata(data);
});

// mensagens de validação
campo.addEventListener('input', () => {
  campo.setCustomValidity('');
  campo.checkValidity();
});

// se tentar submeter o form com data fora do intervalo, mostra o erro
campo.addEventListener('invalid', () => {
    campo.setCustomValidity('A data deve estar entre hoje e 2 anos à frente');
});
/* deixar borda vermelha enquanto o campo for inválido */
input:invalid {
    border: red 1px solid;
}
<form>
  <input id="campoData" type="date" name="data">
  <input type="submit" value="ok">
</form>

According to the documentation, values should always be set in the already mentioned ISO 8601 format ("yyyy-mm-dd"), so I created the functions to assist in formatting.

Then I set the minimum and maximum values according to the given rules (minimum = current date, maximum = current date + 2 years).


Important detail: the behavior of input type="date" is dependent on the browser. Many show a calendar when you click the field - for example, Chrome looks like this:

calendário quando você clica no input type=date

Note that dates prior to today are faded and nothing happens if you click on them.

But nothing prevents you from typhoon an invalid date directly in the field. So in the above example I added a CSS to make the border red if the value is invalid (just so you can see that the browser detects when the value is outside the established limits), and does not leave the form be submitted (type a date outside the allowed range and then try to click "ok").

But of course this more "visual" part would only help the user because you should also validate the date received on the server.


Finally, do not use regex for this. Regex basically handles text (same digits as 1 and 2 are treated as mere characters), so making numerical comparisons (how to know if the year is between the current and 2 years ahead) is quite complicated and not worth it (just to quote an example, see here how regex can end up getting very complicated if you really want to validate any possible date).

  • I believe that solves my problem temporarily. Thanks for the help, this validation is very complex for my Javascript level, so I get a little lost with some things.

  • @Gildevanpereira If the answer solved your problem, you can accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. Don’t forget that you can also vote in response, if it has found it useful.

  • @Gildevanpereira Anyway, if the minimum and maximum values are dynamic (vary according to the current date), there is not much to escape from Javascript :-)

  • This code helped me a lot but now as I do to use this code for the return date field?

1

Some things are missing in the Pattern you are using, first the character / need escape to work properly, another point is that you need to indicate that your string should contain only these characters, from start to finish. I did some tests and I got this result:

const pattern = /^\d{1,2}\/\d{1,2}\/\d{4}$/

pattern.test("07/02/2021") // true
pattern.test("08/02/20202112") // false

Basically the character ^ indicates the beginning of the line, while the character $ indicates the end of the line, so you can ensure that your string will contain only characters that meet the informed rule.

NOTE: This patern will not validate cases like 07/13/2020 or 40/20/4500, such entries shall be deemed to be valid.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.