Sql употребляют дату со дня до - PullRequest
2 голосов
/ 16 апреля 2019

Итак, я пишу REST API, и один из моих объектов имеет тип java.util.Date;Моя конечная точка POST использует JSON-тип, что-то вроде этого:

{
   "authorId": 7845,
   "authorName": {
      "first": "Dan",
      "second": "Brown"
   },
   "birth": {
      "date": "1987-10-25",
      "country": "USA",
      "city": "New York"
   },
   "description": "Very good author!"
}

Также я переопределяю метод Джексона deserialize для обработки недопустимого формата даты и всего, что с этим связано:

public class CustomDateDeserializer extends StdDeserializer<Date> {
    public CustomDateDeserializer() {
        this(null);
    }

    public CustomDateDeserializer(Class t) {
        super(t);
    }

    @Override
    public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException {
        String date = jp.getValueAsString();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setLenient(false);

        Date parsed;
        try {
            parsed = sdf.parse(date);
        } catch (ParseException e) {
            throw new InvalidDateTypeException(jp.currentName(), jp.getText());
        }
        return parsed;
    }
}

В моемМодель DTO Я использую именно этот десериализатор для этого параметра:

@JsonFormat(pattern = "yyyy-MM-dd")
@JsonDeserialize(using = CustomDateDeserializer.class)
@PastOrPresent(message = "Value 'date' must be past or present!")
private Date date;

При жизни всех моих промежуточных объектов (моделей и DTO) это значение везде выглядит так, как во входных данных JSON - 1987-10-25.

Контроллер:

@PostMapping(value = "/author/new", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> addNewAuthor(@RequestBody @Valid AuthorPostDto postAuthor) {
    AuthorPostDto response = authorService.addNewAuthor(postAuthor);
    return new ResponseEntity<>(response, HttpStatus.CREATED);
}

Метод обслуживания:

public AuthorPostDto addNewAuthor(AuthorPostDto author) {
    if (authorRepository.existsByAuthorId(author.getAuthorId())) {
        throw new AuthorAlreadyExistsException();
    }

    Author toPost = toModelMapper.mapAuthorDtoToAuthor(author);
    Author response = authorRepository.save(toPost);
    return toDtoMapper.mapAuthorModelToDto_POST(response);
}

Все объекты - postAuthor (проанализировано Джексоном в контроллере), toPost, response и возвращаемое значение из службы- содержит Date значение, как во входных данных JSON - 1987-10-25.

Но в SQL и в возвращаемом значении из контроллера дата отображается днем ​​ранее: 1987-10-24 ...

Какчтобы это исправить ??

1 Ответ

0 голосов
/ 26 апреля 2019

Ох ... После дня борьбы с этим я выиграл!

Проблема была в следующем: когда я отправляю свой json с датой 1987-10-25, он анализирует мой DTO, когда это необходимо.Но дата также должна иметь часы, минуты и секунды.Вот почему Java автоматически устанавливает здесь шесть нулей: 00:00:00.Итак, моя Дата выглядит так: 1987-10-25 00:00:00.

Как я писал при жизни всех моих промежуточных объектов (моделей и DTO), это значение везде выглядит как эта дата: 1987-10-25 00:00:00.Но как только этот объект покинул мое приложение, он установил здесь мой часовой пояс: -2.Итак, для SQL и в ответном JSON моя дата будет такой: 1987-10-24 22:00:00.

Чтобы решить ее - установите часовой пояс равным 0 в методе десериализации:

public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException {
    String date = jp.getValueAsString();

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setTimeZone(TimeZone.getTimeZone(ZoneOffset.ofHours(0))); //here
    sdf.setLenient(false);

    Date parsed;

    try {
        parsed = sdf.parse(date);
    } catch (ParseException e) {
        throw new InvalidDateTypeException(jp.currentName(), jp.getText());
    }

    return parsed;
}

Теперь это работает хорошо дляя.

...