User inputs date from JSP page, and it converts to Joda DateTime, the string output is
2014-03-26T00:00:00.000+09:00
However when I persist this entity containing date filed in database, and retrieve and print out again, it becomes
2014-03-25T09:00:00.000+09:00.
I don't know why database make this change to minus one day.
I use postgres, hibernate JPA for application development.
Thanks in advance.
What is the value in the database? Use pgAdmin app, the psql command line tool, or some other database admin tool to query Postgres directly.
What data type are you using in Postgres? You probably should be using TIMESTAMP WITH TIME ZONE. Avoid using the WITHOUT time zone type as it ignores any time zone offset info you may provide.
Despite the name, neither type stores any time zone info. The difference is whether you want Postgres to pay any attention to time zone info on incoming data. Be sure to read the doc thoroughly and play with it to experiment until understand how date-time works.
Read Always Use TIMESTAMP WITH TIME ZONE by David E. Wheeler, a Postgres expert.
Related
I have an instance of Oracle DB running in 2 locations - US and Europe. The java app servers connected to these are also in different locations. Eg, DB in US is connected to java server in India and DB in Europe is connected to java server in Japan. My task is, to pick a date from database from US and send it via Kafka to Europe and vice versa.
The problem is, the time I send from first region will not match with the time in other region. I want that if I send "22-Aug-2022 12:00:00" from US, it should get converted into equivalent time in Europe that is "22-Aug-2022 06:00:00" (depends on DB time only, not app server time).
What I thought of this problem was that I would take the UTC time from one region, send it over and in the destination region, insert the equivalent time. But whatever I have tried is not working due to lack of experience. I am not able to get the correct UTC timestamp in java.
Can someone suggest the best approach for this problem which takes care of converting and fetching the timestamp at DB level.
Edit:-
PS: Please ignore the time conversion logic in the given example. It's just an example and may be it is not factually correct. Please provide suggestions on time conversion in a generic way
The most accepted solution is to:
Store all dates in UTC in database and backend so it is consistent.
Then convert the dates to local date and time zone on frontend to display to user.
as how to convert to UTC maybe this answer can help you: Java: How do you convert a UTC timestamp to local time?
I have encountered problem in using JPA to save Time type into database.
Time value from browser into Java is mapped correctly, but when JPA save the value into DB, it become a different value.
Is there any solution to save time into database without changing the data of time?
(I have only 2 solutions: Change Time type into long or string, but I still prefer the solution that can save Time value).
Data input in browser:
Data input in browser
Save before save into DB:
Data before save into database
The data save into database(I use MySQL). I change value from 11:00:00 to 04:00:00:
Data when save into database
Actually you are trying to use timestamp (which actually represents a time point) field for duration (which represents time interval) purposes.
When you enter 11:00 it might means 11:00 at PST, UTC, ICT timezones. And these will be absolutely different values.
Instead of java.util.Date in java you have to use java.time.Duration and use TIME field in MySQL (http://www.mysqltutorial.org/mysql-time/)
I saw here on SO a few related questions (like this one and of course, this one)... Essentially, what I want is to store date-time as UTC, and let application user choose the time zone he wants to display date-time in.
Since it seems that date-time fields are affected by the underlying JDBC driver, I wonder if this is an acceptable way to go about storing UTC date-time:
Set both MySQL and Application server machine to UTC time zone (no need to separate)
Both MySQL and JVM should pick up underlying system time settings (if not instructed otherwise)
Use DATETIME table columns on MySQL side
Use java.util.Date as corresponding mapping on Hibernate side (I guess java.sql.Timestamp could be used too)
Let the application worry about interpreting date-time fields - i.e. let the user choose preferred time zone
Is this OK?
EDIT
To clarify - here I meant to refer to timestamps created strictly on the server (e.g.date-time of record creation). So the application server instantiates Date objects (new Date() equals current date-time on the server, and this is really time zone agnostic).
Now if a client user wants to supply some date for searching/filtering purposes, here is where the transformation from client-local time to UTC should take place, IMHO...
I would suggest another simple approach which would independent of machine timezone settings.
Instead of setting the timezone of the server machine, set the timezone of JVM. This can be done via system properties. On Windows example would as follows
set JAVA_OPTS=%JAVA_OPTS% -Duser.timezone=GMT
For MySQL here is the reference for doing it.
Now this this make sure that all your date-time are in GMT
Keep the timezone as configurable property OR it can be user dependent as well. So you store timezone for each user if the users belong to different geographies.
Whenever, a date is needed, after you select it from the database, apply the timezone to get the correct time.
The advantage of this approach is that this will work for the all the timezone users. Meaning the user will see the correct time as per their timezone.
Use locales to implement internationalization.
In java, I want to know that what is the best practice to keep date info for display, query, report etc. It seems that if we persist as long, all timezone dependency will be removed and we will keep 'persist globally, display locally' principle since Date object automatically converts long to current timezone.
But what is the advantage of persisting as Date object?
Do I loose any info other than info owner's timezone?
Can I get any wrong info when DLS takes into account?
Difference between persisting as UTC date and long is just readable db info?
Depending on your database you should use either TIMESTAMP WITH TIMEZONE or you convert it to UTC time and store it as long.
The first one relies on the DB to handle it correctly (the DB will, but will your DB driver? You have to test this for your setup). The second one makes it a manual process, you will get the correct result in the end but will have more hazzle with it because you have to take care about everything.
Inside Java you might want to use Calendar over Date because there you can specify the TIMEZONE etc. manually, thus you are able to display Dates in timezones different to your own easier.
It seems (and maybe I'm wrong) that if you want to preserve the timezone of when something happened with JDBC and Postgres you need to store the timezone separately from the timestamp.
That is I would prefer to give my ORM/JDBC/JPA a Java Calendar (or Joda DataTime) with say timezone America/New_York to a Postgres timestampz field. AND I would expect on retrieval regardless of the Servers timezone (or defaulting to UTC) to give me back a Calendar with timezone America/New_York. But just looking at most JDBC code (and things that depend on it that doesn't happen).
Is this correct?
This seems ridiculous that I would need to store the tz in another field when postgres supports it.
Thus it seems like the only two options are:
Select the timestampz Postgres column as a java.util.String and parse it.
Store the timezone as a separate field.
Option number one and two one would require some sort of conversion interceptors for my SQL mapping / ORM libraries.
What is the best solution for JDBC ?
What is the best solution for JPA (if different than JDBC)?
When you store a timestamp with time zone (timestamptz) it's converted to UTC for storage in the DB. When retrieved, it's converted to the client's current timezone, not the timezone it was originally in. It's a point in time, basically.
There is also timestamp without time zone (timestamp). This is not subject to conversion, but does not carry a timestamp with it. If you store a timestamp with your client time zone set to UTC, then retrieve it when the client time zone is '+08:00', you get the same value. That's half what you want, in that it preserves the raw time value.
The names and behaviours are awful and confusing, but set by the SQL standard.
You must store the time zone separately if you wish to record a point in time at a particular time zone. I'd recommend storing it as an INTERVAL with a CHECK constraint limiting it to be colname BETWEEN INTERVAL '-12' HOUR + INTERVAL '1' SECOND AND INTERVAL '12' HOUR. That definition rejects -12:00 and accepts +12:00; I'm not totally sure that's right, so check.
You could either store the timestamp of local time at that time zone (what I'd probably do), or store the timestamptz of the UTC time when the event occurred plus an offset that lets you convert it to local time.
Either will work fine for JDBC. For JPA, it'll depend on how well your provider understands and maps interval types. Ideally you want a transient generated field in your entity that reconstructs the Calendar instance you want using the timestamp and interval stored in the database.
EclipseLink supports storing the timezone in Oracle, I think you could get it to be stored in Postgres as well if you customized your PostgreSQLPlatform.