Current sysdate and time - sql

First, I am from India and am working for US customers so I am using US(America) database.
I have tried to display current Sysdate and time but it's showing US time. but I want to display Indian current time.
select sysdate from dual;

SELECT TO_CHAR
(SYSDATE, 'MM-DD-YYYY HH24:MI:SS') "NOW"
FROM DUAL;
NOW
-------------------
04-13-2001 09:45:51

Try to change your system time to Indian time zone. I think this should work.
Also try to change the your session time_zoe
ALTER SESSION SET TIME_ZONE = 'Asia/Calcutta';

try this i hope it helps
https://community.oracle.com/thread/3958062
https://docs.oracle.com/database/121/SQLRF/functions117.htm#SQLRF00671
The following example illustrates that CURRENT_TIMESTAMP is sensitive to the session time zone:
ALTER SESSION SET TIME_ZONE = '-5:0';
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;
SESSIONTIMEZONE CURRENT_TIMESTAMP
--------------- ---------------------------------------------------
-05:00 04-APR-00 01.17.56.917550 PM -05:00
ALTER SESSION SET TIME_ZONE = '-8:0';
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;
SESSIONTIMEZONE CURRENT_TIMESTAMP
--------------- ----------------------------------------------------
-08:00 04-APR-00 10.18.21.366065 AM -08:00

Related

remove milliseconds from datetime type

