This question already has answers here:
How to find difference b/w TIMESTAMP format values in Oracle?
(3 answers)
Closed 8 years ago.
So I'm trying to convet a timestamp to seconds.
I read that you could do it this way
to_char(to_date(10000,'sssss'),'hh24:mi:ss')
But turns out this way you can't go over 86399 seconds.
This is my date format: +000000000 00:00:00.000000
What's the best approach to converting this to seconds? (this is the result of subtracting two dates to find the difference).
You could convert timestamp to date by adding a number (zero in our case).
Oracle downgrade then the type from timestamp to date
ex:
select systimestamp+0 as sysdate_ from dual
and the difference in secondes between 2 timestamp:
SQL> select 24*60*60*
((SYSTIMESTAMP+0)
-(TO_TIMESTAMP('16-MAY-1414:10:10.123000','DD-MON-RRHH24:MI:SS.FF')+0)
)
diff_ss from dual;
DIFF_SS
----------
15140
It looks like you're trying to find the total number of seconds in an interval (which is the datatype returned when you subtract two timestamps). In order to convert the interval to seconds, you need to extract each component and convert them to seconds. Here's an example:
SELECT interval_value,
(EXTRACT (DAY FROM interval_value) * 24 * 60 * 60)
+ (EXTRACT (HOUR FROM interval_value) * 60 * 60)
+ (EXTRACT (MINUTE FROM interval_value) * 60)
+ EXTRACT (SECOND FROM interval_value)
AS interval_in_sec
FROM (SELECT SYSTIMESTAMP - TRUNC (SYSTIMESTAMP - 1) AS interval_value
FROM DUAL)
If you want the number of seconds between two dates (or timestamps),
select floor(
(to_date(to_char(timestamp1, 'yyyy-mm-dd HH24:MI:ss'),'yyyy-mm-dd HH24:MI:ss')
- to_date(to_char(timestamp2, 'yyyy-mm-dd HH24:MI:ss'),'yyyy-mm-dd HH24:MI:ss')
)
* 24 -- hours per day
* 60 -- minutes per hour
* 60 -- seconds per minute
)
etc
Related
I am wondering, how can I convert datetime into hours per minute? I want the following. To minus the end_trip with the start_trip that is in hours and minutes. Moreover, I want to create a new column for the result. However, I am getting nowhere. I want to use basic arithmetic for this not some built in functions like DATEDIFF. Please help.
Below is my code
INSERT INTO TRIP VALUES(
TO_DATE('26-01-2022 14:00:00', 'DD/MM/YYYY HH24:MI:SS'), - start_time
TO_DATE('26-01-2022 14:50:00', 'DD/MM/YYYY HH24:MI:SS') - end_time
;
SELECT
trip_start_actual as start_time, trip_end_actual as end_time, (trip_end_actual - trip_start_actual)
from trip;
commit;
Subtracting two dates in Oracle will yield a difference in fractional days. To get minutes from that, simply multiply that difference by 1440:
SELECT trip_start_actual AS start_time,
trip_end_actual AS end_time,
1440 * (trip_end_actual - trip_start_actual) AS num_minutes
FROM trip;
when we subtract two dates in oracle the difference integer also comes in days. we need to multiply that by 24 to get hours and multiply by 24 * 60 = 1440 to get minutes and multiply by 24 * 60 * 60 = 86400 to get seconds.
SELECT
trip_start_actual as start_time, trip_end_actual as end_time,
round ((trip_end_actual - trip_start_actual) * 24 * 60) as
time_diff_minutes from trip;
This question already has answers here:
Convert from date to epoch-Oracle
(3 answers)
PL/SQL sysdate to Unix epoch time in ms
(1 answer)
Closed 3 years ago.
I need to convert an Oracle DATE value to a Unix style seconds-since-epoch-start value.
I've tried various combinations of Oracle's conversions such as:
select to_number(to_date('10/05/2019','mm/dd/yyyy')) from dual;
select to_number(to_timestamp(to_date('10/05/2019','mm/dd/yyyy'))) from dual;
select to_number(to_char(to_date('10/05/2019','mm/dd/yyyy'))) from dual;
Nothing seems to work. Does anyone have an answer to this?
If that's number of seconds since Jan 01 1906, then:
SQL> select sysdate - date '1906-01-01' days,
2 (sysdate - date '1906-01-01') * 24 * 60 * 60 unix_style
3 from dual;
DAYS UNIX_STYLE
---------- ----------
41555,811 3590422068
SQL>
Why? Because - when you subtract two dates in Oracle, result is number of days. Then you have to multiply it by 24 (as there are 24 hours in a day), by 60 (as there are 60 minutes in an hour) and once again by 60 (as there are 60 seconds in a minute).
Of course, you could have multiplied it by 86400 (which is 24 * 60 * 60), but - former is difficult to understand while latter shows what's going on and why.
If - as Wernfried commented - date differs from the one you said, you'd just replace date '1906-01-01' with date '1970-01-01'.
How can i subtract days to a timestamp in CrateDB SQL query?
Exist something similar to this?
TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 14 DAY)
Don't think there is a built in function but you could do something like this
SELECT DATE_FORMAT(CURRENT_TIMESTAMP - 1000*60*60*24*14) LIMIT 100
in this example (1000 * 60 * 60) * 24 * 14 (24 is to get days and 14 is your number of days)
NB. You can also cast dates into timestamp and perform similar functionality
SELECT ABS(cast('2019-01-1' AS TIMESTAMP) - CURRENT_TIMESTAMP ) / (1000*60*60*24) LIMIT 100
this will get you a number of days between now and 1st of January
So far that's all what they have in their docs
You can subtract INTERVAL from TIMESTAMP, but before any matematichal operation you need to CAST the datatype, you can do it in this way:
SELECT now() - CAST('14 day' AS INTERVAL)
Or the same function of above, but in a contracted way
SELECT now() - '14 day'::INTERVAL;
As a string to be CAST to an INTERVAL you can use a number followed by any of this:
second
minute
hour
day
week
month
quarter
year
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;
I thought it was really simple but it isn't.
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')
- 1/(24*50*60*1000) data
FROM dual;
It simply doesn't work.
Other details:
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') -
NUMTODSINTERVAL(1/(24*50*60*1000),'HOUR') data
FROM dual;
doesn't work..
The right seems to be
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') -
NUMTODSINTERVAL(1/(24*25*60*1000),'HOUR') data
FROM dual;
Why? How does it work?
For adding or subtracting an amount of time expressed as a literal you can use INTERVAL.
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')
- INTERVAL '0.001' SECOND
FROM dual;
As well there are now standard ways to express date and time literals and avoid the use of various database specific conversion functions.
SELECT TIMESTAMP '2012-10-08 00:00:00'
- INTERVAL '0.001' SECOND DATA
FROM dual;
For your original question the time part of a day is stored in fractional days. So one second is:
1 / (hours in day * minutes in hour * seconds in a minute)
Divide by 1000 to get milliseconds.
1 / (24 * 60 * 60 * 1000)
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/(24*50*60*1000),'HOUR') data
FROM dual;
OUTPUT
DATA
---------------------------------
09/AUG/12 11:59:59.999950000 PM
1 row selected.
The answer posted above subtracts a tenth of a millisecond from the date. I think what you want is the following:
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY')-NUMTODSINTERVAL(1/1000,'SECOND')
FROM dual;
Output:
DATA
---------------------------------------------------------------------------
09-AUG-12 11.59.59.999000000 PM
^^^
|||
tenths|thousandths
|
hundredths
The following NUMTODSINTERVAL(1/(24*25*60*1000),'HOUR') seems to work only because 24*25 = 600. But that number is wrong because 1/(600*60*1000) of an hour is a tenth of a millisecond, not a millisecond. If you want to use 'HOUR' in NUMTODSINTERVAL() you should use 1/(60*60*1000) (sixty minutes in an hour, sixty seconds in a minute, 1000 ms in a second).
This is correct (with a millisecond being 1000th of a second):-
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/1000,'SECOND') data FROM dual;
DATA
-----------------------------
09-AUG-12 23.59.59.999000000
As to why the other code isn't working it's because you aren't calculating a millisecond correctly. An hour must be divided by 60 to give minutes and again by 60 to given seconds then by 1000 to give a millisecond, thus if you must use HOUR as the interval then it is:-
SELECT TO_TIMESTAMP('10/08/2012','DD/MM/YYYY') - NUMTODSINTERVAL(1/(60*60*1000),'HOUR') as data FROM dual;
DATA
---------------------------------------------------------------------------
09-AUG-12 23.59.59.999000000
select TO_CHAR(TO_TIMESTAMP('10.05.2012', 'DD.MM.YYYY') -
NUMTODSINTERVAL(1/1000, 'SECOND'), 'DD.MM.YYYY HH24:MI:SS:FF3') Res
from dual;
RES
-----------------------------
09.05.2012 23:59:59.999