MaskedDateField
El MaskedDateField es un campo de texto que permite a los usuarios ingresar fechas como números y formatea automáticamente la entrada según una máscara definida cuando el campo pierde el foco. La máscara especifica el formato de fecha esperado, guiando tanto la entrada como la visualización. El componente admite un análisis flexible, validación, localización y restauración de valores para un manejo de fechas consistente y específico de la región.
Básicos
El MaskedDateField se centra exclusivamente en valores de fecha. Si necesitas un componente similar para ingresar y formatear hora, consulta el MaskedTimeField en su lugar.
El MaskedDateField se puede instanciar con o sin parámetros. Puedes definir un valor inicial, una etiqueta, un marcador de posición y un oyente de eventos para los cambios de valor.
Mostrar Código
- MaskedDateFieldView.java
Reglas de máscara
El MaskedDateField admite múltiples formatos de fecha utilizados alrededor del mundo, que varían por el orden de día, mes y año. Los patrones comunes incluyen:
- Día/Mes/Año (utilizado en la mayor parte de Europa)
- Mes/Día/Año (utilizado en los Estados Unidos)
- Año/Mes/Día (utilizado en China, Japón y Corea; también el estándar ISO:
YYYY-MM-DD)
Dentro de estos formatos, las variaciones locales incluyen la elección del separador (por ejemplo, -, /, o .), si los años son de dos o cuatro dígitos, y si los meses o días de un solo dígito están rellenos con ceros a la izquierda.
Para manejar esta diversidad, el MaskedDateField utiliza indicadores de formato, cada uno comenzando con %, seguido de una letra que representa una parte específica de la fecha. Estos indicadores definen cómo se analiza la entrada y cómo se muestra la fecha.
Para formatear o analizar fechas con la misma sintaxis de máscara fuera de un campo, utiliza la clase utilitaria MaskDecorator.
Indicadores de formato de fecha
| Formato | Descripción |
|---|---|
%Y | Año |
%M | Mes |
%D | Día |
Modificadores
Los modificadores permiten un mayor control sobre cómo se formatean los componentes de la fecha:
| Modificador | Descripción |
|---|---|
z | Rellenar con ceros |
s | Representación de texto corto |
l | Representación de texto largo |
p | Número empaquetado |
d | Decimal (formato predeterminado) |
Estos pueden combinarse para construir una amplia variedad de máscaras de fecha.
Localización del formato de fecha
El MaskedDateField se adapta a los formatos de fecha regionales configurando la localidad adecuada. Esto asegura que las fechas se visualicen y analicen de una manera que coincida con las expectativas del usuario.
| Región | Formato | Ejemplo |
|---|---|---|
| Estados Unidos | MM/DD/YYYY | 07/04/2023 |
| Europa | DD/MM/YYYY | 04/07/2023 |
| Estándar ISO | YYYY-MM-DD | 2023-07-04 |
Para aplicar la localización, utiliza el método setLocale(). Este acepta un java.util.Locale y ajusta automáticamente tanto el formato como el análisis:
dateField.setLocale(Locale.FRANCE);
Lógica de análisis
El MaskedDateField analiza la entrada del usuario basándose en la máscara de fecha definida. Acepta tanto entradas numéricas completas como abreviadas con o sin delimitadores, permitiendo una entrada flexible mientras asegura la validez de las fechas.
El comportamiento de análisis depende del orden de formato definido por la máscara (por ejemplo, %Mz/%Dz/%Yz para mes/día/año). Este formato determina cómo se interpretan las secuencias numéricas.
Por ejemplo, supongamos que hoy es 15 de septiembre de 2012, así sería como se interpretarían varias entradas:
Ejemplos de escenarios de análisis
| Entrada | YMD (ISO) | MDY (US) | DMY (EU) |
|---|---|---|---|
1 | Un solo dígito siempre se interpreta como un número de día dentro del mes actual, por lo que esto sería el 1 de septiembre de 2012. | Lo mismo que YMD | Lo mismo que YMD |
12 | Dos dígitos siempre se interpretan como un número de día dentro del mes actual, por lo que esto sería el 12 de septiembre de 2012. | Lo mismo que YMD | Lo mismo que YMD |
112 | Tres dígitos se interpretan como un número de mes de 1 dígito seguido de un número de día de 2 dígitos, por lo que esto sería el 12 de enero de 2012. | Lo mismo que YMD | Tres dígitos se interpretan como un número de día de 1 dígito seguido de un número de mes de 2 dígitos, por lo que esto sería el 1 de diciembre de 2012. |
1004 | Cuatro dígitos se interpretan como MMDD, por lo que esto sería el 4 de octubre de 2012. | Lo mismo que YMD | Cuatro dígitos se interpretan como DDMM, por lo que esto sería el 10 de abril de 2012. |
020304 | Seis dígitos se interpretan como YYMMDD, por lo que esto sería el 4 de marzo de 2002. | Seis dígitos se interpretan como MMDDYY, por lo que esto sería el 3 de febrero de 2004. | Seis dígitos se interpretan como DDMMYY, por lo que esto sería el 2 de marzo de 2004. |
8 digits | Ocho dígitos se interpretan como YYYYMMDD. Por ejemplo, 20040612 es el 12 de junio de 2004. | Ocho dígitos se interpretan como MMDDYYYY. Por ejemplo, 06122004 es el 12 de junio de 2004. | Ocho dígitos se interpretan como DDMMYYYY. Por ejemplo, 06122004 es el 6 de diciembre de 2004. |
12/6 | Dos números separados por cualquier delimitador válido se interpretan como MM/DD, por lo que esto sería el 6 de diciembre de 2012. Nota: Todos los caracteres excepto letras y dígitos se consideran delimitadores válidos. | Lo mismo que YMD | Dos números separados por cualquier delimitador se interpretan como DD/MM, por lo que esto sería el 12 de junio de 2012. |
3/4/5 | 5 de abril de 2012 | 4 de marzo de 2005 | 3 de abril de 2005 |
Análisis de fechas textuales 25.11
Por defecto, el MaskedDateField solo acepta entradas numéricas para fechas. Sin embargo, puedes habilitar el análisis de fechas textuales para permitir a los usuarios introducir nombres de meses y días en su entrada. Esta función es particularmente útil para crear una entrada de fecha más natural.
Para habilitar el análisis textual, utiliza el método setTextualDateParsing():
dateField.setTextualDateParsing(true);
Sustitución de nombres de meses
Cuando se habilita el análisis textual, puedes usar modificadores especiales en tu máscara para aceptar nombres de meses en lugar de valores numéricos:
%Ms- Acepta nombres de meses cortos (Ene, Feb, Mar, etc.)%Ml- Acepta nombres de meses largos (Enero, Febrero, Marzo, etc.)
Los nombres de meses pueden aparecer en cualquier posición dentro de la máscara, y el campo seguirá aceptando entradas numéricas como respaldo.
Ejemplos
| Máscara | Entrada | Resultado |
|---|---|---|
%Ms/%Dz/%Yz | Sep/01/25 | Válido - Se analiza como 1 de septiembre de 2025 |
%Ml/%Dz/%Yz | Septiembre/01/25 | Válido - Se analiza como 1 de septiembre de 2025 |
%Dz/%Ml/%Yz | 01/Septiembre/25 | Válido - Se analiza como 1 de septiembre de 2025 |
%Mz/%Dz/%Yz | 09/01/25 | Válido - El respaldo numérico aún funciona |
Los 12 meses están soportados en ambos formatos, corto (Ene, Feb, Mar, Abr, May, Jun, Jul, Ago, Sep, Oct, Nov, Dic) y largo (Enero, Febrero, etc.).
Decoración del nombre del día
Los nombres de los días de la semana pueden incluirse en la entrada para una mejor legibilidad, pero son decorativos solamente y se eliminan durante el análisis. No afectan el valor real de la fecha.
%Ds- Acepta nombres de días cortos (Lun, Mar, Mié, etc.)%Dl- Acepta nombres de días largos (Lunes, Martes, Miércoles, etc.)
Al utilizar nombres de días de la semana (%Ds o %Dl), tu máscara también debe incluir %Dz o %Dd para especificar el número real del día. Sin un componente de día numérico, la entrada será inválida.
Ejemplos
| Máscara | Entrada | Resultado |
|---|---|---|
%Ds %Mz/%Dz/%Yz | Lun 09/01/25 | Válido - El nombre del día es decorativo |
%Dl %Mz/%Dz/%Yz | Lunes 09/01/25 | Válido - El nombre del día es decorativo |
%Mz/%Dz/%Yz %Ds | 09/01/25 Mar | Válido - El nombre del día al final |
%Dl/%Mz/%Yz | Lunes/09/25 | Inválido - Falta %Dz |
%Mz/%Dl/%Yz | 09/Lunes/25 | Inválido - Falta %Dz |
Todos los 7 días de la semana están soportados en ambos formatos, corto (Lun, Mar, Mié, Jue, Vie, Sab, Dom) y largo (Lunes, Martes, etc.).
Reglas adicionales de análisis
El análisis de fechas textuales incluye varias funciones útiles:
- No es sensible a mayúsculas: Entradas como
LUNES 09/01/25,lunes 09/01/25, oLunes 09/01/25funcionan de la misma manera. - Consciente de la localidad: Los nombres de meses y días deben coincidir con la localidad configurada del campo. Por ejemplo, con una localidad francesa, utiliza
septembre, noSeptember. Los nombres en inglés no serán reconocidos a menos que la localidad esté configurada en inglés.- Localidad francesa:
septembre/01/25es reconocido como septiembre - Localidad alemana:
Montag 09/01/25es reconocido con lunes como el nombre del día
- Localidad francesa:
Estableciendo restricciones mínimas/máximas
Puedes restringir el rango de fechas permitidas en un MaskedDateField utilizando los métodos setMin() y setMax():
dateField.setMin(LocalDate.of(2020, 1, 1));
dateField.setMax(LocalDate.of(2030, 12, 31));
Ambos métodos aceptan valores de tipo java.time.LocalDate. La entrada fuera del rango definido se considerará inválida.
Restaurando el valor
El MaskedDateField incluye una función de restauración que reinicia el valor del campo a un estado predefinido u original. Esto es útil para revertir la entrada del usuario o restablecer a una fecha predeterminada.
dateField.setRestoreValue(LocalDate.of(2025, 1, 1));
dateField.restoreValue();
Formas de restaurar el valor
- Programáticamente, llamando a
restoreValue() - A través del teclado, presionando ESC (esta es la tecla de restauración predeterminada a menos que se sobrescriba por un oyente de eventos)
Puedes establecer el valor para restaurar con setRestoreValue(), pasando una instancia de LocalDate.
Mostrar Código
- MaskedDateFieldRestoreView.java
Patrones de validación
Puedes aplicar reglas de validación del lado del cliente usando expresiones regulares con el método setPattern():
dateField.setPattern("^\\d{2}/\\d{2}/\\d{4}$");
Este patrón asegura que solo se consideren válidos los valores que coinciden con el formato MM/DD/YYYY (dos dígitos, barra, dos dígitos, barra, cuatro dígitos).
El patrón debe seguir la sintaxis de RegExp de JavaScript como se documenta aquí.
El campo intenta analizar y formatear entradas de fechas numéricas basadas en la máscara actual. Sin embargo, los usuarios aún pueden ingresar manualmente valores que no coinciden con el formato esperado. Si la entrada es sintácticamente válida pero semánticamente incorrecta o no analizable (por ejemplo, 99/99/9999), puede pasar las verificaciones de patrón pero fallar en la validación lógica.
Siempre debes validar el valor de entrada en la lógica de tu aplicación, incluso si se establece un patrón de expresión regular, para asegurar que la fecha esté correctamente formateada y sea significativa.
Selector de fecha
El MaskedDateField incluye un selector de calendario integrado que permite a los usuarios seleccionar una fecha visualmente, en lugar de escribirla. Esto mejora la usabilidad para usuarios menos técnicos o cuando se requiere entrada precisa.
Mostrar Código
- MaskedDateFieldPickerView.java
Accediendo al selector
Puedes acceder al selector de fechas usando getPicker():
DatePicker picker = dateField.getPicker();
Mostrar/ocultar el icono del selector
Utiliza setIconVisible() para mostrar u ocultar el icono del calendario junto al campo:
picker.setIconVisible(true); // muestra el icono
Comportamiento de apertura automática
Puedes configurar el selector para que se abra automáticamente cuando el usuario interactúa con el campo (por ejemplo, clic, presiona Enter o teclas de flecha):
picker.setAutoOpen(true);
Para asegurar que los usuarios solo puedan seleccionar una fecha mediante el selector de calendario (y no escribirla manualmente), combina las siguientes dos configuraciones:
dateField.getPicker().setAutoOpen(true); // Abre el selector en la interacción del usuario
dateField.setAllowCustomValue(false); // Desactiva la entrada de texto manual
Esta configuración garantiza que toda la entrada de fecha provenga de la interfaz del selector, lo que es útil cuando deseas un control estricto sobre el formato y eliminar problemas de análisis de entradas escritas.
Abrir manualmente el calendario
Para abrir el calendario programáticamente:
picker.open();
O usa el alias:
picker.show(); // igual que open()
Mostrar semanas en el calendario
El selector puede mostrar opcionalmente números de semana en la vista del calendario:
picker.setShowWeeks(true);
MaskedDateFieldSpinner
El MaskedDateFieldSpinner extiende MaskedDateField al añadir controles de spinner que permiten a los usuarios aumentar o disminuir la fecha usando teclas de flecha o botones de la interfaz. Proporciona un estilo de interacción más guiado, especialmente útil en aplicaciones de estilo de escritorio.
Mostrar Código
- MaskedDateFieldSpinnerView.java
Características clave
-
Paso de Fecha Interactivo: Utiliza teclas de flecha o botones de giro para aumentar o disminuir el valor de la fecha.
-
Unidad de Paso Personalizable: Elige qué parte de la fecha modificar usando
setSpinField():spinner.setSpinField(MaskedDateFieldSpinner.SpinField.MONTH);Las opciones incluyen
DAY,WEEK,MONTH, yYEAR. -
Fronteras Mínimas/Máximas: Hereda soporte para las fechas mínimas y máximas permitidas usando
setMin()ysetMax(). -
Salida Formateada: Totalmente compatible con las máscaras y configuraciones de localización del
MaskedDateField.
Ejemplo: Configurar el paso semanal
MaskedDateFieldSpinner spinner = new MaskedDateFieldSpinner();
spinner.setSpinField(MaskedDateFieldSpinner.SpinField.WEEK);
Esto hace que cada paso de giro avance o retroceda la fecha en una semana.