Converting UTC Timestamp to user time zone - java

In my PostgreSQL database i have a Timestamp column where I store data in UTC,
I fetch this date as LocalDateTime in my Java code.
When I generate an excel file I want to convert this date to the user time zone,
I found this solution:
localDateTimeFromDB.toInstant(ZoneOffset.UTC)
.atZone(ZoneId.of(userTimeZone))
.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
It works but I want to know if is it the optimize solution ?

You could skip the manual imtermediate conversion to an Instant, but I doubt this will optimize your approach significantly.
Here's some slightly different code of a very similar length producing the same result (,I think. You haven't shown yours so far):
localDateTimeFromDb.atZone(ZoneOffset.UTC)
.withZoneSameInstant(ZoneId.of(userTimeZone))
.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));

Related

Convert from joda.Datetime to time.LocalDateTime is the right way?

I need timestamp format for my dates in database.
For now i have joda.Datetime in database , but also in my restApi application.
I tried to create a new column , and converted the existing joda.Datetime in the other column time.LocalDateTime. Also I replaced in all code joda.DateTime with time.LocalDateTime.
It works, but when i make a get call in postman, i received a json like:
{
seconds: x1,
minutes: x2,
hours: x3,
days: x4,
........
}
I think i need a convertor, to show the timestamp as "dd-mm-yy hh-mm-ss"
I want to have timestamp format in database to be able to execute SQL standard operation and named queries on time.
In my database I have bytea type for dates. I use PostgreSQL with DBeaver.
Is this the right way, or you could recommend me another option?
Is this the right way, or you could recommend me another option?
Without experience with PostgreSQL I should say that bytea is the wrong datatype for your dates or timestamps. timestamp with time zone is good and supports SQL operations and queries. It further has the advantage that you can store OffsetDateTime (perhaps even Instant, I am not sure) directly, so you avoid formatting your timestamp for storing it. That’ll be recommended.
For a time stamp to be a time stamp date and time of day is not enough. Date and time of day will be interpreted differently in different time zones (and is even ambiguous in the fall when summer time ends and the clocks are turned backward). As far as I have understood timestamp with time zone will make sure that time stamps are stored in UTC, so will be unambiguous points in time. In Java the Instant class represents a point in time independently of time zone, so is good for timestamps. Some JDBC drivers allow you to store an Instant directly into a timestamp with time zone column, others require you to convert to OffsetDateTime first. In the latter case use
OffsetDateTime dateTimeForDatabase = yourInstant.atOffset(ZoneOffset.UTC);
Edit: Please note that the with time zone bit is a bit of a lie, as #Jon Skeet points out in a comment. The database doesn’t store a time zone or offset, it only makes sure that dates and times are stored in UTC for removing ambiguity about the point in time.
Link: Date/Time Types in the PostgreSQL docs

Java, Oracle db - Timezone issues after trunc(nvl) strips timestamp from a datetime object

Trying to fix a bug in our reporting. Currently the issue is as stands:
At 9:45PM on 2/22 in PST someone submits a work order.
It hits our Oracle Database and normalizes to EST (our db is in EST, but we work with clients all over US).
In iReport, we are using the following:
trunc(nvl(ls.date_occurred,ls.date_created)) between TRUNC($P{DATE_FROM}) AND TRUNC($P{DATE_TO})
This STRIPS the timestamp off of the datetime object, so when the report is generated it does not save the hours, only the date which is now 2/23 (at 12:25 AM respectively).
This obviously throws off our reporting feature. All of the data seems to be correct except this date offset that is generated a day after because of the timezone difference, and the adjusted data not having a timestamp asociated with it.
Does anyone have another way to adjust for datetime without using a function that strips the timestamp off of the date?
As I understand your from/to dates are not in EST which makes the discrepancy between the dates you require in your report to the date in you Database. In order to get the correct records instead if truncating the dates you need to adjust the requested to/from dates according to the timezone of the request (If you request from PST timezone first convert the dates to EST then make the query)
also, you can look at : TIMESTAMP WITH TIME ZONE Datatype
https://docs.oracle.com/cd/B19306_01/server.102/b14225/ch4datetime.htm
Turns out that I need to adjust for the timezone of date_created inside the nvl, because date_occurred is trunced whereas date_created is not. This causes data loss.

Save TimeZone with Date in mongodb

I have java.util.Date field in my document class.
E:g:
#Document(collection = "testdoc")
public class TestDoc {
#Id
String id;
Date startDate;
}
Even if I set the Date with UTC and IST, it always save in my collection as below,
"startDate" : ISODate("2015-08-21T18:30:00.000Z")
How can I save the time zone also in mongo collection? What does Z stand in this case?
The 'Z' signifies that the time is stored in UTC. Mongo internally converts all local representations of time in UTC before storing. However, one suggestion would be to store the time along with the timezone which is received from your application. You can later reconstruct the local time from the UTC time and the timezone in your application logic.
Please go through this link. They have given an example on how to model local time data using JavaScript.
https://docs.mongodb.com/v3.2/tutorial/model-time-data/
Do the conversion before storing and save as UTC always. Then reconvert it in the timezone you want before displaying.
If you desperately want to store the timezone with the offset you may have to deal with it as a separate string in db, but it cannot go with date field for MongoDB.
As currently MongoDB doesn't allow saving of timezone.
Below is the open JIRA issue or the same.
https://jira.mongodb.org/browse/SERVER-6310
Dates in MongoDB are stored in UTC. There isn't timestamp with a timezone data type like in some relational databases. Applications that need to access and modify timestamps, based on local time, should store the timezone offset together with the date and offset dates on an application level.
In the MongoDB shell, this could be done using the following format with JavaScript:
let now = new Date();
db.page_views.save({date: now,
offset: now.getTimezoneOffset()});
Then you need to apply the saved offset to reconstruct the original local time, as in the following example:
let record = db.page_views.findOne();
let localNow = new Date( record.date.getTime() - ( record.offset * 60000 ) );
I guess here you'll find a good guideline how to handle timestamps in different scenarios for different data language independent.
As it's recommendet in the document, ALWAYS use UTC to save the data, even it is local timezone. If necessary, save the time zone in a seperate field ( JSON or xml) and follw the format guideline ISO 8601. ( like you did but there are many possible representations)
As far as I know, correct me if i'm wrong, JSOn does not deal with specific date formats but JS does. Microsoft docs recommends the followind format bases on ECMA YYYY-MM-DDTHH:mm:ss.sssZ this
The Z in the Timestamp shows that it's UTC format with zero offset +00:00
if nothing else is added.
If you want to use the "Z" notation, you have to add or substract the offset within the timestamp instead of writing the zero-offset and add the offset at the end.
I recommend you to follw the w3c guideline because it covers different scenatios for different time saving usecases.
Hope this helps

