Некорректное время (часовой пояс) в ответе
Работаю с использованием CamundaBPM, собираю статистику по задачам и не только, выполняю запрос на собственный эндпоинт (на RestController) и получаю список процессов и их задач
@GetMapping("/history")
public ResponseEntity<List<ProcessDto>> getHistoryProcesses(HttpServletRequest request, HttpServletResponse response) {
...
}
Класс:
public class ProcessDto {
private String id;
private Date created;
...
}
Тайм зона стоит Europe/Moscow, дата (если смотреть через дебаггер) верная и имеет такой вид:
created: Mon Nov 01 14:16:40 MSK 2021 - тип Date, если его раскрыть, то
fastTime: 1635765400581
cdate: 2021-11-01T14:16:40.581+0300
В дебаг-консоли отображается верное время: DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor - Writing [[ProcessDto(id=2fe11c6f-3b05-11ec-978e-0242ac110003, created=Mon Nov 01 14:16:40 MSK 2021, ownerName (truncated)...
Но проблема в том, что в ответе время отображается (в браузере, в постмане) на 3 часа меньше, чем должно быть."created": "2021-11-01T11:16:40.581+0000", и имеет уже такой вид
Я предполагаю, что проблема в сериализации (?) дат такого типа, нужно менять конфиг Jackson или что-то еще?
Ответы (1 шт):
Время, которое отображается в консоли, выводится в формате по умолчанию, заданном в методе Date::toString:
public String toString()
Converts this Date object to a String of the form:
dow mon dd hh:mm:ss zzz yyyy
Jaskson использует свой класс для форматирования даты StdDateFormat без часового пояса и с локалью en_US, используя формат ISO-8601:
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.getDateFormat());
// DateFormat com.fasterxml.jackson.databind.util.StdDateFormat: (timezone: null, locale: en_US, lenient: null)
Соответственно, для изменения формата даты нужно либо сконфигурировать ObjectMapper:
ObjectMapper mskDateMapper = new ObjectMapper();
mskDateMapper.setDateFormat(new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US));
mskDateMapper.getDateFormat().setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
ProcessDto p = new ProcessDto("id", new Date());
System.out.println(p);
System.out.println("----");
System.out.println(mskDateMapper.writerWithDefaultPrettyPrinter().writeValueAsString(p));
Вывод:
ProcessDto [id=id, created=Wed Dec 01 00:05:41 EET 2021] // toString, default time zone
----
{
"id" : "id",
"created" : "Wed Dec 01 01:05:41 MSK 2021"
}
Либо задать формат на уровне сериализуемого DTO класса (тогда настройки маппера будут проигнорированы):
static class ProcessDto {
private final String id;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="EEE MMM dd HH:mm:ss z yyyy", timezone="Asia/Novosibirsk", locale = "en_US")
private final Date created;
// конструктор, геттеры, toString
}
Вывод в часовом поясе Новосибирска:
ProcessDto [id=id, created=Wed Dec 01 00:10:29 EET 2021]
----
{
"id" : "id",
"created" : "Wed Dec 01 05:10:29 NOVT 2021"
}