Date timezone getting changed when using spring boot default jackson mapping - spring

I have spring boot rest service which call another service xyz and receive date in format yyyy-MM-ddXXX from json. But time Zone of of date is getting changed in my service response. Suppose I am getting date in JSON from service xyz as "date": "2018-08-27-07:00" but my service response is returning date : "2018-08-27-04:00". Offset getting changed. Date field in my POJO is . I want to use the same offset I am getting from backend service and it can be any offset.
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-ddXXX")
private Calendar date;

The problem is that Calendar (and Date) use implicit time conversions to adjust it to your time zone. And almost always it is something that not expected.
To avoid this use java.time classes (such as OffsetDateTime or ZonedDateTime, or even LocalDateTime if you do not need to work wit time zones).
And small offtopic advice: try to use time format aligned to ISO8601 standard (like 2018-08-24T22:30:00)

Related

Date conversation with time zone information

I have one issue. Solutions might be there already in this forum but I couldn't find anything. Please share if it's already answered.
The scenario is as below.
Request is coming in CET to my application which is running in UTac time zone. My backend stored procedure is running in CET zone. The time that is passed in as string with cet offset I need to send same as SQL date with same date to my backend.
Current implementation is:
Convert string date to offsetdate. Then create Instant from that offsetdate and then util date using that instant. Once I have until date I am converting that to SQL Date.
So here issue is if input request us 2012-07-15T00:00:00+02:00 then when applications which is running in UTC is giving correct offset date with cet offset information but when it is converting to instant then always UTC will come. So new date is 2012-07-14T00:00:00Z and because if this my util and SQL date is also coming 1 day behind.
Can anyone please guide if there is any other way where I can create SQL or util. Date for same date irrespective of any time zone?
Because the expectation is request can come with any time zone and we need to understand that zone and then convert or use accordingly and same date should go to back end.
API developed with: Spring boot with JAVA 8 and backend we are accessing using stored procedure where stored procedure is expecting in SQL date.
Since you can use OffsetDate and other classes from java.time, the modern Java date and time API, you should no longer be using java.util.Date nor java.sql.Date. Those classes are poorly designed and long outdated, and the modern API offers all the functionality you need. You might have thought that you needed a java.sql.Date for storing into your SQL database. But with JDBC 4.2 (or a newer JPA implementation such as Hibernate) you can directly store a LocalDate there, which you will prefer.
String requestString = "2012-07-15T00:00:00+02:00";
OffsetDateTime dateTime = OffsetDateTime.parse(requestString);
LocalDate date = dateTime.toLocalDate();
System.out.println("Date is " + date);
This prints:
Date is 2012-07-15
No day has gone lost. To save do for example:
PreparedStatement ps = yourDatabaseConnection.prepareStatement(
"insert into your_table (your_date) values (?);");
ps.setObject(1, date);
ps.executeUpdate();
Sometimes we need to pass an old-fashioned type to a legacy API that we cannot afford to change right away. If this was your reason for wanting a java.sql.Date, convert like this:
java.sql.Date sqlDate = java.sql.Date.valueOf(date);
System.out.println("Old-fashioned java.sql.Date is " + sqlDate);
Old-fashioned java.sql.Date is 2012-07-15
Still no day is lost.
Edit: If what your legacy API requires is a java.util.Date, you will need to know the way to convert:
Instant startOfDay = date.atStartOfDay(ZoneId.systemDefault()).toInstant();
Date oldFashionedUtilDate = Date.from(startOfDay);
System.out.println("As old-fashioned java.util.Date: " + oldFashionedUtilDate);
When I run with a default time zone UTC the output is:
As old-fashioned java.util.Date: Sun Jul 15 00:00:00 UTC 2012

Spring Boot - Jackson - datetime timezone problems

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.

Jodas LocalDateTime with Spring Data and Couchbase has no timezone

I wanna persistant an object with LocalDateTime fields with spring data and a couchbase behind in a spring boot app.
Here are the fieldmapping:
#Field
private LocalDateTime start;
#Field
private LocalDateTime end;
When I save the object then the dates are stored as numbers in couchbase.
Here are the stored data in couchbase:
"start": 1518818215508,
So the problem is, if I store an LocalDateTime e.g at 10.00, and then read it from db the result is 09:00 instead of 10:00 because of my local time +1:00.
In Postgres I would save the date in an column with mapping: columnDefinition= "TIMESTAMP WITH TIME ZONE"
How I can solve this problem in couchbase?
JSON (famously) has no date format (unlike relational databases which have a sprawling number of different formats). If you want to store timezone data in JSON, here are two options I can think of:
Using a string instead of a number, and then using something like ISO-8601.
Store the epoch time as you currently are as a UTC value, but also store a separate number field that represents a timezone offset from UTC
I would recommend going with the first approach.
I'm no Spring/Java expert, but a quick look at the documentation says you can do this by setting system property org.springframework.data.couchbase.useISOStringConverterForDate to true

Date format handling in Spring MVC

HI I have a problem in my current Spring +JPA project. My entity object and bean object for web page are same.
From web page using jquery i am reading date in (dd-mon-yyyy) format from screen and saving it to database. The field is of Date type in my bean class.
During update i am fetching values from database and displaying the same in web page. But this time the date format has chnaged to different fromat(yyyy/mm/dd) on screen.
So while saving again i am getting error, as the date format has been changed and i am unable to parse the value received form screen.
So is there any proper way to handle this situation.
I assume that you are storing the dates in database as a DATE or DATETIME type. If so, the value should be a Date object in Java. In order to output the date value as dd-mon-yyyy, you will need to use SimpleDateFormat to convert the date object into a string representation in your desired format:
new SimpleDateFormat("dd-MMM-yyyy").format(date);
An additional note: for an internal-only API, it doesn't matter what format you choose as long as you are consistent everywhere. But if you are creating something that could one day be exposed publicly, I would suggest that you send/receive date and time value in the ISO8601 format: yyyy-MM-ddTHH:mm:ssZ. This format is understood by everyone everywhere.
Update:
Based on your comment, I would say add a new method to your bean class:
private DateFormat dateformat = new SimpleDateFormat("dd-MMM-yyyy");
public String getFromDateString() {
return dateformat.format(fromDate);
}
And then in your JSP, call ${bean.fromDateString}.

How to convert a cassandra date object into epoch timestamp in java

I am creating a java plugin for moving data from cassandra database to elastic search. I am getting all the data but the date which I am getting from the database is in human readable form ie Row[Fri Jul 25 11:36:10 IST 2014].I want this to be converted to epoch timestamp format like 1414386721.
I do not know Cassandra DB, but according to this doc your driver should be translating the date-time value in Cassandra to a java.util.Date object in Java.
You may be confused about how a java.util.Date object works. The j.u.Date class is confusing and difficult in many ways, one of which is that while a Date has no time zone its toString implementation on-the-fly applies the JVM’s current default time zone as it generates the string.
You may also be new to date-time work and therefore confusing a date-time object with its String representation. Consider that 1.4 is a number and should not be confused with its representation as a String in the format of a price €1.40. Likewise a date-time object is not a String but can be represented as a String generated any number of formats.
Lastly, if you are indeed getting a java.util.Date object, learn to convert that to either the Joda-Time library or the java.time library. The java.util.Date and .Calendar classes are notoriously troublesome.

Resources