23

On client side, i use dd/MM/yyyy date format. The field use a twitter bootstrap 3 datetime picker (https://eonasdan.github.io/bootstrap-datetimepicker/)

I enter via twitter bootstrap 3 datetime picker 24/07/2015
in my json i sent, i see: birthdate: "24/07/2015"

In my dto, i do

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
private Date birthdate;

When i receive the date on the server, in my dto see: 23/07/2015 19:00

One day is lost.

Any explication?

robert trudel
  • 5,283
  • 17
  • 72
  • 124
  • have you checked your local time settings on your system ? – Sampath Jul 25 '15 at 02:44
  • client / server is on the same machine: both is edt -4 hours (mtl time)... – robert trudel Jul 25 '15 at 03:13
  • 2
    It is most definitely a time zone translation issue. One side is treating the time as UTC, and the other is converting to local time. We've had this issue in some client/server integration with 3rd-party system. The dead giveaway is the "19:00" that has been added to the other time, it is exactly 5 hours of difference (not actually a full day). – mellamokb Jul 25 '15 at 03:34
  • browser side i get for a new date: Fri Jul 24 2015 23:49:26 GMT-0400 (EDT). On the server i get: Fri Jul 23:49:26 EDT 2015. I think Eastern Daylight Saving Time (EDT) = GMT-4 (USA + Canada) – robert trudel Jul 25 '15 at 03:50
  • If you query your service using a tool like Postman, does the date come incorrect? In my case, the problem was in the restTemplate client, not in server. – Raffael Bechara Rameh Apr 30 '18 at 12:37
  • Had the same issue. Using postman to verify that the client is not the culprit. Seems like an issue with the timezone Jackson is using vs the timezone of the system. Had to change the jackson config to compensate for dates – cp5 Jan 14 '19 at 15:42

6 Answers6

13

According to JacksonFAQDateHandling page:

All time objects that have associated TimeZone (java.util.Calendar etc) that Jackson constructs use the standard timezone (GMT), not the local time zone (whatever that might be). That is: Jackson defaults to using GMT for all processing unless specifically told otherwise.

In your case, it looks like the date is automatically being converted to GMT/UTC. Try to provide your local timezone explicitly to avoid UTC conversion [as mentioned in the question How come this time is off by 9 hours? (5 hours, 3 hours etc) on same page]:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy", timezone="EST")

Secondly, I think you are using Date.toString() to print date. Note that java Date class is timezone independent but its toString() method uses the system's default timezone before printing.

Here it looks like 24/07/2015 00:00 UTC is being converted to 23/07/2015 19:00 EST by toString(). Both of these represent the same moment of time but in different timezones.

Community
  • 1
  • 1
AimZ
  • 526
  • 2
  • 9
  • i don't use toString(), but surely when @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy"), toString is maybe called. Is there a standard solution to manage this? keep only gmt date... but would need to know the timezone of the user somewhere to display date correctly. Maybe something could be used with new Date of java 8 or joda? – robert trudel Jul 29 '15 at 18:36
  • 1
    Best practice is to store the date/time info in UTC in database and also store user's timezone. Then use that timezone when displaying dates to user or remove timezone offset before storing. There are many articles listing benefits of this approach i.e. application can support different timezones. Java8 Date API has provided a new set of classes to work with date/time. Here is a nice article on Java8 Date API https://dzone.com/articles/deeper-look-java-8-date-and. Java8 or Joda _simplifies_ the date/timezone handling. – AimZ Jul 30 '15 at 15:49
1

AimZ answer is what pointed me to this but I added these three lines to my application.properties file and achieved the same thing

spring.jackson.date-format=yyyy-MM-dd

spring.jackson.serialization.write-dates-as-timestamps:false

spring.jackson.time-zone:EST

MarkyMarksFunkyBunch
  • 1,060
  • 10
  • 10
0

Had the same issue. Using postman to verify that the client is not the culprit. Seems like an issue with the timezone Jackson is using vs the timezone of the system. Had to change the Jackson config to compensate for dates

@Configuration

public class JacksonConfig {

    @Bean
    @Primary
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        final Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder = new Jackson2ObjectMapperBuilder();
        jackson2ObjectMapperBuilder.timeZone(TimeZone.getDefault());
        jackson2ObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
        jackson2ObjectMapperBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return jackson2ObjectMapperBuilder;
    }

}
cp5
  • 1,087
  • 6
  • 26
  • 58
0

I had the same issue in JavaScript when selecting dates from a datepicker. I formatted the fields using .toString() method but the function gave me a different date (I was messing a day as well). Like this:

var mydate = new Date('2020-04-03'); console.log(mydate.toString());

//Thu Apr 02 2020 20:00:00 GMT-0400 (Eastern Daylight Time)

I fixed it ussing .toUTCString() instead.

var mydate = new Date('2020-04-03');

console.log(mydate.toUTCString());

//Fri, 03 Apr 2020 00:00:00 GMT
Lorena Pita
  • 1,366
  • 1
  • 17
  • 20
0

I had the same issue in java. You can use ObjectMapper to set to default timezone

ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.setTimeZone(TimeZone.getDefault());

Solution here: Jackson @JsonFormat set date with one day less

Full configuration class:

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    for (HttpMessageConverter converter : converters) {
        if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
            ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
            mapper.registerModule(new Hibernate5Module());
            mapper.setTimeZone(TimeZone.getDefault());
        }
    }
}
0

I faced this same problem this week. For us the problem was the Decoder that we were using. Our project is using feing and to decode our JSON we were using JacksonDecoder, so we changed to GsonDecoder, so problem solved.

private fun servico(): IUsuarioServiceDeskClient {
    return Feign.builder()
        .options(Request.Options(240000, 240000))
        .client(ApacheHttpClient()) 
        .encoder(JacksonEncoder())
        .decoder(GsonDecoder())
        .errorDecoder(SincServiceDeskErrorDecoder(urlBase))
        .target(IUsuarioServiceDeskClient::class.java, urlBase)
}