web-dev-qa-db-ja.com

日付範囲の検証

2つの日付(StartDateとEndDate)を比較して、一方が他方の前にあるかどうかを確認します。最も簡単な解決策は、バッキングBeanでそれを実行し、メソッドを「短絡」することです。

ただし、この検証は他のフォーム検証と同時には行われません。たとえば、(日付以外に)検証を必要とする別のフィールドがあり、無効な入力がある場合、その特定のフィールドのメッセージのみを取得します。他のフィールドが有効な場合のみ、バッキングBeanに基づいて日付の検証が行われます。

誰かが解決策を持っていますか?

14
ChrisGeo

ただし、この検証は他のフォームの検証と同時には行われません。

実際、バッキングBeanアクションメソッドは、入力の検証を実行するためのものではありません。


誰もが解決策を持っていますか?

仕事に適したツールを使用してください。通常の Validator を使用します。

_@FacesValidator("dataRangeValidator")
public class DateRangeValidator implements Validator {
    // ...
}
_

ただし、単一のバリデーターで複数の入力値を検証することは、実際には別の話です。基本的には、他のコンポーネントまたはその値をvalidate()メソッド実装にグラブ/パスする必要があります。最も単純な形式では、_<f:attribute>_を使用できます。 _<p:calendar>_を使用して日付を選択していると仮定すると、具体的なキックオフの例を次に示します。

_<p:calendar id="startDate" binding="#{startDateComponent}" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true">
    <f:validator validatorId="dateRangeValidator" />
    <f:attribute name="startDateComponent" value="#{startDateComponent}" />
</p:calendar>
_

binding属性に注意してください。指定された変数名のELスコープでコンポーネントを使用できるようになります。また、この例は現状のままであり、絶対にBeanプロパティにバインドしないでください!)

dateRangeValidatorは次のようになります。

_@FacesValidator("dateRangeValidator")
public class DateRangeValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value == null) {
            return; // Let required="true" handle.
        }

        UIInput startDateComponent = (UIInput) component.getAttributes().get("startDateComponent");

        if (!startDateComponent.isValid()) {
            return; // Already invalidated. Don't care about it then.
        }

        Date startDate = (Date) startDateComponent.getValue();

        if (startDate == null) {
            return; // Let required="true" handle.
        }

        Date endDate = (Date) value;

        if (startDate.after(endDate)) {
            startDateComponent.setValid(false);
            throw new ValidatorException(new FacesMessage(
                FacesMessage.SEVERITY_ERROR, "Start date may not be after end date.", null));
        }
    }

}
_

JSFユーティリティライブラリOmniFaces を使用する場合は、その _<o:validateOrder>_コンポーネント を使用することもできます。この要件は、カスタムバリデーターを必要とせずに、次のようにして達成できます。

_<p:calendar id="startDate" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true" />
<o:validateOrder components="startDate endDate" />
_

以下も参照してください。

34
BalusC

最小日と最大日を制限できるPrimeFacesを使用している場合。ユーザーはこれより大きな範囲を選択できませんでした。これは例です:

<p:calendar id="startDate" value="#{bean.startDate}" maxdate="#{bean.endDate}">
     <p:ajax event="dateSelect" update="endDate"/>
</p:calendar>
<p:calendar id="endDate" value="#{bean.endDate}" mindate="#{bean.startDate}" disabled="#{empty bean.startDate}">
      <p:ajax event="dateSelect" update="startDate"/>
 </p:calendar>
5
JoseJC

BalusCソリューションは、フォームで検証する日付範囲が1つしかない場合にのみ機能するため、複数の日付範囲検証を可能にするための改善点があります。

  • 別の<f:attribute>をendDateカレンダーコンポーネントに追加し、startDateコンポーネントへのバインディング属性名を指定します。

    <f:attribute name="bindingAttributeName" value="startDateComponent" />
    
  • 次にバリデータで:

    String startDateBindingAttrName = (String) component.getAttributes().get("bindingAttributeName");
    UIInput startDateComponent = (UIInput) component.getAttributes().get(startDateBindingAttrName);
    
1
Lotzy

Baseと同じようにBalusCを解答し、将来私が使用する...

これにより、間隔(年、月、週)、参照比較の初期、または最終を設定できます。

@FacesValidator("dateRangeValidator")
public class DateRangeValidator implements Validator {

