it-swarm.com.ru

Неправильный формат даты при отправке формы Spring

У меня есть проект, где я использую Spring MVC и Thymeleaf. Мне нужно отображать даты в разных форматах для каждого пользователя в зависимости от его предпочтений. Например, UserA хочет отображать даты, такие как MM/dd/yyyy, а UserB хочет отображать даты, такие как dd/MM/yyyy.

Для этого я использую этот параметр thymeleaf:

th:value="${#dates.format(myDate, dateFormat)}"

Значение dateFormat основано на предпочтениях пользователя. Это отлично работает.

Моя проблема в том, что ввод даты осуществляется в форме, и когда я отправляю форму, она не принимает хороший формат. Я всегда получаю ММ/дд/гггг.

Если я выберу формат дд/мм/гггг и введу 18.01.2016, в моем контроллере весны я получу "Чт 01 июня 00:00:00 CEST 2017", что соответствует 01.06.2017 в дд/мм/гггг ,.

Что я могу сделать, чтобы получить дату в нужном формате?

Вот мой код:

<form th:action="@{/test}" th:object="${filter}" th:method="POST">
    <input type="date" th:type="date" class="form-control" th:id="myDate"
           th:name="myDate" th:value="${#dates.format(filter.myDate, dateFormat)}"/>
</form>

Контроллер:

@RequestMapping(value = "/test", method = RequestMethod.POST)
public String myTest(@ModelAttribute Filter filter, Model model) {

    Systeme.out.println(model.dateFormat);
    // dd/MM/yyyy

    Systeme.out.println(filter.myDate.toString());
    // Thu Jun 01 00:00:00 CEST 2017

    return "test";
}
5
YLombardi

После дня исследований я обнаружил, что Spring читает значение, отправляемое в веб-запросе, и пытается связать его с объектом Filter.

Для значения даты исключается поиск значения в формате "MM/dd/yyyy". Если вы отправляете значение в другом формате, оно не работает.

Чтобы решить эту проблему, вы можете использовать аннотацию "InitBinder".

@InitBinder
private void dateBinder(WebDataBinder binder) {
    //The date format to parse or output your dates
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormat());
    //Create a new CustomDateEditor
    CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
    //Register it as custom editor for the Date type
    binder.registerCustomEditor(Date.class, editor);
}

Этот метод выполняется для каждого веб-запроса. Здесь я вызываю мой метод dateFormat (), чтобы получить формат в настройках пользователя, и говорю Spring, что все Java.util.Date, которые он находит в веб-запросах, имеют этот формат.

Вот мой полный код:

Фильтр:

import Java.util.Date;

@lombok.Data
public class TestDateFilter {
    private Date myDate;

    public TestDateFilter() {
        this.myDate = new Date();
    }
}

Контроллер:

@RequestMapping(value = "/testdate")
public String testDate(Model model) {
    model.addAttribute("filter", new TestDateFilter());
    return "testdate";
}

@RequestMapping(value = "/testdate", method = RequestMethod.POST)
public String testDatePost(@ModelAttribute("filter") TestDateFilter filter, Model model) {
    System.out.printf(filter.getLoadingStartDate().toString());
    System.out.printf(dateFormat());
    return "testdate";
}

@ModelAttribute("dateFormat")
public String dateFormat() {
    return userPreferenceService.getDateFormat();
}

@InitBinder
private void dateBinder(WebDataBinder binder) {
    //The date format to parse or output your dates
    SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormat());
    //Create a new CustomDateEditor
    CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
    //Register it as custom editor for the Date type
    binder.registerCustomEditor(Date.class, editor);
}

HTML:

    <form th:action="@{/testdate}" th:object="${filter}" th:method="POST">
        <div class="row">
            <div class="col-xs-12 col-sm-6">
                <div class="input-group date">
                    <input type="date" th:type="date" class="form-control"
                           th:id="loadingStartDate" th:name="loadingStartDate"
                           th:value="${#dates.format(filter.loadingStartDate, dateFormat)}" />
                </div>
            </div>
        </div>
        <div class="row">
            <div class="form-group">
                <div class="col-xs-12 col-sm-12">
                    <button type="submit" class="btn btn-primary btn-lg pull-right">
                        submit
                    </button>
                </div>
            </div>
        </div>
    </form>
6
YLombardi

Вы можете аннотировать атрибут Date

    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Date dob;

без зависимости от Joda начиная с весны 3.2

3
Pierpaolo Pagnoni

Я думаю, что есть проблема, потому что Spring не понимает, что введенное значение является датой. Является ли ваша переменная myDate типа Java.util.Date?

Если это так, попробуйте зарегистрировать форматировщик так:

package your.pack.formatter;

import Java.text.ParseException;
import Java.text.SimpleDateFormat;
import Java.util.Date;
import Java.util.Locale;
import org.Apache.commons.lang3.time.DateUtils;
import org.springframework.format.Formatter;

public class DateFormatter implements Formatter<Date> { 

    final String defaultDateFormat = "dd.MM.yyyy";

    @Override
    public String print(Date object, Locale locale) {
        return new SimpleDateFormat(defaultDateFormat).format(object);
    }

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        return DateUtils.parseDate(text, defaultDateFormat);
    }
}

Затем зарегистрируйте его в вашей конфигурации:

@Configuration
public class ConversionServiceConfig extends WebMvcConfigurerAdapter {

   @Bean
   public DateFormatter dateFormatter() {
       return new DateFormatter();
   }

   @Override
   public void addFormatters(FormatterRegistry registry) {
       registry.addFormatter(dateFormatter());
   }
}

Но я не знаю, как заставить это работать динамически, как вы хотите ...

Хранятся ли пользовательские настройки в базе данных или в свойствах?

1
sanluck