Get the original Timezone from Postgres tstz field - java-8

I am having a table like this.
CREATE TABLE tstz (
ts timestamp NULL,
tstz timestamptz NULL,
seq text NULL
);
Whenever, I store the timestamp with time zone, it gets converted to the timezone of the database. How do I get back the original timezone with which it is retrieved?
For example, I am storing the timezone like 2020-04-29T08:06:03.424689+05:30 to the database. However, when I read the database using Java and read the timezone again like following.
Optional<Tstz> tstzOptionalSaved = tstzRepository.findById(tstz.getSeq());
Tstz tstzSaved = tstzOptionalSaved.get();
log.info("Timezone {}" , tstzSaved.getTstz().getZone().getId());
the above code always returns UTC which is the timezone of the database.
Is there a way to do this in Postgres or in Java?

You can use OffsetDateTime. From postgresql docs,
all OffsetDateTime will instances will have to be in UTC (have offset 0). This is because the backend stores them as UTC.
So you need to add one column for offset and then use the offset to get original value,
OffsetDateTime tstz = rs.getObject("tstz", OffsetDateTime.class);
OffsetDateTime odtOriginal = tstz
.toInstant()
.atOffset(ZoneOffset.ofTotalSeconds(rs.getInt("tstz_offset")));
// 2020-04-29T08:06:03.424689+05:30

Related

How to fetch the date from epoch in CockroachDB

I have a column which has the time stamp stored in epoch. I need to fetch the date from the epoch time stamp. For instance for epoch = 1552942715, I need to fetch the date as 1552867200. How can this be achieved?
create table test (epoch text NULL);
Create table sample where the column is text datatype.
select (epoch::int)::TIMESTAMPTZ from test;
If the column is of type int or any other number then just cast it to timestampz

How to store timestamp with timezone

I am trying to store a timestamp with timezone into my oracle db.
I have for example this code:
$deadline = new \DateTime('2018-11-07 13:33', new \DateTimeZone("EUROPE/BERLIN"));
$control->setDeadline($deadline);
and the result stored in my oracle db is this one:
07.11.18 13:33:00.000000000 +01:00
but my goal is to to store the timestamp with this format: 07.11.18 13:33:00.000000000 EUROPE/BERLIN
if I run this query the value is correctly saved with the desired format:
update my_table
set deadline = TIMESTAMP '2018-11-07 09:00:00 EUROPE/BERLIN'
What I am doing wrong? What is the correct way to format the timestamp to obtain the desired result with symfony?
Looks like synfony transforms Europe/Berlin to +01:00 - which would be a bug.
As workaround you could do following:
ALTER SESSION SET TIME_ZONE = 'Europe/Berlin';
and then insert the value without any time zone, i.e.
$deadline = new \DateTime('2018-11-07 13:33');
$control->setDeadline($deadline);
If you insert a timestamp into a TIMESTAMP WITH TIME ZONE column and you don't provide any time zone information then Oracle defaults the time zone to your current SESSIONTIMEZONE which you set before.
You can set your SESSIONTIMEZONE also by Environment Variable ORA_SDTZ or in your Registry at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ORACLE\KEY_{ORACLE_HOME Name}\ORA_SDTZ, resp. HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_{ORACLE_HOME Name}\ORA_SDTZ

How to write date / timestamp string to Date timestamp column in Oracle DB?

I have stored some Oracle tables in Hadoop using AVRO file format and Hive external tables to access the data.
I have stored Date and Timestamp values as a formatted String, using the TO_CHAR function from Oracle on the import.
Now I want to export this exact data back with Spark to an Oracle table having a Date column. I use the command:
// Create a data frame from the Hive table
val data = sqlContext.sql("select * from avro_table")
// export df to existing oracle table
data.write.mode("overwrite").jdbc(jdbcString, "tableName", prop)
But then i get the error:
ORA-00902: invalid data type
This is because it tries to insert a string into a date column. Is there a safe way to insert a date / timestamp string from a Spark dataframe to an Oracle date / timestamp column? With safe i mean do not lose any timezone information.
You should use to_date, to_timestamp and/or date_format functions to do the transformation from stringified date/timestamp values to their corresponding type-aware ones.
date_format(dateExpr: Column, format: String): Column Converts a date/timestamp/string to a value of string in the format specified by the date format given by the second argument.
to_date(e: Column, fmt: String): Column Converts the column into a DateType with a specified format (see http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html) return null if fail.
to_timestamp(s: Column, fmt: String): Column Convert time string to a Unix timestamp (in seconds) with a specified format (see http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html) to Unix timestamp (in seconds), return null if fail.
Use select or withColumn operators.
A sample code could be as follows:
data.withColumn("real_date", date_format(...))
.write
.mode("overwrite")
.jdbc(jdbcString, "tableName", prop)

