Oracle TO_CHAR (timestamp) and timestamp differ in minutes and seconds - sql

SELECT
TO_CHAR((current_timestamp), 'YYYY-MM-DD HH:MM:SS AM') AS curr_time, current_timestamp, dbtimezone
FROM dual;
The result is:
curr_time 2014-05-22 12:05:23 PM
current_timestamp 22-MAY-14 12.39.23.447181000 PM ASIA/CALCUTTA
dbtimezone +00:00
why do curr_time and current_timestamp differ by minutes?

because MM are month, not minutes... (and 05 is... may)
You have to use MI
Change your format to
'YYYY-MM-DD HH:MI:SS AM'

Related

Subtracting time in oracle sql

I am trying to subtract time from each other based on a case condition
but the error is am getting is non-numeric character found where numeric character was expected
HERE IS THE CODE
select
case
when to_date('01-JAN-2019 05:00 AM', 'HH:MI:SS AM') <
to_date('01-JAN-2019 05:00 PM', 'HH:MI:SS AM')
then round((to_date('01-JAN-2019 05:00 AM', 'HH:MI:SS AM') -
to_date('01-JAN-2019 09:00 AM', 'HH:MI:SS AM'))*24,2)
else 0
end late
from dual
One option would be using ISO 8601 standard timestamp format as
select case
when timestamp'2019-01-01 05:00:00' < timestamp'2019-01-01 17:00:00'
then
timestamp'2019-01-01 05:00:00' - timestamp'2019-01-01 09:00:00'
else interval '0' second
end as late
from dual
If you need numeric value for hour only, then consider :
select case
when timestamp'2019-01-01 05:00:00' < timestamp'2019-01-01 17:00:00'
then
extract( hour from timestamp'2019-01-01 05:00:00'
- timestamp'2019-01-01 09:00:00' )
else 0
end as late
from dual
Demo
You have to match date format and format mask:
SQL> select
2 round(
3 (to_date('01-JAN-2019 05:00 AM', 'dd-mon-yyyy HH:MI AM') -
4 to_date('01-JAN-2019 09:00 AM', 'dd-mon-yyyy HH:MI AM')
5 ) * 24, 2) result
6 from dual;
RESULT
----------
-4
SQL>
First conversion format and real string format must match. Next, convert date to timestamp before substracting, so the result is interval. Finally, extract parts needed from the interval
select
extract( day from diff ) Days,
extract( hour from diff ) Hours,
extract( minute from diff ) Minutes
from (
select CAST(to_date('01-JAN-2019 09:00 AM', 'DD-MON-YYYY HH:MI AM') as timestamp)
- CAST(to_date('01-JAN-2019 05:00 AM', 'DD-MON-YYYY HH:MI AM') as timestamp) diff
from dual
)

Date in varchar format of two different types need to be changed to a date in varchar of a specific format

I have a column LOGIN_DATETIME from LOGIN table
The column is varchar2 has values in two format
20-11-2018 01:00:00
20-07-2018 14:00
I need to derive a varchar value from this column with the following format
dd-mmm-yyyy hh:mi am/pm
Result expected
20-Nov-2018 01:00 AM
20-Jul-2018 02:00 PM
I tried like
Format 1:
SELECT TO_CHAR(TO_DATE(LOGIN_DATETIME, 'DD-mm-yyyy hh:mi:ss'), 'dd-mmm-yyyy hh:mi AM')
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
Format 2:
SELECT TO_CHAR(TO_DATE(LOGIN_DATETIME, 'DD-mm-yyyy hh:mi'), 'dd-mmm-yyyy hh:mi AM')
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
It's not working.
You could use this only one query:
SELECT
CASE
WHEN LENGTH(login_datetime) = 19 THEN TO_CHAR(TO_DATE(login_datetime, 'DD-MM-YYYY HH24:MI:SS'), 'DD-Mon-YYYY HH:MI AM')
WHEN LENGTH(login_datetime) = 16 THEN TO_CHAR(TO_DATE(login_datetime, 'DD-MM-YYYY HH24:MI'), 'DD-Mon-YYYY HH:MI AM')
END AS login_datetime
FROM login
ORDER BY 1;
Tested ok in rextester
Use case and select format based on field length
SELECT
CASE WHEN LENGTH(LOGIN_DATETIME) = 16 THEN TO_CHAR(TO_DATE(LOGIN_DATETIME, 'dd-mm-yyyy hh24:mi'), 'dd-mm-yyyy HH:mi AM')
ELSE TO_CHAR(TO_DATE(LOGIN_DATETIME, 'dd-mm-yyyy hh:mi:ss'), 'dd-mm-yyyy HH:mi AM')
END
FROM LOGIN
WHERE LOGIN_DATETIME is not null;
That was easy one I dunno the syntax of SQL it was mon not mmm in date format
SELECT
TO_char(to_timestamp (LOGIN_DATETIME, 'DD-MM-RRRR HH24:MI:SS.FF'), 'DD-Mon-YYYY HH12:mi AM')
from LOGIN
WHERE LOGIN_DATETIME is NOT null;
OR
SELECT
TO_char(to_timestamp (LOGIN_DATETIME, 'DD-MM-YYYY HH24:MI:SS.FF'), 'DD-Mon-YYYY HH12:mi AM')
from LOGIN
WHERE LOGIN_DATETIME is NOT null;
The both formats work in one query itself.

How to grab the value for the previous hour when the data type is TIMESTAMP with TIMEZONE

