Suppose I have a table foo with the colum changed_colum of type date.
Now i would like to get the local timestamp from that colum, I try the following:
select TO_CHAR(cast (changed_colum as timestamp) at local, 'YYYY-MM-DD HH24:MI:SS TZR') from foo
result--->
2016-07-08 08:48:35 EUROPE/BERLIN
but this print the date of the application server. I need the local date of the session and not of the server.
Any Idea?
According to Oracle's documents at:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions037.htm
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions079.htm#i999873
try this:
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;
or
this:
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;
Hope this will help.
Not clear what you are asking... If you know the dates are all "using the server time zone", then you can use
from_tz(cast (changed_column as timestamp), dbtimezone) at time zone sessiontimezone
and then format it as needed.
DATE datatype does not contain any time zone information. What is the time zone of these dates? Unless you don't know this from design of your application you cannot convert.
AT LOCAL is equal to AT TIME ZONE SESSIONTIMEZONE, i.e. the timezone set by your application server at logon (or set by ALTER SESSION SET TIME ZONE = ...). If you like this time zone equal to the timezone of your client then you have to code this at the application server.
Related
Instead of always writing:
select my_column at time zone 'UTC' at time zone 'Europe/Paris' from my_table;
I would prefer doing:
select dtz(my_column, 'Europe/Paris') from my_table;
UTC is system-wide (server time zone), and could even be hardcoded in dtz().
Can someone share an efficient implementation of such a function?
Edit
select my_column at time zone 'UTC' at time zone 'Europe/Paris' from my_table;
Can be shortened a very very little bit like this:
select timezone('UTC', my_column) at time zone 'Europe/Paris' from my_table;
Its really dificult to see what you are having trouble with on this.
I don't believe the server timezone helps you here. As I understand it, it's the SQL client timezone than affects this.
You're not going to get a function more efficient than (IMMUTABLE):
RETURN arg1 AT TIME ZONE 'UTC' AT TIME ZONE arg2;
But this will always be less efficient than writing it inline in your SQL.
Ideally your timestamp should be TIMESTAMP WITH TIMEZONE instead of TIMESTAMP WITHOUT TIMEZONE since it's being used to store absolute timestamps not local timestamps. This would prevent the need for two conversions (into UTC and out of it). But that does mean you would need to add the AT TIME ZONE 'UTC' into your INSERT and UPDATE statements.
Oracle database is hosted in US. Application server hosted in UK.
I am trying to access the oracle application from India, how can I write a query that will show IST time. (Local machine time).
This is an oracle form, so no coding can be done.
Tried below but did not worked
SELECT
TO_CHAR(current_date, 'DD-MON-YYYY HH24:MI')
FROM DUAL
Indian time is +5.5 hours from GMT, SYS_EXTRACT_UTC(SYSTIMESTAMP) gives time in GMT for any Oracle server
select to_char(SYS_EXTRACT_UTC(SYSTIMESTAMP) +
(5.5/24), 'DD-MON-YY HH24:MI:SS') from dual;
First change the timezone of your session:
ALTER SESSION SET TIME_ZONE = 'Asia/Calcutta';
SELECT TO_CHAR(CURRENT_DATE, 'DD-MON-YYYY HH24:MI') FROM dual;
Note, you cannot use the short name, because 'IST' is also used for "Indian Standard Time" and "Iran Standard Time" and "Israel Standard Time" and "Indonesian Standard Time".
Thus Oracle requires either the full name (see IANA time zone database) or UTC Offset, e.g. ALTER SESSION SET TIME_ZONE = '+5:30';. However, this is more risky in case your country uses DST (Daylight Saving Time)
Change your timezone with this first,
systimestamp AT TIME ZONE 'IST'
After executing this SQL in oracle 10g:
SELECT SYSDATE, CURRENT_TIMESTAMP FROM DUAL
I receive this strange output:
What is cause of the difference in time?
The server time is equal of SYSDATE value
CURRENT_DATE and CURRENT_TIMESTAMP return the current date and time in the session time zone.
SYSDATE and SYSTIMESTAMP return the system date and time - that is, of the system on which the database resides.
If your client session isn't in the same timezone as the server the database is on (or says it isn't anyway, via your NLS settings), mixing the SYS* and CURRENT_* functions will return different values. They are all correct, they just represent different things. It looks like your server is (or thinks it is) in a +4:00 timezone, while your client session is in a +4:30 timezone.
You might also see small differences in the time if the clocks aren't synchronised, which doesn't seem to be an issue here.
SYSDATE, SYSTIMESTAMP returns the Database's date and timestamp, whereas current_date, current_timestamp returns the date and timestamp of the location from where you work.
For eg. working from India, I access a database located in Paris. at 4:00PM IST:
select sysdate,systimestamp from dual;
This returns me the date and Time of Paris:
RESULT
12-MAY-14 12-MAY-14 12.30.03.283502000 PM +02:00
select current_date,current_timestamp from dual;
This returns me the date and Time of India:
RESULT
12-MAY-14 12-MAY-14 04.00.03.283520000 PM ASIA/CALCUTTA
Please note the 3:30 time difference.
SYSDATE returns the system date, of the system on which the database resides
CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE
execute this comman
ALTER SESSION SET TIME_ZONE = '+3:0';
and it will provide you the same result.
SYSDATE provides date and time of a server.
CURRENT_DATE provides date and time of client.(i.e., your system)
CURRENT_TIMESTAMP provides data and timestamp of a clinet.
Note: SYSDATE - returns only the date, i.e., "yyyy-mm-dd" is not correct. SYSDATE returns the system date of the database server including hours, minutes, and seconds. For example:
SELECT SYSDATE FROM DUAL;
will return output similar to the following: 12/15/2017 12:42:39 PM
SYSDATE, systimestamp return datetime of server where database is installed. SYSDATE - returns only date, i.e., "yyyy-mm-dd". systimestamp returns date with time and zone, i.e., "yyyy-mm-dd hh:mm:ss:ms timezone"
now() returns datetime at the time statement execution, i.e., "yyyy-mm-dd hh:mm:ss"
CURRENT_DATE - "yyyy-mm-dd", CURRENT_TIME - "hh:mm:ss", CURRENT_TIMESTAMP - "yyyy-mm-dd hh:mm:ss timezone". These are related to a record insertion time.
In Postgres, is it possible to change the default format mask for a timestamp?
right now comes back as
2012-01-03 20:27:53.611489
I would like resolution to minute like this:
2012-01-03 20:27
I know I can do this on individual columns with to_char() as or stripped down with a substr() by the receiving app, but having it formatted correctly initially would save a lot of work and reduce a lot of errors.
In PostgreSQL, The formatting of timestamps is independent of storage. One answer is to use to_char and format the timestamp to whatever format you need at the moment you need it, like this:
select to_char(current_timestamp, 'yyyy-MM-dd HH24:MI:SS.MS');
select to_timestamp('2012-10-11 12:13:14.123',
'yyyy-MM-dd HH24:MI:SS.MS')::timestamp;
But if you must set the default formatting:
Change the postgresql timestamp format globally:
Take a look at your timezone, run this as an sql query:
show timezone
Result: "US/Eastern"
So when you are printing out current_timestamp, you see this:
select current_timestamp
Result: 2012-10-23 20:58:35.422282-04
The -04 at the end is your time zone relative to UTC. You can change your timezone with:
set timezone = 'US/Pacific'
Then:
select current_timestamp
Result: 2012-10-23 18:00:38.773296-07
So notice the -07 there, that means we Pacific is 7 hours away from UTC. How do I make that unsightly timezone go away? One way is just to make a table, it defaults to a timestamp without timezone:
CREATE TABLE worse_than_fail_table
(
mykey INT unique not null,
fail_date TIMESTAMP not null
);
Then if you add a timestamp to that table and select from it
select fail_date from worse_than_fail_table
Result: 2012-10-23 21:09:39.335146
yay, no timezone on the end. But you want more control over how the timestamp shows up by default! You could do something like this:
CREATE TABLE moo (
key int PRIMARY KEY,
boo text NOT NULL DEFAULT TO_CHAR(CURRENT_TIMESTAMP,'YYYYMM')
);
It's a text field which gives you more control over how it shows up by default when you do a select somecolumns from sometable. Notice you can cast a string to timestamp:
select '2012-10-11 12:13:14.56789'::timestamp
Result: 2012-10-11 12:13:14.56789
You could cast a current_timestamp to timestamp which removes the timezone:
select current_timestamp::timestamp
Result: 2012-10-23 21:18:05.107047
You can get rid of the timezone like this:
select current_timestamp at time zone 'UTC'
Result: "2012-10-24 01:40:10.543251"
But if you really want the timezone back you can do this:
select current_timestamp::timestamp with time zone
Result: 2012-10-23 21:20:21.256478-04
You can yank out what you want with extract:
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20
And this monstrosity:
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'EST';
Result: 2001-02-16 20:38:40
In postgres, you can change the default format mask for datetimes - using the set datestyle option; the available options can be found here (see 8.5.2. Date/Time Output).
Unfortunately, all the available options include the number of seconds - you will therefore need to reformat them either in the query or the application code (if applicable).
to_char() is used to create a string literal. If you want a different timestamp value, use date_trunc():
date_trunc('minute', now())
For converting literal input, use to_timestamp():
to_timestamp('2012-01-03 20:27:53.611489', 'YYYY-MM-DD HH24:MI')
This returns timestamptz. Cast to timestamp [without time zone] by appending ::timestamp (which assumes your current timezone setting), or with the AT TIME ZONE construct to define a time zone explicitly.
To my knowledge, there is no setting in PostgreSQL that would trim seconds from timestamp literals by default.
I have a SQL Builder library that direcltly uses ADO.NET. I have a means of creating a select query with a greater-than-or-equal operator, like:
select *
from book
where book.date_created >= {some date}
My issue is that {some date} is going to always be in the UTC time zone, but it's being compared to the book.date_created column which is a TIMESTAMP(6) WITH TIME ZONE column, which will not be in the UTC timezone.
I can execute the query, but my results are off becuaes of timezone comparisons. My query is for all books where the date_created >= x, but some of the results returned are not greater than x because after subtracting 5 hours for the time zone, they are now less than x. The IDataRecord DateTime fields returned are converted to UTC using DateTime.SpecifyKind()
Can I form my query such that it interprets book.date_created in the UTC timezone?
Note: While I'd love to change my Oracle DB columns to not specify timezones, changing table structures is not something I can do.
Edit:
Currently, {some date} is a SQL Parameter. It's backing datatype is a DateTime with UTC as the timezone. As a parameter, it is a TimestampWithTZ. The Value of the parameter is a DateTime with the kind specified as UTC as well.
Update:
The issue seems to be related to my results set from the IDataRecord. When I pull DateTimes off, I use DateTime.SpecifyKind() to put them in UTC mode. The problem is, the date times come out as DateTimeKind.Unspecified. When converting from Unspecified to UTC, it just drops the timezone and declares it is UTC without changing the underlying value. I'm not sure how to have the IDataRecord pull in the TimeZone value.
You need to use the FROM_TZ function that transforms a TIMESTAMP into a TIMESTAMP WITH TIME ZONE. For example, if you know that your variable is in UTC time (+0:00):
SELECT *
FROM book
WHERE date_created >= from_tz(<timestamp>, '+0:00');
Here's a sample script that shows the behaviour you describe (your local time zone should be set to +1:00):
CREATE TABLE t (tz TIMESTAMP(6) WITH TIME ZONE);
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 +1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 -1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
-- This will return two values instead of one
SELECT *
FROM t
WHERE tz >= to_timestamp('20000101 00:00:00', 'yyyymmdd hh24:mi:ss');
-- This query will return only one row
SELECT *
FROM t
WHERE tz >= from_tz (to_timestamp('20000101 00:00:00',
'yyyymmdd hh24:mi:ss'), '+0:00');
below links will help you.
Datetime Datatypes and Time Zone Support
TIMESTAMP WITH TIME ZONE Data Type
Write Time Zone Aware Code in Oracle
ORACLE timezone summary
Oracle Date and Time data types