Spring @DateTimeFormat ошибка преобразования с переходом на летнее время - PullRequest
5 голосов
/ 04 ноября 2011

Я использую Spring MVC на компьютере, на котором настроено летнее время (часовой пояс Америки / Sao_Paulo).В своем классе формы я использовал аннотацию DateTimeFormat для настройки вывода моей даты:

public class JustificativaOcorForm {
  ...
  @NotNull
  @DateTimeFormat(pattern="yyyy-MM-dd")
  private Date dataMarcacao;
  ...
}

Во время отладки я получаю дату 16/10/2011 (дд / мм / гггг), которая является началомдневное время, но весна преобразует его в 2011-10-15.Почему?

2011-11-04 16:35:31,965 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converting value Sun Oct 16 00:00:00 BRST 2011 of [TypeDescriptor @javax.validation.constraints.NotNull @org.springframework.format.annotation.DateTimeFormat java.util.Date] to [TypeDescriptor java.lang.Long]
2011-11-04 16:35:31,965 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converted to 1318730400000
2011-11-04 16:35:32,010 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converted to '2011-10-15'

Я вижу этот вопрос: @ DateTimeFormat в Spring выдает ошибку по одному за день

, но Spring 3 использует Joda-Time, и у меня естьjoda-time-2.0.jar в моем классе, так что я не знаю, почему это происходит и как я могу это решить.

[РЕДАКТИРОВАТЬ]

Я имеюпроверил создание объектов LocalData и нашел кое-что:

LocalDate ld = new LocalDate( new SimpleDateFormat("dd/MM/yyyy").parse("16/10/2011").getTime() );
System.out.println( new SimpleDateFormat("dd/MM/yyyy HH:mm:ss Z z").format( ld.toDate() )  );
//prints 15/10/2011 00:00:00 -0200 BRST

LocalDate ld2 = new LocalDate( 2011,10,16 );
System.out.println( new SimpleDateFormat("dd/MM/yyyy HH:mm:ss Z z").format( ld2.toDate() )  );
//prints 16/10/2011 00:00:00 -0200 BRST

Кажется, что первый подход - думать, что время в UTC, потому что при отладке я вижу, что Joda использует метод convertUTCToLocal класса DateTimeZone.

Может быть, это тоже значение по умолчанию для Spring, он ожидает и одну дату в UTC, и я передаю дату BRT.

Так что я думаю, что мое решение - изменить объекты на LocalDate и использоватьВторой способ создания экземпляра этого объекта.

1 Ответ

5 голосов
/ 10 ноября 2011

Это может ответить на некоторые части вашего вопроса.

Когда у вас есть объект java.util.Data, который будет напечатан в вашем часовом поясе системы внутри toString. Таким образом, если вы установите дату в UTC 2011-10-16 00:00:00, она будет внутренне преобразована в метку времени UTC в Date. toString напечатает эту временную метку в вашем местном часовом поясе, и это будет через пару часов после UTC (поскольку Сан-Паулу находится к западу от Лондона), примерно 2011-10-15 22:00:00. Это то, что вы увидите на контрольных точках и отладочных отпечатках. Данные могут все еще быть внутренне правильными.

Если обнаружено, что единственный реальный способ печати дат - через SimpleDateFormat, например:

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    try {
        Date dateInUTC = dateFormat.parse("2011-10-16 00:00:00");
        Date currentDate = new Date();
        String stringInUTC = dateFormat.format(currentDate);
        System.out.println(dateInUTC);
        System.out.println(currentDate);
        System.out.println(stringInUTC);
    }
    catch (ParseException e) {
        // not too worry, I wrote a nice date
    }

Теперь распечатка будет выглядеть очень запутанно

Sun Oct 16 01:00:00 CET 2011
Thu Nov 10 15:47:46 CET 2011
2011-11-10 14:47:46

Но давайте пройдемся по нему.

  1. Во-первых, мой SimpleDateFormat получает формат, и я установил его так, чтобы весь входящий и исходящий текст находился в часовом поясе UTC.
  2. Когда я разбираю дату 2011-10-16 00:00:00, она будет интерпретироваться как UTC, но когда я ее печатаю, java использует мою локаль (CET), чтобы напечатать ее как 2011-10-16 01:00:00 это также то, что я бы увидел в точке останова
  3. Когда я создаю новую Date (), эта Date будет в моей локали, и когда я распечатываю ее, она будет показывать 15:47 (мое текущее время), но когда я форматирую ее с моим SimpleDateFormat, осведомленным о часовом поясе, она покажет UTC.

Тем не менее, Java и даты будут сбивать вас с толку, пока вы не вырвете волосы:)

Надеюсь, это поможет некоторым.

...