¿Cómo analizar una hora en un objeto Fecha a partir de la entrada del usuario en JavaScript?
Estoy trabajando en un widget de formulario para que los usuarios ingresen una hora del día en una entrada de texto (para una aplicación de calendario). Usando JavaScript (estamos usando jQuery FWIW), quiero encontrar la mejor manera de analizar el texto que el usuario ingresa en un Date()
objeto JavaScript para poder realizar comparaciones y otras cosas fácilmente.
Probé el parse()
método y es demasiado exigente para mis necesidades. Esperaría que pudiera analizar con éxito los siguientes ejemplos de horas de entrada (además de otros formatos de hora lógicamente similares) como el mismo Date()
objeto:
- 13:00
- 13:00
- 13:00
- 13:00
- 13:00.
- 1:00p.m.
- 13:00
- 13:00
- 1p
- 13:00
- 13:00 horas
- 1p
- 13:00
- 13
Estoy pensando que podría usar expresiones regulares para dividir la entrada y extraer la información que quiero usar para crear mi Date()
objeto. ¿Cuál es la mejor manera de hacer esto?
Una solución rápida que funciona con la entrada que ha especificado:
function parseTime( t ) {
var d = new Date();
var time = t.match( /(\d+)(?::(\d\d))?\s*(p?)/ );
d.setHours( parseInt( time[1]) + (time[3] ? 12 : 0) );
d.setMinutes( parseInt( time[2]) || 0 );
return d;
}
var tests = [
'1:00 pm','1:00 p.m.','1:00 p','1:00pm','1:00p.m.','1:00p','1 pm',
'1 p.m.','1 p','1pm','1p.m.', '1p', '13:00','13', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400',
'1000', '100', '123', '2459', '2359', '2359am', '1100', '123p',
'1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ];
for ( var i = 0; i < tests.length; i++ ) {
console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) );
}
También debería funcionar para algunas otras variedades (incluso si se usa am, seguirá funcionando, por ejemplo). Obviamente esto es bastante tosco pero también es bastante liviano (mucho más barato usarlo que una biblioteca completa, por ejemplo).
Advertencia: el código no funciona a las 12:00 a. m., etc.
Todos los ejemplos proporcionados no funcionan entre las 12:00 a. m. y las 0:59 a. m. También arrojan un error si la expresión regular no coincide con una hora. Lo siguiente maneja esto:
function parseTime(timeString) {
if (timeString == '') return null;
var time = timeString.match(/(\d+)(:(\d\d))?\s*(p?)/i);
if (time == null) return null;
var hours = parseInt(time[1],10);
if (hours == 12 && !time[4]) {
hours = 0;
}
else {
hours += (hours < 12 && time[4])? 12 : 0;
}
var d = new Date();
d.setHours(hours);
d.setMinutes(parseInt(time[3],10) || 0);
d.setSeconds(0, 0);
return d;
}
var tests = [
'1:00 pm','1:00 p.m.','1:00 p','1:00pm','1:00p.m.','1:00p','1 pm',
'1 p.m.','1 p','1pm','1p.m.', '1p', '13:00','13', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400',
'1000', '100', '123', '2459', '2359', '2359am', '1100', '123p',
'1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ];
for ( var i = 0; i < tests.length; i++ ) {
console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) );
}
Esto funcionará para cadenas que contengan una hora en cualquier lugar de su interior. Por lo tanto, "abcde12:00pmdef" se analizaría y devolvería las 12 p. m. Si el resultado deseado es que solo devuelve una hora cuando la cadena solo contiene una hora, se puede usar la siguiente expresión regular siempre que reemplace "hora[4]" con "hora[6]".
/^(\d+)(:(\d\d))?\s*((a|(p))m?)?$/i
No te molestes en hacerlo tú mismo, solo usa datejs .
Aquí hay una mejora en la versión de Joe . No dudes en editarlo más.
function parseTime(timeString)
{
if (timeString == '') return null;
var d = new Date();
var time = timeString.match(/(\d+)(:(\d\d))?\s*(p?)/i);
d.setHours( parseInt(time[1],10) + ( ( parseInt(time[1],10) < 12 && time[4] ) ? 12 : 0) );
d.setMinutes( parseInt(time[3],10) || 0 );
d.setSeconds(0, 0);
return d;
}
var tests = [
'1:00 pm','1:00 p.m.','1:00 p','1:00pm','1:00p.m.','1:00p','1 pm',
'1 p.m.','1 p','1pm','1p.m.', '1p', '13:00','13', '1a', '12', '12a', '12p', '12am', '12pm', '2400am', '2400pm', '2400',
'1000', '100', '123', '2459', '2359', '2359am', '1100', '123p',
'1234', '1', '9', '99', '999', '9999', '99999', '0000', '0011', '-1', 'mioaw' ];
for ( var i = 0; i < tests.length; i++ ) {
console.log( tests[i].padStart( 9, ' ' ) + " = " + parseTime(tests[i]) );
}
Cambios:
- Se agregó el parámetro radix a las llamadas parseInt() (para que jslint no se queje).
- Se hizo que la expresión regular no distinga entre mayúsculas y minúsculas para que "2:23 p. m." funcione como "2:23 p. m."