   @Override
   public void validate(FacesContext facesContext, UIComponent component,
           Object value) throws ValidatorException {

       UIInput dateIniComponent = (UIInput) component.getAttributes().get("dateIniComponent");
       UIInput dateFinComponent = (UIInput) component.getAttributes().get("dateFinComponent");
       String range = ((String) component.getAttributes().get("range")).toLowerCase();
       String reference = ((String) component.getAttributes().get("reference")).toLowerCase();

       if (value == null) {
           return;
       } else if (value instanceof Date) {
           Date dateIni = null;
           Date dateFin = null;
           if ((dateIniComponent == null) && (dateFinComponent != null)) {
               if (!dateFinComponent.isValid()) {
                   return; //No hay datos contra quien comparar
               }
               dateFin = (Date) dateFinComponent.getValue();
               dateIni = (Date) value;
           }

           if ((dateFinComponent == null) && (dateIniComponent != null)) {
               if (!dateIniComponent.isValid()) {
                   return; //No hay datos contra quien comparar
               }
               dateIni = (Date) dateIniComponent.getValue();
               dateFin = (Date) value;
           }

           if ((dateIni != null) && (dateFin != null)) {
               Calendar cal = Calendar.getInstance();

               cal.setTime(dateIni);
               Integer yearIni = cal.get(Calendar.YEAR);
               Integer monthIni = cal.get(Calendar.MONTH);
               Long daysMonthIni = (long) YearMonth.of(yearIni, monthIni + 1).lengthOfMonth();
               Long daysYearIni = (long) cal.getActualMaximum(Calendar.DAY_OF_YEAR);

               cal.setTime(dateFin);
               Integer yearFin = cal.get(Calendar.YEAR);
               Integer monthFin = cal.get(Calendar.MONTH);
               Long daysMonthFin = (long) YearMonth.of(yearFin, monthFin + 1).lengthOfMonth();
               Long daysYearFin = (long) cal.getActualMaximum(Calendar.DAY_OF_YEAR);

               Long daysAllowed =
                       ("year".equals(range) ? ("ini".equals(reference)?daysYearIni:("fin".equals(reference)?daysYearFin:null)) :
                       ("month".equals(range) ? ("ini".equals(reference)?daysMonthIni:("fin".equals(reference)?daysMonthFin:null)) : 
                       ("week".equals(range) ? 7 : null)));

               Long daysBetweenDates = TimeUnit.DAYS.convert(dateFin.getTime() - dateIni.getTime(), TimeUnit.MILLISECONDS);

               if (daysAllowed == null) {
                   FacesMessage facesMessage
                           = new FacesMessage(
                                   FacesMessage.SEVERITY_ERROR,
                                   "Rango de fechas mal expresado en el facelet (Vista) ",
                                   "Rango de fechas mal expresado en el facelet (Vista) ");
                   throw new ValidatorException(facesMessage);
               }

               if (dateFin.before(dateIni)) {
                   FacesMessage facesMessage
                           = new FacesMessage(
                                   FacesMessage.SEVERITY_ERROR,
                                   "Fecha Final No es posterior a Fecha Inicial ",
                                   "La Fecha Final debe ser posterior a Fecha Inicial");
                   throw new ValidatorException(facesMessage);
               }

               if (daysBetweenDates > daysAllowed) {
                   FacesMessage facesMessage
                           = new FacesMessage(
                                   FacesMessage.SEVERITY_ERROR,
                                   "Se ha excedido los dias permitidos " + daysAllowed + " entre fechas seleccionadas, entre las fechas hay " + daysBetweenDates + " dias",
                                   "entre las fechas hay " + daysBetweenDates + " dias");
                   throw new ValidatorException(facesMessage);
               }
           }

       }
   }

}

今ビューで

    <p:outputLabel value="Date Initial:" for="itHeadDateInitial" />
    <p:calendar id="itHeadDateInitial"
                navigator="true" 
                binding="#{bindingDateIniComponent}" 
                value="#{theBean.DateIni}"
                pattern="dd-MM-yyyy" mask="true" >
        <f:validator validatorId="dateRangeValidator" />
        <f:attribute name="dateFinComponent" value="#{bindingDateFinComponent}" />
        <f:attribute name="range" value="year" />
        <f:attribute name="reference" value="ini" />
    </p:calendar>


    <p:outputLabel value="Date Final:" for="itHeadDateFinal" />
    <p:calendar id="itHeadDateFinal"
                navigator="true" 
                binding="#{bindingDateFinComponent}" 
                value="#{theBean.DateFin}"
                pattern="dd-MM-yyyy" mask="true" >
        <f:validator validatorId="dateRangeValidator" />
        <f:attribute name="dateIniComponent" value="#{bindingDateIniComponent}" />
        <f:attribute name="range" value="year" />
        <f:attribute name="reference" value="ini" />
    </p:calendar>
1
chepe lucho