So I have some logic that will try to grab the Value (VALUE) correlated to the previous hour if the criteria are met. The HOUR column is a TIMESTAMP with TIME ZONE column. I figured I can run the following query but got an ORA-00932 inconsistent datatypes: expected TIMESTAMP WITH TIME ZONE got NUMBER error. Is there some sort of conversion function I have to add to my 'timestamp with timezone' value?
Below is my query code:
SELECT MAX(VALUE)
FROM VALUE V
WHERE CODE = 'HI'
AND HR = '15-JAN-17 05.00.00.000000000 AM' - (1/24);
Thanks in advance.
'15-JAN-17 05.00.00.000000000 AM' is a string, not a timestamp. You can convert it to a timestamp (with no time zone) as #D-Shih suggested, but you should specify the format mask and the date language rather than relying on NLS settings:
AND HR = to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24);
or if it's a fixed value (presumably it isn't, or you could just change that literal):
AND HR = timestamp '2017-01-15 05:00:00' - (1/24);
Subtracting a number of days from a timestamp gives you a date result, so you perhaps really want to do:
AND HR = timestamp '2017-01-15 05:00:00' - interval '1' hour;
This now stays as a timestamp, but you have no time zone information. If you know the time zone you can include it in string literal and format mask, or in the timestamp literal, e.g.:
AND HR = timestamp '2017-01-15 05:00:00 America/Los_Angeles' - (1/24);
or from your original string, if that's all you have to work with, you can use from_tz():
AND HR = from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour;
Doing the interval subtraction last should mean that it handles DST properly.
Demo of the various conversions, starting from your string value:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF1';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF1 TZR TZD';
select
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') as a_timestamp,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - (1/24) as b_date,
to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH') - interval '1' hour as c_timestamp,
from_tz(to_timestamp('15-JAN-17 05.00.00.000000000 AM', 'DD-MON-RR HH.MI.SS.FF AM',
'NLS_DATE_LANGUAGE=ENGLISH'), 'America/Los_Angeles') - interval '1' hour as d_timestamp_tz
from dual;
A_TIMESTAMP B_DATE C_TIMESTAMP D_TIMESTAMP_TZ
--------------------- ------------------- --------------------- ---------------------------------------------
2017-01-15 05:00:00.0 2017-01-15 04:00:00 2017-01-15 04:00:00.0 2017-01-15 04:00:00.0 AMERICA/LOS_ANGELES PST
use TO_TIMESTAMP to let '15-JAN-17 05.00.00.000000000 AM' to datetime then minus one hour.
SELECT MAX(VALUE)
FROM VALUE V
WHERE CODE = 'HI'
AND HR = TO_TIMESTAMP('15-JAN-17 05.00.00.000000000 AM','DD-MON-RR HH.MI.SS.FF AM') - (1/24);

Oracle how to convert time in UTC to the local time (offset information is missing)

I have a table which contains a date column. I think that the date in that column is saved in UTC.
I would like when the date is retrieved that it is printed in local time. That means when I call the date from Germany, the result should be something like this:
2015-04-29 11:24:06 +0200UTC EUROPE/BERLIN
I tried the following sql:
SELECT TO_CHAR(CAST(dateColum as TIMESTAMP WITH LOCAL TIME ZONE), 'YYYY-MM-DD HH24:MI:SS TZR') from myTable;
the result looks like this:
2015-04-29 11:24:06 EUROPE/BERLIN
+/- offset is missing.
Any idea?
Oracle Setup:
CREATE TABLE table_name ( value ) AS
SELECT DATE '2016-07-13' FROM DUAL;
Query:
SELECT TO_CHAR(
FROM_TZ( CAST( value AS TIMESTAMP ), 'UTC' )
AT TIME ZONE 'EUROPE/BERLIN',
'YYYY-MM-DD HH24:MI:SS TZH:TZM TZR'
) AS berlin_time
FROM table_name;
Output:
BERLIN_TIME
----------------------------------------
2016-07-13 02:00:00 +02:00 EUROPE/BERLIN
Query 2:
SELECT TO_CHAR(
FROM_TZ( CAST( value AS TIMESTAMP ), 'UTC' ) AT LOCAL,
'YYYY-MM-DD HH24:MI:SS TZH:TZM TZR'
) AS local_time
FROM table_name;
Output:
LOCAL_TIME
----------------------------------------
2016-07-13 02:00:00 +02:00 EUROPE/BERLIN

12 Hours format in oracle

I have function that receive user name and return time in , time out and username in one column.
I used substring to make it into 3 columns and time out return as 24 hours format and I need it into 12 hours format.
select substr( FUN1('username'),1,5) TIMEIN ,
substr( FUN1('username'),7,6) TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;
Use the TO_CHAR function
SELECT TO_CHAR(substr( FUN1('username'),1,5), 'DD-MM-YYYY HH:MI:SS AM') TIMEIN,
TO_CHAR(substr( FUN1('username'),7,6), 'DD-MM-YYYY HH:MI:SS AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME
FROM dual;
You can do this by converting the TIMEOUT to a date using TO_DATE assuming the time is in 24 hours format, and then re-converting it to a string using TO_CHAR with the format as 12 hours format -
select to_char(to_date('13:00', 'HH24:MI'),'HH:MI AM') from dual;
Here's how your SQL in the question would look like for the TIMEOUT -
select substr( FUN1('username'),1,5) TIMEIN ,
to_char(to_date(substr( FUN1('username'),7,6), 'HH24:MI'),'HH:MI AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;