I've run into an interesting challenge using a PostgreSQL database with the PostgreSQL JDBC driver. It seems that the latest version of the driver, 9.2, uses the client time zone when performing date/time matches.
This becomes a problem when the server (JasperReports Server) is set to UTC and the database server is set to US/Eastern.
If I run the following query from a client set to the UTC time zone I get different results using the 9.0 JDBC driver and the 9.2 JDBC driver.
select now(), extract(timezone FROM now()), current_setting('TIMEZONE'), now()-interval '1 hour' as "1HourAgo"
Results using 9.0 JDBC driver:
now date_part current_setting 1HourAgo
2013-08-26 15:33:57.590089 -14,400 US/Eastern 2013-08-26 14:33:57.590089
Results using 9.2 JDBC driver:
now date_part current_setting 1HourAgo
2013-08-26 15:41:49.067903 0 UTC 2013-08-26 14:41:49.067903
This is causing a WHERE statement in a query to return incorrect results. For example,
WHERE end_time between now() - interval '1 hour' and now()
works as expected using the 9,0 driver but returns no results using the 9,2 driver as the driver appears to be offsetting the value of end_time to match UTC (the client's time zone). The following is a workaround, but an ugly one:
WHERE end_time at time zone 'EDT' between now() - interval '1 hour' and now()
Questions:
Has anyone else run across this before?
Is there an explanation for this change in behavior? I haven't been able to find anything in the JDBC release notes
Any advice on how to work around this other than rolling back the driver to an older version?
Thanks!
I just ran into this issue myself. I verified that the postgres jdbc driver is indeed picking up the connection timezone from the jvm, and I wasn't able to find a way to override this behavior. It really would be nice if they provided a jdbc url connection parameter for this purpose.
As a workaround, I discovered that my connection pool library (HikariCP) can execute a sql statement for each new connection:
hikariConfig.setConnectionInitSql("set time zone 'UTC'");
The use of the local timezone as the default timezone is required by the JDBC standard (and API documentation), and is made explicit by PreparedStatement.setTimestamp. However it also applies to all other areas where JDBC sets or retrieves time related data.
See also my answer to Is java.sql.Timestamp timezone specific?
Short version try:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Hi we ran across this issue with client and server timezone miss match We needed our unit tests to be run using "UTC". By looking at the source code for postgres jdbc driver (and this being test code) we "fixed" it by changing the TZ inside of the jvm before obtaining a connection.
Just in case others struggle with this - you can edit the "conf" file that launches SQLDeveloper and add the following line :
AddVMOption -Duser.timezone=UTC
I found this file on my machine at :
/opt/sqldeveloper/ide/bin/ide.conf
Thanks to #a_horse_with_no_name for pointing me in the right direction with a comment in one of the other answers
I don’t know JasperReports, but generally speaking, using the JSR-310 (Java 8) date/time types (supported by JDBC 4.2) should work without having to worry about time zone mismatches between database server and client.
See Using Java 8 Date and Time classes in the PostgreSQL JDBC driver documentation.
Related
Running SELECT current_timestamp in Dbeaver running PostgreSQL Version 12.2 gives me a datetime result that is 8 Days, 2 Hours and 4 minutes in the past compared to my system time. I am not sure if I need to tweak a time setting somewhere...
There are two explanations I can think of:
the system time on the database server is off
the timezone parameter is set to a weird value in your client session
When I run the following query in PgAdmin4 or psql, I get the same values for current_time, now(), and current_timestamp:
SELECT now(), CURRENT_TIME, CURRENT_TIMESTAMP;
now | current_time | current_timestamp
-------------------------------+--------------------+-------------------------------
2020-04-27 11:54:55.443006+01 | 11:54:55.443006+01 | 2020-04-27 11:54:55.443006+01
But when I run the same query from within DBeaver by connecting to the same PostgreSQL database, using JDBC driver, there's a difference between current_time and now() (and current_timestamp):
now |current_time|current_timestamp |
-------------------|------------|-------------------|
2020-04-27 12:57:00| 11:57:00|2020-04-27 12:57:00|
Obviously, the JDBC driver is somehow creating a discrepancy between current_time and current_timestamp.
My questions:
Is this the expected behavior from JDBC driver? (Why?)
Is there a way to control this behavior via some configuration of the JDBC driver itself without modifying the applications and queries relying on the JDBC driver?
current_time is a time WITH time zone something that is not supported by JDBC.
Applications need to take special steps to retrieve that value correctly. So, yes this is somewhat expected. I guess DBEaver uses getTime() which returns the time as UTC
That's one of the reasons the use of current_time is discouraged
I have a postgresql database that I deploy scripts to using flyway. I use the maven flyway plugin to launch the database build against the target database. In that build I have scripts that do things like:
create table my_table(
my_date_time timestamp with time zone not null
);
insert into my_table(my_date_time)
select '2000-01-01';
The postgresql database timezone is set to UTC. My client machine (that runs the maven/flyway build) is running CEST (UTC+2:00).
When the scripts run, the database interprets the string literal above as '1999-12-31 22:00:00+00:00' and writes that to storage.
It seems that the jdbc client connection created by flyway is not setting its client timezone to UTC, but is taking the timstamp string and interpreting it as '2000-01-01 00:00:00+02:00'.
How can I set the client timezone on the jdbc connection created by flyway to UTC? Is there a setting that can be placed in my flyway.conf file?
If I change my local machine timezone to UTC the problem goes away, but I'd rather not do that on my development workstation.
A colleague suggested the following
mvn -Duser.timezone=UTC flyway:migrate
Instead of just giving it a date, which postgres has to interpret, it would be better to fully specify the timestamp:
insert into my_table(my_date_time)
select '2000-01-01T00:00:00+00';
If that is not possible, you could try running mvn with -Duser.timezone=UTC but fully specifying the timestamp is the better option as it leaves no room for misinterpretation or misconfiguration.
Another way is to set session timezone in migration script itself
SET timezone TO 'UTC';
i use flyway CLI in a script. so setting correct timezone to the corresponding environment variable before executing flyway command works for me:
export TZ=GMT
I'm using Postgresql 9.6 and pgAdmin 4. Fresh install on both Windows and Mac, happens on both.
I need to store the current time and date.
None of my timestamp functions are returning times.
Time and Date work fine
SELECT CURRENT_DATE
Output: 2016-07-15
SELECT CURRENT_TIME
Output: 14:27:22.333352+01:00
SELECT CURRENT_TIMESTAMP
Output: 2016-07-15T00:00:00Z
Expected: 2016-07-15T14:27:22+01:00
SELECT now()
Output: 2016-07-15T00:00:00Z
Expected: 2016-07-15T14:27:22+01:00
What is the problem here?
set timezone TO 'GMT';
SET TIME ZONE 'UTC';
OR
You can set timezone param into pgsql/data/postgresql.conf file:
timezone = 'US/Central'
and then restart postgresql sever.
The problem is a bug in pgAdmin 4.
Timestamps are displayed incorrectly with the time set to 00:00:00Z
The data is stored correctly and the correct time can be observed using a different a different client such as psql
This issue has been resolved with newer version of pgAdmin4.
I started using the jOra eclipse plugin. The plugin seems pretty robust and I'm hoping to stop using SQLDeveloper for 95% of my database needs.
Many of our tables have columns of type TIMESTAMP with LOCAL TIME ZONE. I can connect to the oracle DB using a jdbc string and the plugin seems to function very well. However, when I try to update one of these TIMESTAMP with LOCAL TIME ZONE values, I get a sql exception: java.sql.SQLException: connection session time zone was not set.
Does anyone know how I can set the time zone through the jdbc connection url? jOra doesn't seem to support adding custom connection properties, so the connection URL is really my only option.
Update: Running version 1.0.1, which I believe is the latest version.
Update2: Apparently I can perform an update statement in the sql worksheet just fine, just can't use their detail browser interface to update.
What version do you use? According to their release notes this issue was already fixed in 0.9.0. Consider upgrading. If still in vain, I'd report a bug over there, they seem to maintain it well enough.
After you connect to the DB, try running:
ALTER SESSION SET time_zone='+01:00';
Alternatively you could create a system trigger:
CREATE OR REPLACE TRIGGER setSessionTZ
AFTER LOGON ON DATABASE
BEGIN
EXECUTE IMMEDIATE 'ALTER SESSION SET time_zone=''+01:00''';
END;