What is proper way to persist time or date -type of information into database?

What is the proper way to save date or time based data in the database?
What are the proper "field mappings" for java to postgresql(or to some other database)?
That data should be stored in utc format without timezones.
-> timestamp and date based stuff fails in here, those will add current timezone (http://docs.oracle.com/javase/7/docs/api/java/util/Date.html)
-> what are the other options?
should I use "plain epoch/integer" column and other column for timezone? But then I cannot use all the functions etc. that the database is providing for me.
I could use hibernate with some jodatime magic, but in my current stack I don't have hibernate in use.
Possible solutions:
1). Change the computer/java timezone -> java will in the UCT (eg. export TZ="GMT" or -Duser.timezone=UCT)
2). Use epoch/Integer/Long values in date/time fields / types -> works but now I cannot use build in database functions.
3). Use Jodatime with custom hibernate datatypes?
4). Use Java8 new time and date apis?
In most cases, it is best to use the Postgres data type timestamptz (short for timestamp with time zone) when dealing with multiple time zones or when you want to save all timestamps as UTC.
Don't let the name mislead you, the time zone is not actually saved. But (as opposed to timestamp [without time zone]) the time zone from textual input is taken into account as modifier to compute the actual UTC timestamp value, which is saved.
On output, the text representation of the value is formatted according to your current time zone setting: timestamp is shifted and the according time zone modifier attached to it.
Note that timestamps without appended time zone are interpreted according to the current time zone setting of your session. If you want to enter a literal UTC value disregarding the current time zone, it has to be:
'2014-08-21 16:39:09+0'::timestamptz
not:
'2014-08-21 16:39:09'::timestamptz -- would assume current time zone
Detailed explanation in this related answer:
Ignoring timezones altogether in Rails and PostgreSQL
As you say, it would be best to store dates as UTC on the database. In oracle you can use a DATE or TIMESTAMP datatype. You can then use the java layer to present your dates in local time to the user and with a java.sql.timestamp column. Joda is essentially built in to the latest version of java so definitely use that for any conversions etc. The alternative would be to store timestamp with timezone in oracle and perhaps use oracle date functions in your sql and stored procedures to convert the date as required. We do the former, but it may depend on your team (db people vs java people) and your audience - are there likely to be lots of different timezones in the user base or is timing on the DST changeover going to break your app.
If you can describe particular situations you are concerned about I'm sure someone will help out. Storing your data in UTC will at least ensure that your data is solid but may require many conversions in the presentation layer.
There is not a single correct way but I my opinion is that you should store time as a long unix timestamp and single dates as epoch days. Java 8 has nice functions to deal with them. Avoid locking yourself with jodatime and hibernate just to manage a date.
What do you mean functions that the database is providing you?
You can always do SQL selects with integers and long since they are called from your program.
If you need a lot of manual use of the database (not programmatic) then you may want to use human readable dates.

Convert oracle.sql.timestamptz to postgresql timestamp with timezone

Sorry, but i`m noob and i need your advices.
I have some result set from oracle with timestamptz, i get string value of this timestamptz which like
2014-1-10 13.47.56.0 7:0
and then I need put it in postgresql-request in some function which takes timestamp with timezone. How can I convert this this string to timestamp with timezone in java? I tried do something look like
TO_TIMESTAMP_TZ("2014-1-10 13.47.32.0 7:0","YYYY-MM-DD HH24:MI:SS.FF TZH:TZM") but it didn`t work for me. Help me, please.
I don't know of a function TO_TIMESTAMP_TZ() in Postgres. You probably mean to_timestamp().
I also don't know of a template patterns TZH:TZM. You could use the AT TIME ZONE construct.
And data is quoted with single quotes; double quotes are for identifiers.
This works for me:
SELECT to_timestamp('2014-1-10 13.47.32.0', 'YYYY-MM-DD HH24:MI:SS.MS')::timestamp
AT TIME ZONE '-7:0'; -- shift back
It would be smarter to output timestamps in ISO 8601 format with TZR (time zone region) in Oracle, which is less ambiguous. Details in the Oracle manual.
Or better yet, UTC timestamps (without 0 offset), which you can cast to timestamptz directly in Postgres:
SELECT '2014-01-10 06:47:32+0'::timestamptz;
Or UNIX epochs, which can be fed to the second form of to_timestamp().
SELECT to_timestamp(1389336452);
Details about timestamps in Postgres:
Ignoring time zones altogether in Rails and PostgreSQL

Categories

Resources