Java LocalDate сохраняется как полуслучайное количество дней назад при сохранении в MySQL базе данных - PullRequest
2 голосов
/ 18 июня 2020

У меня проблема с сохранением правильных Java LocalDates в базе данных MySQL. Когда я регистрирую дату, она показывает правильную дату, но когда я сохраняю ее для двух разных сущностей (Пользователь и Семья),

  • Домохозяйство всегда сохраняет ее как на день раньше. (согласованно и объяснимо с помощью разницы часовых поясов), но

  • Пользователь сохраняет полуслучайную другую дату, которую я не понимаю .

Примеры правильной даты, сохраненных данных домашнего хозяйства, даты сохранения пользователя и разницы в количестве дней между датой пользователя и даты домашнего хозяйства можно увидеть в следующей таблице. На дату 2017-04-01 "случайная" версия для объекта User даже отличается.

image showing date difference

Даты верны при запуске локально на мой MacBook Pro, но даты различаются в нашей Java 11 среде разработки или производства Google App Engine. Не могли бы вы помочь мне понять, почему это происходит?

Дата получена с помощью веб-службы REST, которая принимает дату в виде строки YYYY-MM-DD в формате ISO как часть класса UserRegistrationCommand. Затем этот класс преобразует строку в объект LocalDate в своем методе getMoveInDate:

public class UserRegistrationCommand {

    ...
    public String moveInDate;
    ...

    public LocalDate getMoveInDate() {
        if(moveInDate == null) {
            return null;
        }
        try {
            return LocalDate.parse(moveInDate, DateTimeFormatter.ISO_LOCAL_DATE);
        } catch (Exception e) {
            return null;
        }
    }
}

Используя Spring JPA, я затем сохраняю эту дату для объекта User и Household соответственно в базе данных MySQL, где таблицы для эти объекты используют тип данных DATE.

Когда я регистрирую дату до сохранения, она показывает правильное значение. Но когда дата сохраняется в базе данных, таблица User получает дату за много дней, а таблица Household получает дату, которая на один день раньше даты отправки.

(Даты в комментариях к коду ниже относится к первому примеру даты на моем изображении)

Сохранение объекта User:

@Transactional
public User createUser(String email, String password, String firstName, String lastName, String language, Household household, LocalDate moveInDate, String redirectState) {
    LOG.debug("Registering user {}, {}, moveInDate: {}", email, household, moveInDate != null ? moveInDate.toString() : "null"); // <-- Logs "Registering user ... moveInDate: 2017-08-01 ..."
    [...]
    Locale locale = localeProvider.matchAvailableLocale(language);
    User user = new User(email, encodedPassword, firstName, lastName, locale, household, moveInDate, NotificationPreferences.defaultPreferences());
    user.setRedirectState(redirectState);
    Image profilePicture = avatarService.createProfilePicture(user.getNameInitials());
    user.setProfilePicture(profilePicture);
    return save(user); // <-- calls userRepository.save(user), but date is stored as 2017-07-27
}

Сохранение объекта домашнего хозяйства:

LOGGER.debug("ActivationCodeRegistrationStrategy.register: Setting moveInDate {} for household {} for user {}", cmd.getMoveInDate(), activationCode.getHousehold(), cmd.email); <-- logs "ActivationCodeRegistrationStrategy.register: Setting moveInDate 2017-08-01 ..."

householdService.setMoveInDate(activationCode.getHousehold(), cmd.getMoveInDate()); <-- but a date of 2017-07-31 is saved.

Вызов homeService.setMoveInDate просто устанавливает дату для объекта Household и сохраняет ее в базе данных:

public void setMoveInDate(Household household, LocalDate moveInDate) {
    household.setMoveInDate(moveInDate);
    householdRepository.save(household);
}
...