java - español - primefaces calendar validation
Restringir mutuamente las fechas de inicio y finalización usando p: calendario(sin validación) (1)
Prefacio:
No trabajo con JSF, pero hay un par de cosas que pueden llevarte de vuelta a donde quieres estar:
a) cuando trabaje solo con la parte de fecha de una fecha y hora en un calendario estándar , considere usar:
someCalendar.set(Calendar.MILLISECOND, 0)
b) considere usar joda-time , ya que parece ser frecuentemente recomendado ( here , here y en muchos otros lugares ) sobre la biblioteca estándar para la corrección, el rendimiento y la facilidad de uso en muchas situaciones.
c) Asegúrate de que tu alcance de bean sobreviva a cada llamada ajax (no redirecciona, solo envía FacesContext facesContext = FacesContext.getCurrentInstance();
estándar, etc.) y cada controlador de eventos obtiene el contexto de las caras (por ejemplo, FacesContext facesContext = FacesContext.getCurrentInstance();
)
d) mindate
y similares probablemente no funcionen como esperabas, y no espero que el comportamiento automático se interrumpa tan fácilmente.
Cuando esas opciones no están disponibles, y usted tiene que hacerlo todo usted mismo con lo que tiene:
Philisophical / UX: Lo primero que haría es eliminar la expectativa de acuerdo o perspectiva del par de fechas. No trate al par como un vector que expone o espera una dirección en la línea de tiempo.
En otras palabras, ¿un
start
o una fecha siempre es menor o anterior a unend
oto
fecha? No, como se puede ver para una consulta de datos históricos, o para aplicar correcciones a eventos que aún tienen que suceder o que ya han sucedido.Esta connotación puede confundir fácilmente a un usuario en cuanto a si van a ''volver a'' o ''reenviar'' (y pueden confundirse fácilmente). En su lugar, trataría un par de fechas con un período de tiempo entre ellas como simplemente y simplemente
a pair of dates
o unrange
o unperiod
que declara un intervalo, e inferiría su posición relativa en la línea de tiempo según los valores consecuentemente elegidos. . De esta manera, puede cumplir los requisitos respectivos e inherentes de que las fechas nunca sean iguales, y la izquierda siempre está a la izquierda, la derecha siempre a la derecha.
No podemos inferir qué significa ''comenzar'' o ''de'', pero podemos inferir algún significado y relación relativa: un derecho, una izquierda y un entre en una línea de tiempo cronológica. Nota: Siempre resuelva las fechas en UTC antes de hacer cualquier cálculo o comparación.
long oneDateValue = oneDate.toUtc().toMilliseconds();
long anotherDateValue = anotherDate.toUtc().toMilliseconds();
long right = max (oneDateValue, anotherDateValue);
long left = min (oneDateValue, anotherDateValue);
Evaluación de la precisión: la segunda cosa que consideraría cuando trabaje con un rango de fechas en cualquier idioma es similar a cómo podría tratar con los números de coma flotante. Para las comparaciones, no compare por igualdad, sino que compare el delta con un "nivel de error aceptable". En otras palabras, la aplicación realmente solo se preocupa por un cierto grado de precisión, por lo que debe asegurarse de que solo se capture y considere esa precisión:
const int dateTimeResolutionInMs = 86400000; // milliseconds per day
public bool areEssentiallySame(long left, long right) {
// the difference between right and left is less than our precision
// requires, thus dates are effectively the same
return (right - left < dateTimeResolutionInMs);
}
Precisión de Coercing: En tercer lugar, ¿cómo resolvemos la diferencia en los valores, incluso si está dentro del rango de la resolución? (A la aplicación se le dio más precisión de la que puede manejar, esperar o necesitar).
long diff = value % dateTimeResolutionInMs;
Truncar:
return value - diff;
Nearest (w / bias):
return value + (diff < dateTimeResolutionInMs/ 2) ? -1 * diff : dateTimeResolutionInMs - diff;
return value + (diff < dateTimeResolutionInMs/ 2) ? -1 * diff : dateTimeResolutionInMs - diff;
Otros: hay muchas otras estrategias para reducir o expandir un valor a una resolución preferida o precisión
Adición: en cuanto a recibir llamadas post-backs / Ajax para devolver una vista con los valores que espera para los eventos activados por un elemento de calendar
, es posible que desee separar esa preocupación en una nueva pregunta si la nota en el prefacio no lo hizo Te llevo a cualquier parte, y sabes con certeza que tu frijol está debidamente registrado y reconocido. Es posible que tenga algunos problemas específicos de la versión del navegador / navegador que contribuyen al comportamiento no deseado, y como todo lo demás, existen problemas, tanto conocidos como desconocidos.
Tenemos el requisito de presentar dos p: componentes de calendario para el usuario, que representan una fecha de inicio y otra de finalización. Ambas fechas tienen fechas, horas y minutos. PrimeFaces tiene los mindate
perfectos mindate
, maxdate
, minHour
, maxHour
, minMinute
y minMinute
disponibles.
El requisito ahora es:
Es imposible establecer el datetime de inicio a cualquier cantidad mayor o igual que el datetime final. Es imposible establecer el fin de la fecha y hora en nada menos que o igual al final de la fecha y hora.
La siguiente ecuación debe ser verdadera:
begin datetime < end datetime
Ahora probamos el siguiente JSF:
<p:calendar id="begin-date"
value="#{debugManager.selectedBeginDate}"
mindate="#{debugManager.minBeginDate}"
maxdate="#{debugManager.maxBeginDate}"
maxHour="#{debugManager.maxBeginHour}"
maxMinute="#{debugManager.maxBeginMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button"
required="true">
<p:ajax event="dateSelect" update="end-date" />
</p:calendar>
<p:calendar id="end-date"
value="#{debugManager.selectedEndDate}"
mindate="#{debugManager.minEndDate}"
minHour="#{debugManager.minEndHour}"
minMinute="#{debugManager.minEndMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button">
<p:ajax event="dateSelect" update="begin-date" />
</p:calendar>
Aquí hay un ejemplo de método min / max (fecha mínima de finalización):
public Date getMinEndDate()
{
return this.getSelectedBeginDate();
}
Como puede ver, la fecha de finalización mínima es la fecha de inicio seleccionada actualmente por AJAX. Establecer una fecha de finalización no permite establecer la fecha de inicio después de la fecha de finalización.
Los problemas comienzan cuando se involucra el tiempo en la ecuación ...
Como la interfaz de p: calendar tiene métodos separados, el bean debe proporcionar la lógica:
public int getMinEndHour()
{
Date selectedBeginDate = this.getSelectedBeginDate();
Date selectedEndDate = this.getSelectedEndDate();
if ( selectedBeginDate != null && DateUtil.isSameDay( selectedBeginDate, selectedEndDate ) )
{
return DateUtil.getHourOf( selectedBeginDate );
}
return ComplianceConstants.DEFAULT_COMPLIANCE_CASE_MIN_END_HOUR;
}
Esto básicamente solo dice si se ha establecido una fecha de inicio y si las fechas de inicio y finalización son actualmente las mismas, restrinja la hora final seleccionable ( minHour
de fecha de finalización) a la hora de inicio.
Operaciones:
Set the begin datetime to 2013-04-20 12:34 (legit)
Set the end datetime to 2013-04-22 00:00 (legit)
Ahora el horario de la fecha de finalización es 00:00 y seleccionar una fecha del calendario 2013-04-20 debe permitirse siempre que la hora de finalización se ajuste de alguna manera a al menos 12:35.
Sin embargo, el componente p: calendario no puede saber esto y ahora
sets the end datetime to 2013-04-20 00:00 (legit, but false)
...
El problema ahora es que cuando el usuario presiona una nueva fecha de finalización nueva en el calendario, los atributos mindate / maxdate no pueden restringir al usuario para que coincida con la fecha de inicio. Si el momento de la fecha de finalización ahora es anterior a la fecha de la misma fecha de inicio, no hay nada que podamos hacer al respecto (lo cual es incorrecto).
El problema de seguimiento ahora es que el usuario puede cerrar el calendario y simplemente presionar el botón de enviar para insertar datos falsos en el DB. Por supuesto, un validador podría / debería ejecutarse, pero de alguna manera debemos lograr esto sin un validador .
Lo que intentamos a continuación fue parchar los setSelectedBeginDate( Date selectedBeginDate )
y setSelectedEndDate( Date selectedEndDate )
para ajustar las porciones de tiempo establecidas java.util.Date
si las fechas estaban en el mismo día. Algo como esto:
public void adjustSelectedEndDate()
{
if ( this.selectedEndDate != null )
{
this.log.infov( "adjustSelectedEndDate: b-hour = {0}, e-hour = {1}", DateUtil.getHourOf( this.selectedBeginDate ), DateUtil.getHourOf( this.selectedEndDate ) );
if ( DateUtil.isSameDay( this.selectedBeginDate, this.selectedEndDate ) &&
( DateUtil.getHourOf( this.selectedEndDate ) < DateUtil.getHourOf( this.selectedBeginDate ) ) ||
DateUtil.getHourOf( this.selectedEndDate ) == DateUtil.getHourOf( this.selectedBeginDate ) && DateUtil.getMinuteOf( this.selectedEndDate ) <= DateUtil.getMinuteOf( this.selectedBeginDate ) )
{
this.log.info( "Adjusting selected end date!" );
this.selectedEndDate = DateUtil.addOneMinuteTo( DateUtil.copyTime( this.selectedBeginDate, this.selectedEndDate ) );
}
}
}
Esto requirió que agreguemos @this
al atributo de update
de cada p:calendar
para que los getters respectivos ( getSelectedBeginDate()
y getSelectedEndDate
+ los limitadores min / max) se getSelectedEndDate
durante la actualización.
Sin embargo, colocar un @this
en la actualización confunde los componentes p: calendar, haciendo que los controles deslizantes de tiempo solo se puedan deslizar una vez. Los sucesivos eventos del control deslizante simplemente se ignoran y se comportan de forma incorrecta.
Q''s
- ¿Cómo te acercas a resolver esto?
- ¿Está utilizando
p:remoteCommand
la manera de lograr lo que queremos?
Q opcional :
- ¿Por qué no se implementó PrimeFaces p: calendar para proporcionar un solo minDateTime y maxDateTime, lo que podría resolver los problemas actuales?
Apuesto a que este escenario que describí ya ha sido resuelto antes. Le agradecería mucho si pudiera describir el enfoque que logró resolver esto (o incluso compartir una solución en parte).