Trying to remove the milliseconds and the pm/am from the datetime field using Oracle SQL.
My query is:
select created_dt from mydatabase
Output is:
09-NOV-21 12.18.40.490000000 PM
I tried using to_char(created_dt, 'dd-mm-yy hh24:mi:ss') then using to_timestamp to convert back to datetime type but the milliseconds showing again.
A TIMESTAMP data type is stored in a table as a binary data-type with 1-byte for each of century, year-of-century, month, day, hour, minute and second and has up to 6 bytes for fractional seconds. It is NEVER stored with any particular format.
If you want to change the number of fractional digits in a timestamp then you need to use CAST:
SELECT CAST(created_dt AS TIMESTAMP(0))
FROM mydatabase
However, you could just convert it to a DATE (which also has year-to-second components but no fractional seconds):
SELECT CAST(created_dt AS DATE)
FROM mydatabase
Once you have done that then whatever client application you are using (SQL/Plus, SQL Developer, Java, C#, PHP, etc.) will still use its default rules for displaying the TIMESTAMP (or DATE) and those rules may display a certain number of fractional seconds.
If you are using SQL/Plus or SQL Developer (but not if you are using Java, C#, PHP, etc.) then the default format is controlled by the NLS_TIMESTAMP_FORMAT session parameter.
You can alter this using:
-- Display with precision of the data type
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';
-- Display with 6-digits precision
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF6';
-- Display with no fractional seconds.
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
But, if you want a consistent method of formatting a TIMESTAMP then use TO_CHAR.
How the DATE or TIMESTAMP data types are stored can't be changed.
But you can change how a query outputs a TIMESTAMP by default for the session.
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'
Example:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MON-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
select ts
, CAST(ts AS DATE) dt
, CAST(ts AS TIMESTAMP WITH TIME ZONE) AS tstz
from
(
select
to_timestamp('2021-11-30 23:30:45.123456789', 'YYYY-MM-DD HH24:MI:SS.FF') AS ts
from dual
) q
TS | DT | TSTZ
:------------------ | :------------------- | :-------------------------------
2021-11-30 23:30:45 | 2021-NOV-30 23:30:45 | 30-NOV-21 23.30.45.123457 +00:00
db<>fiddle here

Oracle Spool file via CMD command deliver more Data than expected

i have a Oracle Table "Sales" with columns ID,Sales,TIMESTAMP. Data looks like this:
ID Sales TimeStamp
1 30 2018-08-20 00:00:00.989900 +02:00
1 35 2018-08-21 05:00:00.989900 +02:00
...
1 35 2018-08-27 05:00:00.989900 +02:00
i created a Talend Job to execute a SQL Spool file in CMD mode to export a Query into csv. The Spoolfile look like this:
alter session set NLS_TIMESTAMP_TZ_FORMAT ='YYYY-MM-DD HH24:mi:ss.ff6 TZH:TZM';
alter session set NLS_TIMESTAMP_FORMAT ='YYYY-MM-DD HH24:mi:ss.ff6';
alter session set NLS_DATE_FORMAT ='YYYY-MM-DD';
alter session set NLS_NUMERIC_CHARACTERS ='.,';
spool C:/test.csv
SET ECHO OFF
SET ...
SELECT * FROM Sales where timestamp< to_timestamp('2018-08-25 00:00:00.0000000','YYYY-MM-DD HH24:mi:ss:ff66 TZH:TZM')
when the TalendJob runs the Query on CMD mode, it gives me more data than expected with the Data to '2018-08-25 01:00:00'.
when i execute the SQL Query on Oracle Server manually, it gives correct Data to '2018-08-25 00:00:00'
==> Query on CMD on Talend give 1 hours of Data more than expected.
i don't really understand why that Problem happens.
My assumption is the Problem Timestamp in the Query "'2018-08-25 00:00:00.0000000'". this Timestamp has no time zone. but i am not sure.
can you please help me with this Problem?
Thankyou.
The manual query and the Talend query seem to be running in sessions with different time zones.
You aren't specifying a time zone in your fixed value, despite having TZH:TZM in the format model; and in fact you can't with to_timestamp():
select to_timestamp('2018-08-25 00:00:00.0000000 +02:00','YYYY-MM-DD HH24:mi:ss:ff6 TZH:TZM')
from dual;
ORA-01821: date format not recognized
because that function gives you a plain timestamp:
alter session set NLS_TIMESTAMP_FORMAT ='YYYY-MM-DD HH24:mi:ss.ff6';
alter session set NLS_TIMESTAMP_TZ_FORMAT ='YYYY-MM-DD HH24:mi:ss.ff6 TZH:TZM';
select to_timestamp('2018-08-25 00:00:00.0000000','YYYY-MM-DD HH24:mi:ss:ff6 TZH:TZM')
as plain_timestamp
from dual;
PLAIN_TIMESTAMP
--------------------------
2018-08-25 00:00:00.000000
When you use that plain timestamp in a comparison with your table column, which is a timestamp with time zone, there is an implicit conversion into the session time zone. You can see the effect that has by manually setting it:
alter session set time_zone = 'Europe/London';
select cast(
to_timestamp('2018-08-25 00:00:00.0000000','YYYY-MM-DD HH24:mi:ss:ff6 TZH:TZM')
as timestamp with time zone
) as timestamp_with_session_zone
from dual;
TIMESTAMP_WITH_SESSION_ZONE
---------------------------------
2018-08-25 00:00:00.000000 +01:00
alter session set time_zone = 'America/New_York';
select cast(
to_timestamp('2018-08-25 00:00:00.0000000','YYYY-MM-DD HH24:mi:ss:ff6 TZH:TZM')
as timestamp with time zone
) as timestamp_with_session_zone
from dual;
TIMESTAMP_WITH_SESSION_ZONE
---------------------------------
2018-08-25 00:00:00.000000 -04:00
So, to be getting different data from your two sessions, that comparison is using a different value, therefore the session time zones must be different.
The simple fix is to specify the time zone explicitly in your fixed value, but you need a different function to avoid the error seen earlier; and preferably with a region instead of an offset to allow for daylight savings (assuming the values in your table are region-based too):
select to_timestamp_tz('2018-08-25 00:00:00.0000000 Europe/Berlin','YYYY-MM-DD HH24:mi:ss:ff6 TZR')
as timestamp_with_berlin_zone
from dual;
TIMESTAMP_WITH_BERLIN_ZONE
---------------------------------
2018-08-25 00:00:00.000000 +02:00
or you could use a timestamp literal:
select timestamp '2018-08-25 00:00:00.0 Europe/Berlin' as timestamp_with_berlin_zone
from dual;
which gets the same value.
i haved tried to format the time zone in the Query with to_timestamp_tz(substr('2018-08-25 00:00:00.0000000'),1,25), 'YYYY-MM-DD HH24:mi:ss.ff6 TZH:TZM' at time zone 'berlin/europe') as input_timestamp but it stills gives me more data than expected.
Ignoring the odd substr() which just strips the last two zeros off what is already a fixed string, if you do:
select to_timestamp_tz('2018-08-25 00:00:00.0000000', 'YYYY-MM-DD HH24:mi:ss.ff6 TZH:TZM')
at time zone 'Europe/Berlin' as timestamp_with_wrong_time
from dual;
you get (with my session still on New York time for greater effect)
TIMESTAMP_WITH_WRONG_TIME
---------------------------------
2018-08-25 06:00:00.000000 +02:00
The time zone is now what you expected, but the time is wrong. You have much the same problem as before. You're still converting the fixed value with no time zone supplied into a timestamp with time zone, so it's implicitly using the session time zone:
select to_timestamp_tz('2018-08-25 00:00:00.0000000', 'YYYY-MM-DD HH24:mi:ss.ff6 TZH:TZM')
as timestamp_with_wrong_time
from dual;
TIMESTAMP_WITH_WRONG_TIME
---------------------------------
2018-08-25 00:00:00.000000 -04:00
and then the at timezone 'Europe/Berlin' just gives that exact same point in universal time - midnight in New York, which is 04:00 UTC - but in Berlin local time, which is 06:00. It's the same point of time, just viewed from different places/time zone.
Again, you just need to specify the time zone for the fixed time you're using for the comparison - as timestamp '2018-08-25 00:00:00.0 Europe/Berlin'.

sysdate and dbtimezone different in Oracle Database

With this query: select sysdate from dual;
the result is: 27-09-2018 07:50:50 -- this UK time
with : Select dbtimezone from dual;
output: +10:00
I want the sysdate to be of the same timezone of dbtimezone
I was trying to do it with alter database set time_zone='AEST', but i'm bit confused if this is the right solution.
Any help most appreciated.
Thanks.
It is a common misunderstanding that DBTIMEZONE is the time zone for SYSDATE and SYSTIMESTAMP
SYSDATE and SYSTIMESTAMP are returned in time zone of the operating system on which the database server resides.
DBTIMEZONE is the (internal) time zone of TIMESTAMP WITH LOCAL TIME values. I don't know any practical use of it. Note, you cannot change DBTIMEZONE on your database if the database contains a table with a TIMESTAMP WITH LOCAL TIME ZONE column and the column contains data.
If you want current time at DBTIMEZONE run
select SYSTIMESTAMP AT TIME ZONE DBTIMEZONE
from dual;
CURRENT_TIMESTAMP AT TIME ZONE DBTIMEZONE is also working.
See also How to handle Day Light Saving in Oracle database
SYSDATE returns the current date and time set for the operating system on which the database server resides.
CURRENT_DATE returns the current date in the session time zone.
show parameter nls_date_format
NAME TYPE VALUE
------------------------------ ----------- ------------------------
nls_date_format string dd-Mon-yyyy hh24:mi:ss
select sysdate, current_date, dbtimezone from dual;
SYSDATE CURRENT_DATE DBTIME
-------------------- -------------------- ------
27-Sep-2018 08:16:00 27-Sep-2018 08:16:00 +00:00
alter session set time_zone = '+08:00';
Session altered.
select sysdate, current_date, dbtimezone from dual;
SYSDATE CURRENT_DATE DBTIME
-------------------- -------------------- ------
27-Sep-2018 08:13:06 27-Sep-2018 15:13:06 +00:00

Problems with sys_extract_utc and summer/wintertime

I have a problem converting a timestamp to UTC.
Our System Timezone is 'Europe/Berlin'. The actual ZoneOffset at the moment (as it is not summertime yet) is +1. This ZoneOffset will change on March 26 2017 from +1 to +2. (wintertime to summertime).
If I use the function sys_extract_utc('2017.03.27 00:00') then the offset which now applies is being used for the calculation. So the result is '2017.03.26 23:00', but I expected the result '2017.03.26 22:00'.
How can I get the correct result?
You said
the offset which now applies is being used for the calculation
That isn't quite true. Your session time zone seems to be set to a +01:00 offset instead of a region name:
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set TIME_ZONE = '+01:00';
select sys_extract_utc(timestamp '2017-03-27 00:00:00') from dual;
SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 23:00:00
The timestamp literal being supplied has no time zone information, so it's implicitly converted to the session time zone as part of the function call. An offset has no knowledge of summer/wintertime, so no adjustment is (or can be) made. You'd see the same thing if you ran that query after the 27th.
If you set the session time zone to the region instead then you'll get the correct result.
alter session set TIME_ZONE = 'Europe/Berlin';
select sys_extract_utc(timestamp '2017-03-27 00:00:00') from dual;
SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 22:00:00
You may be able to do that automatically by modifying your operating system environment variables; if not then you can set it in your client or (for SQL*Plus) in a .login or .glogin setup file.
If you're starting from a value which actually has a region, i.e. is a timestamp with time zone data type, then the session time zone doesn't matter:
alter session set TIME_ZONE = '+01:00';
select sys_extract_utc(timestamp '2017-03-27 00:00:00 Europe/Berlin') from dual;
SYS_EXTRACT_UTC(TIM
-------------------
2017-03-26 22:00:00

Oracle sql timezone issue

My requirement here is to get time in GMT/UTC from a date type column. But when I use cast to cast date to timestamp, it is using US/Pacific timezone as reference though session timezone is set to GMT. So unless I use from_tz, I am not seeing desired result. Is there any other timezone setting in oracle sql that I need to modify to take GMT as reference always?
alter session set time_zone='+00:00';
select sessiontimezone from dual;
select current_timestamp from dual;
select sys_extract_utc(cast (sysdate as timestamp)) from dual;
select sys_extract_utc(from_tz(cast (sysdate as timestamp), '-07:00')) from dual;
select sys_extract_utc(current_timestamp) from dual;
Session altered.
SESSIONTIMEZONE
---------------------------------------------------------------------------
+00:00
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
11-APR-16 08.46.42.292173 AM +00:00
SYS_EXTRACT_UTC(CAST(SYSDATEASTIMESTAMP))
---------------------------------------------------------------------------
11-APR-16 01.46.42.000000 AM
SYS_EXTRACT_UTC(FROM_TZ(CAST(SYSDATEASTIMESTAMP),'-07:00'))
---------------------------------------------------------------------------
11-APR-16 08.46.42.000000 AM
SYS_EXTRACT_UTC(CURRENT_TIMESTAMP)
---------------------------------------------------------------------------
11-APR-16 08.46.42.295310 AM
Tasks table has a date type column called task_started. I am looking to get UTC time from this date field. As part of that I was trying to alter session timezone to GMT while inserting the data so that I can simply cast it back to timestamp which is not working.
select task_started from tasks where rownum <2;
TASK_STAR
---------
10-APR-16
desc tasks;
Name Null? Type
----------------------------------------- -------- ----------------------------
...
TASK_STARTED DATE
...
This is a demo using data inserted using sysdate on a system on London time, so currently on BST (+01:00). The difference is smaller than you'd see on the west coast but the same things apply.
Mimicking your table, you can see that the session time zone has no effect on the inserted value since sysdate uses the database server time, not the session (client) time (as explained here):
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZH:TZM';
create table tasks (id number, task_started date);
alter session set time_zone='America/Los_Angeles';
insert into tasks (id, task_started) values (1, sysdate);
select task_started, cast(task_started as timestamp) as ts
from tasks where rownum < 2;
TASK_STARTED TS
------------------- -----------------------
2016-04-11 11:55:59 2016-04-11 11:55:59.000
alter session set time_zone = 'UTC';
select task_started, cast(task_started as timestamp) as ts
from tasks where rownum < 2;
TASK_STARTED TS
------------------- -----------------------
2016-04-11 11:55:59 2016-04-11 11:55:59.000
So that's the BST time in both cases. There isn't any session or database setting that will show you a date (or timestamp, without a time zone) converted to a specific time zone automatically. The database doesn't know what that stored date/time represents unless you tell it. It doesn't know or case if you use sysdate, current_date, or a date literal; at the point the data is inserted into the table it has no time zone information at all.
To get the UTC equivalent you need to use from_tz to declare that the stored value represents a specific time zone; then you can use at time zone (which keeps the time zone info) or sys_extract_utc (which doesn't) on that to convert it; and optionally cast back to a date:
select from_tz(cast(task_started as timestamp), 'Europe/London') as db_tstz,
from_tz(cast(task_started as timestamp), 'Europe/London') at time zone 'UTC' as utc_tstz,
sys_extract_utc(from_tz(cast(task_started as timestamp), 'Europe/London')) as utc_ts,
cast(sys_extract_utc(from_tz(cast(task_started as timestamp), 'Europe/London')) as date) as utc_date
from tasks where rownum < 2;
DB_TSTZ UTC_TSTZ UTC_TS UTC_DATE
------------------------------ ------------------------------ ----------------------- -------------------
2016-04-11 11:55:59.000 +01:00 2016-04-11 10:55:59.000 +00:00 2016-04-11 10:55:59.000 2016-04-11 10:55:59
I've used the time zone region name so it takes care of summer time for me; you could use dbtimezone but that would always use -08:00, and as you showed in the question you need to use -07:00 at the moment. ANd you could use sessiontimezone but then you have to remember to set that properly. Obviously in your case you'd use your local region, e.g. America/Los_Angeles, instead of Europe/London.
And from that you can get the epoch, via an interval by comparing timestamps or more simply from comparing dates:
select sys_extract_utc(from_tz(cast(task_started as timestamp), 'Europe/London'))
- timestamp '1970-01-01 00:00:00' as diff_interval,
cast(sys_extract_utc(from_tz(cast(task_started as timestamp), 'Europe/London')) as date)
- date '1970-01-01' as diff_days,
86400 *
(cast(sys_extract_utc(from_tz(cast(task_started as timestamp), 'Europe/London')) as date)
- date '1970-01-01') as epoch
from tasks where rownum < 2;
DIFF_INTERVAL DIFF_DAYS EPOCH
---------------- --------- -----------
16902 10:55:59.0 16902.46 1460372159
If you put 1460372159 into an online converter (there are many) it will show the UTC time.