Timestamp to complete date format

We are working on oracle 11g enterprises edition. We are facing issue in getting value of date for type TIMESTAMPTZ and TIMESTAMPLTZ. We are storing those dates into one csv file using apache metamodel. We are fetching date from database using :
TIMESTAMPLTZ columnValue = (TIMESTAMPLTZ) row.getValues()[pos];
Timestamp timestamp=columnValue.timestampValue(connection,Calendar.getInstance(Locale.getDefault()));
Date dateByTimeStamp=new Date(timestamp.getTime());
Date dateByDateValue = columnValue.dateValue(connection);
String formattedDate = new SimpleDateFormat("dd-MMM-yy hh.mm.ss.SSSSSS a").format(dateByTimeStamp or dateByDateValue );
dateByDateValue contains date upto yyyy-mm-dd hh:mm:ss format. eg. 2016-10-12 08:49:30. There is no way to get value of nanoseconds and time zone using this object.
dateByTimeStamp object contains cdate that have value of date upto nanoseconds and also have time zone. But the value of date time differ because of time zone, but this cdate object contains information regarding nanoseconds precision.
Is there any way to get date in complete format so that the formatted date can directly be used to restore into another oracle db?

Is Postgres or Ruby adding the timezone to my `timestamp without time zone` column?

If I query my database with SELECT current_setting('TIMEZONE') I get 'UTC' (as expected).
Using PgAdmin, I run the following query:
SELECT foo FROM bar
PgAdmin shows "2011-03-12 08:00:00". However, when I read the value from Ruby (using DataMapper which uses the 'org.postgresql.Driver' JDBC driver as far as I know), it shows "2011-03-12 08:00:00 -0700".
Question: Where in the whole stack is the timezone getting added? Although I realize a lot depends on the specifics of my stack, it would really help to understand what should happen so that I can rule things out. For example, for a timestamp without time zone column, should I expect that JDBC driver gives a 'raw' value with no timezone information?
Something in Ruby is making the timezone adjustment:
psql=> select current_setting('timezone');
current_setting
-----------------
Canada/Pacific
(1 row)
psql=> select min(created_at) from people;
min
----------------------------
2010-07-09 13:58:51.320659
(1 row)
psql=> set timezone = 'utc';
psql=> select current_setting('timezone');
current_setting
-----------------
UTC
(1 row)
psql=> select min(created_at) from people;
min
----------------------------
2010-07-09 13:58:51.320659
(1 row)
You can check this by doing a raw SQL query of a timestamp from within Ruby and seeing what string you get back.
The JDBC driver when reading a timestamp without timezone makes bold/reasonable assumption that this timestamp is expressed in the JVM timezone.
If you do not want timezone to be added, use type 'timestamp without timezone'.
That way, reader will always read same second/hour/minute/day/month/year as you inserted.
I used following procedure to reproduce that
create table t (
without_tz timestamp without time zone ,
with_tz timestamp with time zone
)
SET SESSION TIME ZONE default;
insert into t VALUES ( now(), now() )
select * from t;
SET SESSION TIME ZONE PST8PDT;
insert into t VALUES ( now(), now() )
select * from t;
SET SESSION TIME ZONE PST6PDT;
insert into t VALUES ( now(), now() )
select * from t;
Observing values from select, I come to conclusion that
timestamp without timezone is never converted. You read same second/hour/minute/day/month/year what you inserted, no matter what timezone you are in.
timestamp with timezone converts values you read to your timezone. they represent same instant (point in time) but hour (and sometimes days, sometimes even minutes) values will be diffrent.

Resources