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
Related
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"));
I am new to both Java and Apache spark and trying to understand the timestamp and timezone usage.
I would like all the timestamps to be stored in EST timezone in SQL Server from data i get from apache spark DF.
When I use current_timestamp, I am getting the correct EST time but the offset i am getting when i look at data is '+00:00' instead of '-04:00'.
Here is a value stored in database that is passed in from spark dataset:
2020-04-07 11:36:23.0220 +00:00
From what I see current_timestamp does not accept any timezone. Moreover, the time is correct (it is in EST) but i don't understand why the offset is wrong.
Any help to understand this would be great.
Java Timestamps work more or less as LocalDateTime in Java - they don't contain timezone information. And the database is interpreting this as UTC timestamp. That's why you got a mismatch. I usually use two approaches (depending what suits better)
You can return UTC timestamp from Spark (with simple custom UDF) instead of using current_timestamp which is timezone specific.
You can encode your dates as Strings - similarly, using java.time API you can achieve that with simple udf
Hope things are a bit clearer now.
I convert the UTC default to Localtimezone as below
current_timestamp1 = current_timestamp(),
current_timestamp2 = from_utc_timestamp(current_timestamp, "Australia/Sydney")
Introduction
I realise similar questions have been asked here before. But I still needed to do a bit more testing for my use case - and am I little surprised/confused by the outcome.
The following is a description (with code) of the test and results.
I'm working on an application that:
Records event history (things that happened at a point in time).
This history is immutable. Once an event is written, we do not change it.
We report on this history.
Schedules future, possibly recurrent, actions. For example, "every Friday do this check."
So a clear understanding of time data is very important.
I am trying understand the timestamp types in MySQL (datetime and timestamp) and how they interact with Java code and ISO8601 timestrings.
I've read the MySQL docs around its Timestamp type - how it converts a time value to store it as UTC and, on retrieval, converts that UTC value to the server or session time zone. That sounded like good "point-in-time" storage.
The datetime MySQL type is bit more opaque. This article (http://code.openark.org/blog/mysql/timestamp-vs-datetime-which-should-i-be-using) considers it to be not so different from a string.
I repeated the "SELECT NOW() + 0;" query and got the same kind of answer as the article.
To try to clarify things, I wrote a small Java class that wrote to a single database table comprised of 3 columns:
tz (String denoting the standard timezone id). UTC is used the tests - but it is not a timezone.
mydatetime (Datetime column)
mytimestamp (Timestamp column)
Java code
The Java code is located here: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d
Test 1
I created 3 different ISO8601 timestamp strings - all for the same point in time - but with different offsets/timezones.
Each was written the to database, retrieved and printed out.
To start with I set the MySQL database server time zone to "+00:00".
Output
Writing times to the database.
UTC
2018-04-13T11:12:00Z, 1523617920
Europe/Amsterdam
2018-04-13T13:12:00+02:00, 1523617920
Asia/Calcutta
2018-04-13T16:42:00+05:30, 1523617920
Reading stored times from database.
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523617920, 2018-04-13T11:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta]
All looks good. The epoch seconds, when put into something like https://www.epochconverter.com/, agree with the ISO8601 time strings.
Test 2
I then changed the timezone of the MySQL server from UTC (+00:00) to Europe/Amsterdam (+02:00) and read the stored times again.
Output
Reading stored times from database.
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523625120, 2018-04-13T13:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523625120, 2018-04-13T15:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523625120, 2018-04-13T18:42+05:30[Asia/Calcutta]
My expectation was the Datetime column would be affected - thinking it did not store timezone information. However, it was the Timestamp column that moved.
Conclusion
We will not routinely be changing our server timezone.
I'm trying to see which MySQL data type best represents a point in time - something I can count on as accurate and unchanging (and not head-wrecking). On the basis of the above, if I supply point-in-time info in the form of an ISO8601 string, the Datetime MySQL type retains the supplied information.
It's perfectly possible that my test code is incorrect and/or my interpretation of the results is.
Could do with a little guidance here.
In the test case above, is the Datetime MySQL type doing a better job of storing the point in time information?
After a bit more tweaking, I got a Java class that manages to store and retrieve point-in-time information. I'm still a bit jittery on this - so many parts want to have a say in the time and that makes me uncomfortable.
The class is on the original gist here: https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d (and revisions show changes).
I can change the MySQL server timezone to anything I wish. I still get out what I put in.
A query directly in the MySQL query manager also behaves - the timestamp column as unix epoch holds steady. That's what I expect.
select tz, mydatetime, unix_timestamp(mydatetime) as mydatetime_as_epoch, unix_timestamp(mytimestamp) from basic_time;
tz = timezone id (String); mydatetime (Datetime column); mytimestamp (Timestamp column)
Timestamp MySQL type is a timestamp. I don't need to mess with it.
Java 8 java.sql.Timestamp class fromInstant and toInstant methods claim to maintain the same point in time.
I tried Instant on the setObject and getObject preparedStatement methods. MySQL connector/J just does not accept them - I dug into the source code for a look.
Datetime MySQL type I'm still a bit confused by (I don't know what it is) but knowing the timezone I can maintain the point-in-time information.
I tried both the MySQL Connector/J 5.1.46 and 8.0.11 versions. Same behaviour for each.
The JDBC parameter useLegacyDatetimeCode=false seems to be important. I need to run more tests with and without this to confirm.
Not quite up to analysing this completely just yet. Not fun trying to figure this out.
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.
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.