简体   繁体   中英

Spring myBatis forcing to save ZonedDateTime in system default timezone, how to prevent?

I am setting up an API that receives datetimes as String alongside with the country in which the datetimes are from. I have a formatter that converts those strings into ZonedDateTime

Say I am sending this JSON:

{
    "country": "ID",
    "activeUntil":"2020-03-10 08:00:00"
}

ID is for Indonesia (Timezone "Asia/Jakarta" UTC+7)

This is my converter

public static ZonedDateTime convertDatetimeStringToDatetime(String dtString, String country) throws ParseException {
    DateFormat formatter = new SimpleDateFormat(("yyyy-MM-dd HH:mm:ss"));
    formatter.setTimeZone(TimeZone.getTimeZone(CountryTimezones.timezoneMap.get(country)));
    return formatter.parse(dtString).toInstant().atZone(ZoneId.of(CountryTimezones.timezoneMap.get(country)));
}

CountryTimezones.getTimeZone is just a Map that link a country shortcode to its timezone.

Until this point all goes alright, my object holds the value that I want.

log.info(myObject.getActiveUntil().toString());
log.info(myObject.getActiveUntil().toLocalDateTime().toString());
log.info(myObject.getActiveUntil().withZoneSameInstant(ZoneId.of("UTC")).toString());

shows

2020-03-10T08:00+07:00[Asia/Jakarta]
2020-03-10T08:00
2020-03-10T01:00Z[UTC]

The problems come when I persist the date into database. I am using mybatis, and my query looks like this:

<insert id="insert">
    INSERT INTO sometable (country, active_until, created_by)
    VALUES (#{entity.country}, #{entity.activeUntil}, #{entity.createdBy})
</insert>

(shortened for clarity)

And the datetime saved is "2020-03-10 09:00:00"

For information my location timezone is utc+8, meaning, the datetime is autoconverted to my location timezone.

MyBatis version <mybatis.version>3.4.5</mybatis.version>

I am using MySQL DB

The type of the active_until column is (MySQL) datetime.

This the Query Log :

==> Preparing: INSERT INTO sometable (country, active_until, created_by) VALUES (?, ?, ?)
==> Parameters: ID(String), 2020-03-10 09:00:00.0(Timestamp), Created by System(String)

How to change this behavior to force save all my ZonedDateTime in UTC

I fixed it by adding this to my Application.java

@PostConstruct
public void init() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    System.out.println("Spring boot application running in UTC timezone :" + new Date());
}

myBatis apparently takes the timezone of the application as the timezone to use for saving a ZonedDateTime. Since I hadn't set it up, the application timezone was using system default which must have been the timezone of my location.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM