5

I am having trouble dealing with timezones across my projects.

First of all, I have two use cases:

1) A user input a DateTime with datepicker in HTML and we want to save it without timezone in the database. example input: 10.04.2018 18:00 --> we want to save exactly this date and also want to retrieve exactly this date, no matter what the timezone is on the client side. (we can think about this like a never changing date string)

2) The more common, second use case is, we enter a DateTime with datepicker in HTML and want to save the date with timezone in the database. For example: The Clients Timezone is Europe/Istanbul and he inputs a DateTime: 10.04.2018 18:00. Now we want to save this date as Europe/Berlin in Database which would be 10.04.2017 17:00. When we retrieve the date we want to convert the date to the timezone of the client. In this example, if a client with timezone Europe/Berlin wants to retrieve the database date 10.04.2017 17:00 we would exactly retrieve: 10.04.2017 17:00. But if a client with timezone Europe/Istanbul wants to retrieve the same value 10.04.2017 17:00 we would retrieve: 10.04.2018 18:00

Now I tried to achieve this behavior by settings the webapp timezone to Europe/Berlin and parse the dates for each use case with the Moment.js library on client site. Therefore, I always expect to retrieve a Date in the timezone Europe/Berlin from my web service and then either convert to the local time zone or let the date as it is.

I am using Spring Boot with following version:

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
</parent>
<properties>
    <java.version>1.8</java.version>
</properties>

In my application.properties file i set those values:

spring.jpa.properties.hibernate.jdbc.time_zone=Europe/Berlin
spring.jackson.deserialization.adjust-dates-to-context-time-zone=false
spring.jackson.time-zone=Europe/Berlin

MyApplication:

@PostConstruct
void started() {
   TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
}

My attributes in my model class look like this:

@Column(name = "timeFrom")
@Temporal(TemporalType.TIMESTAMP)
private Date timeFrom;

@Column(name = "timeTo")
@Temporal(TemporalType.TIMESTAMP)
private Date timeTo;

For the first use case, where I want a date which is not parsed to the local time zone i use this code to retrieve my date in javascript: (because I know that my date in database is Europe/Berlin, I convert it to this time zone in order to retrieve the exact same date as it is in the database)

var countHours = moment(timeTracking["countHours"]).tz('Europe/Berlin').format('HH:mm');

For the second use case, where i want to convert my Europe/Berlin date from the database to the local client time zone i use this code:

var timeFrom = moment(timeTracking["timeFrom"]).format('YYYY-MM-DD HH:mm');

When i pass a date from javascript via JSON and ajax to my backend i use this:

moment($("#timeRecord-timeFrom").val()).valueOf()

On serverside i receive a timestamp in milliseconds and i parse it like that:

Date dateFrom = new Date(node.get("startTime").asLong());

Now the weird part: everything I posted above is working perfectly fine on my localhost (local machine). However, as soon as I push my war file to the live system (Jelastic Spring Boot Server) I have an offset of 2 hours in my date.

The strangest part is when I commit my date via ajax and retrieve the persisted object afterward everything is fine and I have no offset. But when I do a full page reload, I immediately receive the date with 2 hours offset. However, the date is still correct in the database.

As this is only happening on the live system and not on the localhost I have no clue how to fix this.

What am I doing wrong? Would it be better to switch to JodaTime or Java8 LocalDateTime? I already tried it but ran into several build errors so stick with java.util.Date.

A best practice tutorial for my use cases would be also appreciated.

zFr3eak
  • 235
  • 1
  • 6
  • 21
  • 1
    The problem is most likely in your rendering code, not your persistence. Dates don't have timezones, only rendered representations of them do. Try the java8/jodatime classes (Instant, LocalDate, etc) instead of Date, to see if that helps you get your head around it. – Paul Hicks Apr 10 '18 at 18:27
  • Do you have an idea why this is only happening on the livesystem, but not on my localhost? I already tried to manage it with both java8 and jodatime. For java8 i wasn't able to setup the jackson serializer and for Jodatime i had casting problems and also ran into errors. Do you have a good tutorial for one of those methods? I already tried it for hours... – zFr3eak Apr 10 '18 at 18:29
  • The problem i have with java8 is described here: (hower including the dependecy as suggest doesen't work for me) https://stackoverflow.com/questions/29956175/json-java-8-localdatetime-format-in-spring-boot – zFr3eak Apr 10 '18 at 20:25
  • Is there a difference between the browsers you're using to test locally and on the live system? I'd look to the client software rather than your application. – Paul Hicks Apr 10 '18 at 21:07
  • See also [Java Best Practice for Date Manipulation/Storage for Geographically Diverse Users](https://stackoverflow.com/questions/40075780/java-best-practice-for-date-manipulation-storage-for-geographically-diverse-user). – Ole V.V. Apr 11 '18 at 04:28
  • 1
    A difference for live vs. localhost is probably the system timezone. On Jelastic that's usually UTC. Can you reproduce the problem locally if you change your system to UTC? – Damien - Layershift Apr 11 '18 at 06:34
  • i was able to reproduce my problem on the localhost system by changing the local timezzone to utc! however, i thought with this line of code in my SpringBootApplication: TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); i would tell the server web app to work in Europe/Berlin instead of UTC. Why am i still running into this error? – zFr3eak Apr 11 '18 at 08:04
  • when i change my TimeZone default to UTC all over my project. i ran into the ame error, but with shifted 2 hours in the other direction. But still the same error... any idea? – zFr3eak Apr 11 '18 at 08:08
  • nobody? i have no clue how to get around this. – zFr3eak Apr 15 '18 at 15:57

0 Answers0