Hay dos cosas que desea hacer, que en mi la vista se considera mejor por separado
1) Desea asegurarse de que la fecha sea real y real. Por ejemplo, el 2019-02-29 no es una fecha real, mientras que 2020-02-29 es una fecha real porque 2020 es un año bisiesto
2) Desea verificar que la fecha esté en el formato correcto (tan dd/mm/aaaa)
El segundo punto se puede hacer con bastante facilidad con un simple RegEx, muchos ejemplos de eso.
Para complicar las cosas, si le preguntas a Firefox si 2019-02-29 es una fecha real, devolverá NaN, que es lo que esperas.
Chrome, por otra parte, se dice que es una cita de verdad y le devolverá el 1 de marzo 2019 - que validará
Chrome, será también aceptar un número de un solo dígito como una fecha adecuada también para algunos Por alguna extraña razón, aliméntelo "2" y le dará la fecha completa del 2001 - que validará
El primer paso es crear una función que intente descifrar una fecha (sin importar el formato) y funciona -browser para devolver un valor booleano que indique si la fecha es válida o no
function validatableDate(value)
{
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();
};
minTwoDigits = function(n)
{ //pads any digit less than 10 with a leading 0
return (parseInt(n) < 10 ? '0' : '') + parseInt(n);
}
var valid_date = false;
var iso_array = null;
// check if there are date dividers (gets around chrome allowing single digit numbers)
if ((value.indexOf('/') != -1) || (value.indexOf('-') != -1)) { //if we're dealing with - dividers we'll do some pre-processing and swap them out for/
if (value.indexOf('-') != -1) {
dash_parts = value.split('-');
value = dash_parts.join("/");
//if we have a leading year, we'll put it at the end and work things out from there
if (dash_parts[0].length > 2) {
value = dash_parts[1] + '/' + dash_parts[2] + '/' + dash_parts[0];
}
}
parts = value.split('/');
if (parts[0] > 12) { //convert to ISO from UK dd/mm/yyyy format
iso_array = [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])]
} else if (parts[1] > 12) { //convert to ISO from American mm/dd/yyyy format
iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
} else //if a date is valid in either UK or US (e.g. 12/12/2017 , 10/10/2017) then we don't particularly care what format it is in - it's valid regardless
{
iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
}
if (Array.isArray(iso_array)) {
value = iso_array.join("-");
var d = new Date(value + 'T00:00:01Z');
if (d.isValid()) //test if it is a valid date (there are issues with this in Chrome with Feb)
{
valid_date = true;
}
//if the month is Feb we need to do another step to cope with Chrome peculiarities
if (parseInt(iso_array[1]) == 2) {
month_info = new Date(iso_array[0], iso_array[1], 0);
//if the day inputed is larger than the last day of the February in that year
if (iso_array[2] > month_info.getDate()) {
valid_date = false;
}
}
}
}
return valid_date;
}
que puede ser comprimido hasta
function validatableDate(t) {
Date.prototype.isValid = function() {
return this.getTime() === this.getTime()
}, minTwoDigits = function (t) {
return (parseInt(t) < 10 ? "0" : "") + parseInt(t)
};
var a = !1,
i = null;
return -1 == t.indexOf("/") && -1 == t.indexOf("-") || (-1 != t.indexOf("-") && (dash_parts = t.split("-"), t = dash_parts.join("/"), dash_parts[0].length > 2 && (t = dash_parts[1] + "/" + dash_parts[2] + "/" + dash_parts[0])), parts = t.split("/"), i = parts[0] > 12 ? [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])] : (parts[1], [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]), Array.isArray(i) && (t = i.join("-"), new Date(t + "T00:00:01Z").isValid() && (a = !0), 2 == parseInt(i[1]) && (month_info = new Date(i[0], i[1], 0), i[2] > month_info.getDate() && (a = !1)))), a
}
que le consigue una prueba de cross-browser en cuanto a si la fecha se puede validar o no, y que va a leer & descifrar las fechas en formatos
- aaaa -mm-dd
- dd-mm-aaaa
- mm-dd-aaaa
- dd/mm/aaaa
- mm/dd/aaaa
Una vez que hayas confirmado que la fecha es verdadera, puedes probar el formato con una expresión regular. Así que para el Reino Unido dd/mm/aa
function dateUK(value) {
valid_uk_date=false;
valid_date=validatableDate(value);
if(valid_date && value.match(/^(0?[1-9]|[12][0-9]|3[01])[\/](0?[1-9]|1[012])[\/]\d{4}$/))
{ valid_uk_date=true;
}
return valid_uk_date;
}
A continuación, sabe que la fecha es real y que es en el formato correcto.
Para el formato aaaa-mm-dd, que haría:
function dateISO(value) {
valid_iso_date=false;
valid_date=validatableDate(value);
if(valid_date && value.match(/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/))
{ valid_iso_date=true;
}
return valid_iso_date;
}
Depende de lo profundo que desea ser, por supuesto, para una verificación aproximada del formato de la cordura una expresión regular puede ser suficiente para sus propósitos . Sin embargo, si desea probar si la fecha es real y si el formato es válido, entonces esto se espera ayude a punto de que en el camino
Gracias
qué idioma es esto? – codaddict
@codaddict, las expresiones regulares son de lenguaje neutral en su mayor parte. –
Muchos lenguajes de programación tienen funciones perfectas para analizar la fecha en cualquier formato y ocuparse de la cantidad de días en un mes, años bisiestos, etc. – eumiro