In Oracle, I have column named Create_date with data returning as 1400003659, 1400072380, and 1403796514 as examples. The column type is NOT NULL NUMBER(15). I'm trying to edit my SELECT statement to return these values as dates (or are these dates and times?).
I've tried the below, but all are returning errors:
SELECT to_date(Create_date, 'YYMMDD'),
SELECT to_date(to_char(Create_date), 'YYMMDD'),
SELECT to_timestamp(Create_date, 'YYMMDD'),
SELECT to_date(LPAD(Create_date, 15, '0'), 'YYMMDD'),
SELECT to_date(LPAD(Create_date), 'YYMMDD'),
An example error message I'm receiving:
SQL Error: ORA-01843: not a valid month
01843. 00000 - "not a valid month"
This looks like a unix timestamp which is the number of seconds since 1/1/1970.
If you want just the date, you need to calculate the number of days and add it to 1/1/1970 like so:
to_date('1970-01-01','YYYY-MM-DD') + numtodsinterval(1400003659,'SECOND')
If you want to retain the timestamp, you can do so like this:
to_char(to_date('1970-01-01','YYYY-MM-DD') + numtodsinterval(1400003659,'SECOND'),'YYYY-MM-DD HH24:MI:SS')
See this for more information.
You need to know what that number means.
If those are UNIX dates (number of second since January 1, 1970), then you can use simple date arithmetic from that baseline by adding the value / 86400 (seconds in a day) to jan 1 1970:
select to_date('01011970','ddmmyyyy') + (1400003659/86400) from dual;
returns: 13/05/2014 5:54:19 PM
Try like this:
select to_date('01-01-1970 1:00:00','MM-DD-YYYY HH24:Mi:SS') + (1400003659/86400) from dual;
FIDDLE DEMO
The answers are not precise! UNIX time is seconds since 1970-01-01 00:00:00 UTC!
So, unless your database server runs on UTC you should do it like this:
SELECT
(TIMESTAMP '1970-01-01 00:00:00' AT TIME ZONE 'UTC'
+ 1400003659 * INTERVAL '1' SECOND) AT LOCAL
FROM dual;
or
SELECT
(TIMESTAMP '1970-01-01 00:00:00' AT TIME ZONE 'UTC'
+ numtodsinterval(1400003659,'second')) AT LOCAL
FROM dual;
or to get the time at time zone of database server's operating system
SELECT
(TIMESTAMP '1970-01-01 00:00:00' AT TIME ZONE 'UTC'
+ numtodsinterval(1400003659,'second')) AT TO_CHAR(SYSTIMESTAMP, 'tzr')
FROM dual;
Related
I have these varchar : 20211026231735.
So I would like a query to substract actual sysdate to that date and convert the substraction to DAY HOURS AND SECONDS.
select TO_CHAR(SYSDATE,'YYYYMMDDHH24MISS') - start_time from TABLEA where job_name='jOB_AA_BB';
I get 4220.
Any help please? Thanks
When you do datetime arithmetic with the DATE datatype, you get back a NUMBER of days. To get an INTERVAL you can subtract two TIMESTAMPs. You don't say what the data type is for start_time, but you might get away with this:
select localtimestamp - start_time
from tablea where job_name='jOB_AA_BB';
LOCALTIMESTAMP gives you a TIMESTAMP value in the current session time zone. There's also CURRENT_TIMESTAMP, which give you the same thing in a TIMESTAMP WITH TIME ZONE and SYSTIMESTAMP that gives you the database time in TIMESTAMP WITH TIME ZONE. You may need to convert your start_time to avoid time zone differences, if any.
You can us the function numtodsinterval to convert the results of date arithmetic to an interval. If necessary then use extract to pull out the needed components.
with tablea(job_name, start_time) as
(select 'jOB_AA_BB','20211026231735' from dual)
select numtodsinterval((SYSDATE - to_date( start_time,'yyyymmddhh24miss')),'hour') date_diff
from tablea where job_name='jOB_AA_BB' ;
with tablea(job_name, start_time) as
(select 'jOB_AA_BB','20211026231735' from dual)
select extract (hour from date_diff) || ':' || extract (minute from date_diff)
from (
select numtodsinterval((sysdate - to_date( start_time,'yyyymmddhh24miss')),'day') date_diff
from tablea where job_name='jOB_AA_BB'
);
NOTE: I am not sure how you got any result, other than an error, as your query winds up as a string - a string. You should not convert sysdate to a string but your string to a date (better yet store it as the proper data type - date).
You can convert the value to a date (rather than converting SYSDATE to a string) and then subtract and explicitly return the value as an INTERVAL DAY TO SECOND type:
SELECT (SYSDATE - TO_DATE('20211026231735', 'YYYYMMDDHH24MISS')) DAY TO SECOND
FROM DUAL;
Or, for your table:
SELECT (SYSDATE - TO_DATE(start_time,'YYYYMMDDHH24MISS')) DAY(5) TO SECOND
FROM TABLEA
WHERE job_name='jOB_AA_BB';
db<>fiddle here
HIRE_DATE is in a 'DATE' column. The timestamp is local (Los Angeles); I would like to convert it to UTC.
I can't for the life of me fathom why the UTC output is mangled (Last 2 digits of YY is the DD; and vice-versa) -- and the time does not convert to UTC.
HIRE_DATE: 30/04/2019 12:00:00 AM
select from_tz(to_timestamp(HIRE_DATE,'DD-MM-YY HH24:MI:SS'), 'America/Los_Angeles') at time zone 'UTC' from TABLE
OUTPUT: 19/04/2030 12:00:00 AM
If HIRE_DATE is a DATE data type then you don't need TO_TIMESTAMP.
TO_TIMESTAMP is used to convert a string (i.e. VARCHAR2) into a TIMESTAMP value but you have a DATE value.
Just do
select from_tz(CAST(HIRE_DATE AS TIMESTAMP), 'America/Los_Angeles') at time zone 'UTC'
from TABLE
Actually I don't understand why FROM_TZ does not accept DATE values whereas almost any other date/timestamp related function accept either DATE or TIMESTAMP value as input.
Note, the default output display format of this query is defined by current user session NLS_TIMESTAMP_TZ_FORMAT setting. If you are not satisfied with the output format, either change NLS_TIMESTAMP_TZ_FORMAT setting by executing ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = '...' or use TO_CHAR function to set output format explicitly.
Instead of
... AT TIME ZONE 'UTC'
you can also use
SYS_EXTRACT_UTC(...)
The upper returns a TIMESTAMP WITH TIME ZONE value, the second one returns a TIMESTAMP value.
Would this do any good?
SQL> select from_tz(cast (sysdate as timestamp), 'UTC') result from dual;
RESULT
---------------------------------------------------------------------------
27.09.20 10:59:28,000000 UTC
Or, in your case
select from_tz(cast (hire_date as timestamp), 'UTC' from dual
No need to apply any format mask to hire_date as it is a DATE datatype (at least, that's what you said).
You use the word "convert" which can mean one of two things:
change the data type, which is what FROM_TZ does
change the value from one time zone to another, which FROM_TZ does not do.
You didn't give your expected output, so we may misunderstand.
To change the data type:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select from_tz(cast(dte as timestamp), 'America/Los_Angeles') from data
FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES')
30-APR-19 12.00.00.000000 PM AMERICA/LOS_ANGELES
To get the simultaneous datetime value in UTC:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select cast(sys_extract_utc(from_tz(cast(dte as timestamp), 'America/Los_Angeles')) as date) from data
CAST(SYS_EXTRACT_UTC(FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES'))ASDATE)
2019-04-30 19:00:00
This question already has answers here:
Convert from date to epoch-Oracle
(3 answers)
Closed 10 months ago.
Does anyone have a better AND faster solution on getting the unix epoch timestamp using Oracle SQL than this?:
SQL> select (cast(sysdate as date) - cast(to_date('1970-01-01', 'YYYY-MM-DD') as date)) * 86400 as unixepoch from dual;
UNIXEPOCH
----------
1490789604;
Oneliner preferred ;)
The above answer is only correct if your database time zone is in UTC. Unix time is always in UTC.
The correct answer that works on any database, regardless of configuration is:
--Convert current time to epoch.
select (cast (systimestamp at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual
--Convert hard-coded timestamp to epoch.
select (cast (timestamp '2019-12-31 23:59:59' at time zone 'UTC' as date) - date '1970-01-01') * 86400
from dual;
You do not need to cast the values as dates, since they are already dates.
SELECT ( SYSDATE - DATE '1970-01-01' ) * 86400 AS unixepoch
FROM DUAL;
How I can to see last 5 mins record before the current time through sql query how i can do this.
The format of time stamp is
03/25/2014 14:00:00
I used this query for the same
SELECT Time stamp FROM TABLE
WHERE S >1 AND SUBSTRING((Time stamp,15,2)-5)
is this fine of any other way to do the same
If you are using MySQL and your timestamp column is of data type datetime you can do
SELECT Timestamp
FROM your_table
WHERE Timestamp >= now() - interval 5 minute
If your timestamp is a date column, you can simply do:
select t.*
from table t
where t.timestamp >= sysdate - 5/(24*60)
Things are a bit more interesting if timestamp is a character column. Then you need to translate it to a date/time:
select t.*
from table t
where to_date(t.timestamp, 'MM/DD/YYYY HH24:MI:SS') >= sysdate - 5/(24*60)
select *
from the_table
where timestamp_column <= timestamp '2014-03-25 14:00:00' - interval '5' minute;
This assumes that timestamp_column is defined with the data type timestamp.
If it isn't you should stop now and re-define your table to use the correct data type.
The expression timestamp '2014-03-25 14:00:00' is a (ANSI SQL) timestamp literal.
It's equivalent to to_timestamp('2014-03-25 14:00:00', 'yyyy-mm-dd hh24:mi:ss') but I prefer the ANSI literal because it's less typing and works across multiple DBMS.
Here's an example of how to get 5 minutes ago in oracle. subtracting from a timestamp in increments of 1 where 1 is a day. so 5 minutes would be 5/(24hours*60min) of a day.
SELECT sysdate, sysdate-(5/(24*60)) as min_Ago5 from dual
I know that to convert a Unix timestamp in milliseconds to an SQL timestamp I can use
SELECT TO_DATE('1970-01-01','YYYY-MM-DD HH24:MI:SS') +
(:timestamp / (1000*60*60*24)) FROM DUAL;
But I need a Timestamp, so I tried with
SELECT TO_TIMESTAMP('1970-01-01 00:00:00','YYYY-MM-DD HH24:MI:SSFF3') +
(:timestamp) from DUAL
Which gives me the error:
Error: ORA-01841: (full) year must be between -4713 and +9999, and not be 0
It seems that adding 1 to the timestamp always converts it to a day.
How can I do the same to get a real timestamp?
You will get a timestamp if you add an interval to a timestamp (see date/interval arithmetics).
As Benoit noticed, you can't specify an interval with seconds when there are more than about 2.1e9 of them:
SQL> SELECT numtodsinterval(2.2e9, 'SECOND'),
2 numtodsinterval(2.3e9, 'SECOND')
3 FROM dual;
NUMTODSINTERVAL(2.2E9,'SECOND' NUMTODSINTERVAL(2.3E9,'SECOND'
------------------------------- -------------------------------
+000024855 03:14:07.147483647 +000024855 03:14:07.147483647
This is why you should use minutes which do not lose precision. For example, assuming :TS is the unix timestamp (i.e. a number):
SQL> variable ts number;
SQL> -- determining unix timestamp with nanosecond precision
SQL> BEGIN
2 :ts := (to_date('2099-01-01 01:02:03', 'yyyy-mm-dd hh24:mi:ss')
3 - date '1970-01-01') * 1000*60*60*24
4 + 123.456789;
5 END;
6 /
ts
---------
4070912523123,456789
SQL> select timestamp '1970-01-01 00:00:00'
2 + numtodsinterval((:ts)/1000/60, 'MINUTE')
3 from dual;
TIMESTAMP'1970-01-0100:00:00'+NUMTODSINTERVAL((:TS)/1000/60,'MINUTE')
---------------------------------------------------------------------------
2099-01-01 01:02:03.123456789
There are two types:
Timestamps
Intervals
Intervals is what you get when you subtract timestamps, and it is nonsensical to add timestamps together.
If you need to get a millisecond interval, I would suggest to use a second interval and divide it by 1000:
I could suggest:
SELECT timestamp'1970-01-01 00:00:00' + (interval '1888' second(9) / 1000)
FROM dual
The problem here is that you cannot use more than 9 digits in a same timestamp literal.
If you need to ad 2,061,464,797,255 milliseconds to the epoch I can suggest:
SELECT TIMESTAMP'1970-01-01 00:00:00'
+ INTERVAL '2' SECOND(9) * 1000000000
+ INTERVAL '061464797' SECOND(9)
+ INTERVAL '255' SECOND(3) / 1000
FROM dual
You get 2035-04-29 13:06:37.255000000
It seems to be subject to the 2038 bug: TIMESTAMP'1970-01-01 00:00:00' + 3 billion seconds does not work, whereas it works with 2 billion.
I've posted here some methods to convert nanoseconds to timestamp and timestamp to nanoseconds. These methods are not affected by time zones and have a nanosecond precision.
You just need to adjust it to use milliseconds instead of nanoseconds.
SELECT TIMESTAMP '1970-01-01 00:00:00 UTC' + numtodsinterval(
1598434427263 --Replace line with desired milliseconds
/ 1000, 'SECOND') AS TIMESTAMP FROM dual;
TIMESTAMP
26/08/20 09:33:47,263000000 UTC
Use
SELECT TIMESTAMP '1970-01-01 00:00:00.1234' + INTERVAL '1 00:00:00' DAY TO SECOND
AS ts
FROM dual;