防止提交本地化日期时间

Prevent localized date time from being submitted

Stringjava.time.LocalDateTime之间来回转换的基本转换器(只是一个原型)。

@FacesConverter("localDateTimeConverter")
public class LocalDateTimeConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            return null;
        }

        try {
            return ZonedDateTime.parse(submittedValue, DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime());
        } catch (IllegalArgumentException | DateTimeException e) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
        if (modelValue == null) {
            return "";
        }

        if (!(modelValue instanceof LocalDateTime)) {
            throw new ConverterException("Message");
        }

        Locale locale = context.getViewRoot().getLocale();

        return DateTimeFormatter.ofPattern(pattern, locale).withZone(ZoneId).format(ZonedDateTime.of((LocalDateTime) modelValue, ZoneOffset.UTC));
    }
}

提交至数据库的日期时间应基于Locale.ENGLISH。因此,它在 getAsObject().

中是常量/静态的

要从数据库中检索的日期时间,即要呈现给最终用户的日期时间是基于用户选择的选定区域设置的。因此,LocalegetAsString()中是动态的。

日期时间使用未本地化的 <p:calendar> 提交以避免麻烦。

这将按预期工作,除非正在提交的 <p:calendar> 组件本身或正在提交的同一表单上的某些其他组件在转换/验证期间失败,在这种情况下,日历组件将预填充本地化日期时间将无法在 getAsObject() 中在所有后续提交表单的尝试中转换,除非给定 <p:calendar> 中的本地化日期时间手动重置为默认语言环境。

由于没有转换/验证违规,以下将通过第一次尝试提交表单。

但是,如果其中一个字段出现转换错误,如下所示,

那么日历组件中的两个日期都将根据所选的语言环境 (hi_IN) 进行更改,因为其中一个字段存在转换错误,显然无法在 getAsObject() 在随后的尝试中,如果在通过为字段提供正确的值来修复转换错误后尝试提交包含组件的表单。

有什么建议吗?

在转换器的 getAsString() 中,您正在使用视图的区域设置来格式化日期。

Locale locale = context.getViewRoot().getLocale();

为了使用 component-specific 语言环境,必须将其作为组件属性提供。这是一个示例,前提是 faces-config.xml 中的 <locale-config><default-locale> 设置为 en.

<p:calendar ... locale="#{facesContext.application.defaultLocale}">

在转换器中你可以提取如下:

Locale locale = (Locale) component.getAttributes().get("locale");

您的转换器的基本转换器示例已同时更改以正确考虑到这一点: