Convert epoch to date in Oracle - oracle

Was wondering if anyone could help with precision time conversion.
Sample: 1501646399999 which is GMT: Wednesday, August 2, 2017 3:59:59.999 AM
I used the below query, but it always rounds off to 02-AUG-17 04:00:00. Can anyone please guide me
select TO_TIMESTAMP('1970-01-01 00:00:00.000', 'YYYY-MM-DD hh24:mi:SS.FF3') + ((1/86400000) * 1501646399999)
from dual;

The problem is that you're adding a number to your fixed timestamp, which is causing that timestamp to be implicitly converted to a date - which doesn't have sub-second precision.
If you add an interval instead then it stays as a timestamp:
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
select TO_TIMESTAMP('1970-01-01 00:00:00.000', 'YYYY-MM-DD hh24:mi:SS.FF3')
+ numtodsinterval(1501646399999/1000, 'SECOND')
from dual;
TO_TIMESTAMP('1970-01-0
-----------------------
2017-08-02 03:59:59.999
Incidentally, you could slightly simplify your query with a timestamp literal:
select TIMESTAMP '1970-01-01 00:00:00' + numtodsinterval(...)
You may also want to check if you should be declaring that timestamp as being UTC, and converting back to local time zone after adding the epoch value; or leaving it explicitly as UTC but as a timestamp with time zone value. It depends exactly what that number is supposed to represent. (You said it's GMT/UTC, but still...)

Related

Oracle Date Issue in Where Clause

I am unable to get the date column to respect the where clause. Regardless what I do, it does not filter on date. I have tried all combinations of to_char and to_date in vain.
HAVING TO_CHAR(PAYMASTR.CHECK_DATE,'MM/DD/YYYY') > '01/01/2021'
I have also tried the code below with all combinations of to_char and to_date.
HAVING PAYMASTR.CHECK_DATE >= TO_DATE('01-01-2021 12:00:00 AM',
'MM-DD-YYYY HH:MM:SS AM')
The check_date of of type DATE.
Result set:
|COMPANY|EMPLOYEE|PAY_SUM_GRP|PAY_GRADE RATE|WAGE_AMOUNT|NET_PAY_AMT|GROSS_PAY|CHECK_DATE|
|-------|--------|-----------|--------------|-----------|-----------|---------|----------|
|2|5|REG 09|21.98|175.84|1459.96|2263.19|1/19/2007 12:00:00 AM|
|2|5|REG 09|21.98|175.84|1663.93|2589.43|1/5/2007 12:00:00 AM|
If CHECK_DATE column's datatype is DATE (should be! If it is VARCHAR2, you're doing it wrong!), then
having check_date > date '2021-01-01'
i.e. compare date to date literal.
Second code you posted is almost OK:
HAVING PAYMASTR.CHECK_DATE >= TO_DATE('01-01-2021 12:00:00 AM', 'MM-DD-YYYY HH:MI:SS AM')
--
MI for minutes; MM is for month
I found this article on code project that did the trick for me. I was struggling really hard to get the query to respect the date parameter in the queru. Setting the session to NLS_DATE_FORMAT worked. Not sure what other implications it may have. Will have to talk to the DBA.
Code Project
It's all about how Oracle stores and works with date DATATYPE
The date has seven components
Century, year, month, day, hour, minute, seconds
and all these components take seven bytes of storage.
Whenever you fetch a Date column from a table, the date value is formatted in a more readable form and this format is set in the nls_date_format parameter.
I am assuming you are grouping by CHECK_DATE otherwise you need to add this date filter with the WHERE clause.
So first check the datatype of your column CHECK_DATE
If it is date then
HAVING CHECK_DATE >= TO_DATE('01-01-2021', 'MM-DD-YYYY')
You don't have to provide hours, minutes, and seconds if omitted hours are rounded to 12 AM or 00 if the 24-hour format is used;
Or if you want to have hours as well then you used MM instead of MI for minutes.
HAVING CHECK_DATE >= TO_DATE('01-01-2021 00:00:00', 'MM-DD-YYYY HH24:MI:SS')
And this does not make sense
HAVING TO_CHAR(PAYMASTR.CHECK_DATE,'MM/DD/YYYY') > '01/01/2021'
You want to compare dates not characters and to_char will provide you a character string that has no sense of comparing with another string '01/01/2021'.
So if you are not grouping by CHECK_DATE user filter condition with WHERE clause
or check the datatype of CHECK_DATE if it is not DATE change it to DATE.

Converting Time Interval to actual time in AM PM in Oracle

How can i convert the result of select statement of time interval field in respective time in Am/Pm format.
My Field is:
Interval Day(2) To Second(6)
I tried this:
select To_Char(Att_EntranceTime , 'HH:MI AM') From EMPLOYEEATTENDENCETABLE;
however this does not help me, i have also tried to add the basetime from systime to my interval field but that did not help.. can someone suggest me what to do?
Intervals can't be directly formatted, as you've discovered. You can add your interval to any date which has its time set to midnight, and then format the resulting date to show the time in your desired format. For example you could add it to today's date using trunc(sysdate):
to_char(trunc(sysdate) + my_interval, 'HH:MI AM')
You need to truncate it to set the time to midnight; otherwise the result will be your interval plus the current system time.
Or you can use any fixed date; here's an example with some dummy data set-up:
create table my_table (my_interval interval day(2) to second(6));
insert into my_table (my_interval) values (interval '0 12:34:56.78' day to second);
insert into my_table (my_interval) values (interval '99 01:02:03.456' day to second);
select my_interval, to_char(date '1970-01-01' + my_interval, 'HH:MI AM') as formatted
from my_table;
MY_INTERVAL FORMATTED
-------------------- ---------
+00 12:34:56.780000 12:34 PM
+99 01:02:03.456000 01:02 AM
The second value shows a potential problem. Your interval is defined to allow a two-digit day number, which means the interval can span anything less than 100 days. If you only extract the time portion you lose that information about the number of days. That may be what you want to happen though. If the interval is supposed to be representing a time of day, which wanting to show AM/PM implies - and it's unusual to store an actual time separate from its date - then having or allowing a number of days seems strange.

Converting a stored UTC time in Oracle 10g to local time

I have a varchar2(20) column with a value like '2015-01-26T20:29:51Z'.
I successfully convert it to a date with to_date(dEnteredDate,'YYYY-MM-DD"T"HH24:MI:SS"Z"')
I wish to convert it to local time by subtracting my SessionTimeZone, currently -07:00 and have a regular date with time, no timezone info.
I do this in MS SQL with;
SET #diff = datediff(hh,GetUTCDate(), GetDate());
SET #dlocal = DATEADD(hh, #diff, #UTCDateTime)
How can I accomplish the same in Oracle 10g?
You can do it like this:
select to_timestamp(dEnteredDate,'YYYY-MM-DD"T"HH24:MI:SS"Z"')- interval '7' hour from test_3;
Here - interval '7' hour will subtract the required time difference and give you the desired result without timezone.
You can do it like this
select cast(to_timestamp_TZ(dEnteredDate||' UTC','YYYY-MM-DD"T"HH24:MI:SS"Z" tzr') at local as date)
from ...

Using Oracle to_date function for date string with milliseconds

I have to perform some inserts into an Oracle DB. I have some dates
in the following format
'23.12.2011 13:01:001'
Following the documentation I wrote inserts to_date as follows:
to_date('23.12.2011 13:01:01', 'DD.MM.YYYY HH24:MI:SS')
which works properly. Now I have dates with milliseconds with the format
'23.12.2011 13:01:001'
I've tried the following:
to_date('23.12.2011 13:01:001', 'DD.MM.YYYY HH24:MI:SSFF3')
which is incorrect (delivers an error 01821. 00000 - "date format not recognized").
Which "String" should I use for this format with milliseconds?
An Oracle DATE does not store times with more precision than a second. You cannot store millisecond precision data in a DATE column.
Your two options are to either truncate the string of the milliseconds before converting it into a DATE, i.e.
to_date( substr('23.12.2011 13:01:001', 1, 19), 'DD.MM.YYYY HH24:MI:SS' )
or to convert the string into a TIMESTAMP that does support millisecond precision
to_timestamp( '23.12.2011 13:01:001', 'DD.MM.YYYY HH24:MI:SSFF3' )
TO_DATE supports conversion to DATE datatype, which doesn't support milliseconds. If you want millisecond support in Oracle, you should look at TIMESTAMP datatype and TO_TIMESTAMP function.
Hope that helps.
For three digits millisecond:
TO_CHAR(LN_AUTOD_UWRG_DTTM,'MM/DD/YYYY HH24:MI:SS.FF3')
For six digits millisecond:
TO_CHAR(LN_AUTOD_UWRG_DTTM,'MM/DD/YYYY HH24:MI:SS.FF'),
You can try this format SS.FF for milliseconds:
to_timestamp(table_1.date_col,'DD-Mon-RR HH24:MI:SS.FF')
For more details:
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions193.htm
You have to change date class to timestamp.
String s=df.format(c.getTime());
java.util.Date parsedUtilDate = df.parse(s);
java.sql.Timestamp timestamp = new java.sql.Timestamp(parsedUtilDate.getTime());

Oracle current_timestamp to seconds conversion

We are using Oracle database.
In our table timestamp is stored as seconds since 1970, how can I convert the time stamp obtained through current_timestamp() function to seconds
This would do it:
select round((cast(current_timestamp as date) - date '1970-01-01')*24*60*60) from dual
Though I wouldn't use current_timestamp if I was only interested in seconds, I would use SYSDATE:
select round((SYSDATE - date '1970-01-01')*24*60*60) from dual
Maybe not completely relevant. I had to resolve other way around problem (e.g. Oracle stores timestamp in V$RMAN_STATUS and V$RMAN_OUTPUT) and I had to convert that to date/timestamp. I was surprised, but the magic date is not 1970-01-01 there, but 1987-07-07. I looked at Oracle's history and the closest date I can think of is when they ported Oracle products to UNIX. Is this right?
Here's my SQL
SELECT /*+ rule */
to_char(min(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON-YYYY HH24:MI:SS') start_tm
, to_char(to_char(max(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON HH24:MI:SS')) end_tm
FROM V$RMAN_STATUS
START WITH (RECID, STAMP) =
(SELECT MAX(session_recid),MAX(session_stamp) FROM V$RMAN_OUTPUT)
CONNECT BY PRIOR RECID = parent_recid ;
I needed to send timestamp to GrayLog via GELF from Oracle DB. I tried different versions and solutions but only one worked correctly.
SQL:
SELECT REPLACE((CAST(dat AS DATE) - TO_DATE('19700101', 'YYYYMMDD')) * 86400 + MOD(EXTRACT(SECOND FROM dat), 1), ',', '.') AS millis
FROM (SELECT SYSTIMESTAMP AT TIME ZONE 'GMT' AS dat FROM dual)
The result for Systmiestamp
2018/12/18 19:47:29,080988 +02:00
will be
1545155249.080988

Resources