Difference between 2 times in sec in Pl/SQL [duplicate] - oracle

This question already has answers here:
Calculate difference between 2 date / times in Oracle SQL
(21 answers)
Closed 8 months ago.
I need some help to identify difference between 2 times in sec
variable :
current_time : this is current time
check_begin_time : in YYYYMMDDHH24MMSS format
I need to check the difference i.e. current time - check_begin_time in secs
Thanks.

As difference of two DATE datatype values in Oracle represents number of days between them, you have to multiply it by 24 (as there are 24 hours in a day) and 60 (as there are 60 minutes in an hour) and 60 (as there are 60 seconds in a minute).
So:
(setting date format, just to know what is what; you don't have to do that)
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
I presume your value is stored as a string (according to date format you posted; though, it is wrong - minutes are MI, not MM) so first convert it to a DATE datatype value, and then do the calculation:
SQL> select sysdate now,
2 (sysdate - to_date('20220614090500', 'yyyymmddhh24miss')) * 24 * 60 * 60 seconds
3 from dual;
NOW SECONDS
------------------- ----------
14.06.2022 09:09:54 294
SQL>

SELECT (END_DT - START_DT) * 60 * 60 * 24 FROM MY_TABLE; -- Seconds
SELECT (END_DT - START_DT) * 60 * 24 FROM MY_TABLE; -- Minutes
SELECT (END_DT - START_DT) * 24 FROM MY_TABLE; -- Hours
To get more info refer to this link: Date Difference

Related

Apply average( ) function to datediff between timestamp fields

I have some data that looks like this:
my_table
name
start
end
Michigan
06-NOV-20 08.25.59.000000000 AM
06-NOV-20 08.44.52.000000000 AM
State
22-NOV-20 11.49.11.000000000 AM
22-NOV-20 11.54.06.000000000 AM
I'm trying to create a new column to calculate the duration as the difference between start and end. I then want to apply a mathematical average (mean/median) to find the average duration by year.
My code, currently:
SELECT
start - end AS duration
FROM
my_table
Current output:
duration
-0 0:18:53.0
-0 0:4:55.0
What I want:
duration
1133
295
How can I go about converting the duration field from datetime to seconds or minutes, so that I can apply an average function to the duration field?
I suggest you spend some time with the Oracle Documentation for your version, also for a fairly quick overview of date/timestamp see here (not just the first sub-topic).
Your issue is what is the results of date/timestamp subtraction. There are two results you can get. Subtracting dates results in a floating point number where the whole number part represents days, and the decimal part the fraction of a day. Subtracting timestamps results in an data type Interval Day to Second. This case deals with timestamps. The Extract is used to get the individual components of the interval. Since you are after the duration in seconds you extract each component multiplying by the appropriate value to convert to seconds, and total the results:
select extract(day from diff) * 60 * 60 * 24 -- days to seconds
+ extract(hour from diff) * 60 * 60 -- hours to seconds
+ extract(minute from diff) * 60 -- minutes to seconds
+ extract(second from diff) -- seconds
from (
select to_timestamp('06-NOV-20 08.44.52.000000000 AM', 'dd-mon-yy hh12.mi.ss.ff AM')
- to_timestamp('06-NOV-20 08.25.59.000000000 AM', 'dd-mon-yy hh12.mi.ss.ff AM') diff
from dual
);
I found this online. Will this help?
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:10729709873260

How Oracle internally deduces the differece between dates

select (current_date - TO_DATE('20210817124015','YYYYMMDDHH24MISS')) from dual;
Outputs:
0.1229282407407407407407407407407407407407
I want to know how oracle internally achieves this value.
ps: the current_date and the hardcoded date are same, only time is the difference.
CURRENT_DATE returns the current date and time in the user's session time zone.
TO_DATE('20210817124015','YYYYMMDDHH24MISS') returns the date 2021-08-17T12:40:15.
Note: A DATE data type always has year, month, day, hour, minute and second components. However, the user interface you are using may chose not to show all the components.
Subtracting one date from another returns the number of days between the two values.
0.1229282407407407407407407407407407407407 days is:
2.950277778 hours; or
177.016666667 minutes; or
10621 seconds; or
2 hours 57 minutes and 1 second.
So your current date was 2021-08-17T12:40:15 + 10621 seconds or 2021-08-17T15:37:16.
For example:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS';
ALTER SESSION SET TIME_ZONE = 'Asia/Samarkand';
SELECT CURRENT_DATE,
TO_DATE('20210817124015','YYYYMMDDHH24MISS') As other_date,
CURRENT_DATE - TO_DATE('20210817124015','YYYYMMDDHH24MISS') as difference,
(CURRENT_DATE - TO_DATE('20210817124015','YYYYMMDDHH24MISS')) DAY TO SECOND
as interval_difference
FROM DUAL;
Outputs:
CURRENT_DATE
OTHER_DATE
DIFFERENCE
INTERVAL_DIFFERENCE
2021-08-17T15:40:01
2021-08-17T12:40:15
.124837962962962962962962962962962962963
+00 02:59:46.000000
db<>fiddle here
Subtracting two dates returns a difference in days.
0.1229282407407407407407407407407407407407 days is
2.9502777777768 hours
177.016666666608 minutes
10621 seconds
Or, put another way, current_date is returning a date value that is 2 hours 57 minutes and 1 second after the hard-coded date. Since the hard-coded date has a time of 12:40:51, that means that current_date has a time of 15:37:52.

Oracle current_timestamp to second including milliseconds

This is my first time posting here. I've been looking out for all threads here & other websites but still I'm unable to fix the codes.
Here it is, I have a sample table called LM Where the structure looks like this: (Cannot change table structure)
LM_REFID(PK) LM_DESC
----------------------------------
VARCHAR2(50) VARCHAR2(50)
And LM_REFID is the PRIMARY KEY
So, here the things, I want to create a BEFORE INSERT trigger to assign timestamp values in seconds, including the milliseconds. It has to be counted in seconds (with milliseconds) from current time to 1/1/1970 00:00:00 (db time)
(As considering the simultaneous insert would violates PK due to same seconds values. Hence, I want the milliseconds values so the PK is unique)
The trigger looks like this:
CREATE OR REPLACE TRIGGER LM_TRG
BEFORE INSERT ON LM
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
:new.LM_REFID := (SYSDATE - TO_DATE('01/01/1970 00:00:00','MM-DD-YYYY HH24:MI:SS'))
* 24 * 60 * 60 ;
END;
/
This would result to values returned in SECONDS is 1449677554
But I don't want the SECONDS only, I want the milliseconds too, so the PK is unique. So, I've tried replaced the SYSDATE function with timestamp there like:
:new.LM_REFID:= (CURRENT_TIMESTAMP - TO_TIMESTAMP ('01/01/1970 00:00:00',
'MM-DD-YYYY HH24:MI:SSFF3')) * 24 * 60 * 60 * 1000
But it leads to error. I also have tried others like CAST, EXTRACT, epoch and more, but still no luck.
I want the sample data for example should be looked like this :
LM_REFID
----------------------------
1449677554.123456
1449677554.123344
1444677554.124466
Anyone can help to improve the trigger?
Thank you.
Maybe something like this:
declare
l_interval interval day(9) to second(6);
l_seconds number(24,6);
begin
l_interval := current_timestamp - timestamp '1970-01-01 00:00:00.000000';
l_seconds := extract(day from l_interval) * 24 * 60 * 60 +
extract(hour from l_interval) * 60 * 60 +
extract(minute from l_interval) * 60 +
extract(second from l_interval);
dbms_output.put_line(l_seconds);
end;
/
l_seconds will contain fractional seconds as well, that's why it has to be declared as number with decimal digits.
But I never get more than three decimal digits out of this - don't know why.

Oracle TimeStamp Issue [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
How to subtract Time in two dates. For example, I have 15:32:34 as sign_out date and 13:34:21 as sign_in date, now I want to do sign_out - sign_in with DATE data type, but I am unable to do it, I am getting 0 value for days, but I need to get the difference of time, can any one help me please
If your columns are timestamp then the difference between them will be an interval. For the values you added as a comment:
select id, time_out - time_in as worked
from t42;
ID WORKED
---------- -----------
1 0 4:22:0.0
1 0 2:23:2.0
You want the total, but you can't directly sum intervals. You could convert them to a numeric representation, sum them, and then convert them back:
select id, numtodsinterval(sum(
extract(day from dd) * (24 * 60 * 60)
+ extract(hour from dd) * (60 * 60)
+ extract(minute from dd) * 60
+ extract(second from dd)
), 'SECOND') as total_worked
from (
select id, time_out - time_in as dd
from t42
)
group by id;
ID TOTAL_WORKED
---------- ------------
1 0 6:45:2.0
You could also treat them as dates; it isn't entirely clear if you're using fractional seconds but for this kind of data it would seem like unnecessary precision. I'm not sure why you aren't using date columns here (perhaps you just didn't realise that an Oracle date column does contain the time down to the second anyway?). Anyway, you can cast them to dates:
select id,
sum(cast(time_out as date) - cast(time_in as date)) as total_days,
numtodsinterval(sum(cast(time_out as date) - cast(time_in as date)), 'DAY')
as total_interval,
to_char(trunc(sysdate)
+ sum(cast(time_out as date) - cast(time_in as date)), 'HH24:MI:SS')
as total_string
from t42
group by id;
ID TOTAL_DAYS TOTAL_INTERVAL TOTAL_STRING
---------- ---------- -------------- ------------
1 .281273148 0 6:45:2.0 06:45:02
The result of subtracting two dates is a number, where 1 would be a whole day. I've shown two ways to convert that to something more useful.
The to_char version will only work if the total is less than a day though; if it might exceed 24 hours then you'd need to calculate it a different way:
select id,
trunc(dd * 24) as hh,
trunc((dd - (trunc(dd * 24)/24)) * 24 * 60) as mi,
trunc((dd - trunc(dd * 24 * 60)/(24 * 60)) * (24 * 60 * 60)) as ss
from (
select id,
sum(cast(time_out as date) - cast(time_in as date)) as dd
from t42
group by id
);
ID HH MI SS
---------- ---------- ---------- ----------
1 6 45 1
... and you can concatenate those into a string if you want (with lpad to add leading zeros). It's odd that the 'seconds' value here is shown as 1, since (dd - trunc(dd * 24 * 60)/(24 * 60)) * (24 * 60 * 60) is 2, and trunc(2) is 2; not sure if there's a rounding error going on in their somewhere. If you use round instead of trunc in the final clasue then it works, but might give a slightly higher value than expected if you do have fractions of seconds.
SQL Fiddle, which doesn't show intervals in a very friendly format, unfortunately. That's with your sample, and another ID that does exceed 24 hours so you can see the difference; and with both round and trunc for the seconds in the last query.

Oracle: how to add minutes to a timestamp?

I need to add 30 minutes to values in a Oracle date column. I do this in my SELECT statement by specifying
to_char(date_and_time + (.000694 * 31)
which works fine most of the time. But not when the time is on the AM/PM border. For example, adding 30 minutes to 12:30 [which is PM] returns 1:00 which is AM. The answer I expect is 13:00. What's the correct way to do this?
In addition to being able to add a number of days to a date, you can use interval data types assuming you are on Oracle 9i or later, which can be somewhat easier to read,
SQL> ed
Wrote file afiedt.buf
SELECT sysdate, sysdate + interval '30' minute FROM dual
SQL> /
SYSDATE SYSDATE+INTERVAL'30'
-------------------- --------------------
02-NOV-2008 16:21:40 02-NOV-2008 16:51:40
All of the other answers are basically right but I don't think anyone's directly answered your original question.
Assuming that "date_and_time" in your example is a column with type DATE or TIMESTAMP, I think you just need to change this:
to_char(date_and_time + (.000694 * 31))
to this:
to_char(date_and_time + (.000694 * 31), 'DD-MON-YYYY HH24:MI')
It sounds like your default date format uses the "HH" code for the hour, not "HH24".
Also, I think your constant term is both confusing and imprecise. I guess what you did is calculate that (.000694) is about the value of a minute, and you are multiplying it by the number of minutes you want to add (31 in the example, although you said 30 in the text).
I would also start with a day and divide it into the units you want within your code. In this case, (1/48) would be 30 minutes; or if you wanted to break it up for clarity, you could write ( (1/24) * (1/2) ).
This would avoid rounding errors (except for those inherent in floating point which should be meaningless here) and is clearer, at least to me.
UPDATE "TABLE"
SET DATE_FIELD = CURRENT_TIMESTAMP + interval '48' minute
WHERE (...)
Where interval is one of
YEAR
MONTH
DAY
HOUR
MINUTE
SECOND
from http://www.orafaq.com/faq/how_does_one_add_a_day_hour_minute_second_to_a_date_value
The SYSDATE pseudo-column shows the current system date and time. Adding 1 to SYSDATE will advance the date by 1 day. Use fractions to add hours, minutes or seconds to the date
SQL> select sysdate, sysdate+1/24, sysdate +1/1440, sysdate + 1/86400 from dual;
SYSDATE SYSDATE+1/24 SYSDATE+1/1440 SYSDATE+1/86400
-------------------- -------------------- -------------------- --------------------
03-Jul-2002 08:32:12 03-Jul-2002 09:32:12 03-Jul-2002 08:33:12 03-Jul-2002 08:32:13
I prefer using an interval literal for this, because interval '30' minute or interval '5' second is a lot easier to read then 30 / (24 * 60) or 5 / (24 * 60 * 69)
e.g.
some_date + interval '2' hour
some_date + interval '30' minute
some_date + interval '5' second
some_date + interval '2' day
You can also combine several units into one expression:
some_date + interval '2 3:06' day to minute
Adds 2 days, 3 hours and 6 minutes to the date value
The above is also standard SQL and also works in several other DBMS.
More details in the manual: https://docs.oracle.com/database/121/SQLRF/sql_elements003.htm#SQLRF00221
If the data type of the field is date or timestamp, Oracle should always give the correct result if you add the correct number given in number of days (or a the correct fraction of a day in your case). So if you are trying to bump the value in 30 minutes, you should use :
select field + 0.5/24 from table;
Based on the information you provided, I believe this is what you tried to do and I am quite sure it works.
Can we not use this
SELECT date_and_time + INTERVAL '20:00' MINUTE TO SECOND FROM dual;
I am new to this domain.
like that very easily
i added 10 minutes to system date and always in preference use the Db server functions not custom one .
select to_char(sysdate + NUMTODSINTERVAL(10,'MINUTE'),'DD/MM/YYYY HH24:MI:SS') from dual;
Be sure that Oracle understands that the starting time is PM, and to specify the HH24 format mask for the final output.
SELECT to_char((to_date('12:40 PM', 'HH:MI AM') + (1/24/60) * 30), 'HH24:MI') as time
FROM dual
TIME
---------
13:10
Note: the 'AM' in the HH:MI is just the placeholder for the AM/PM meridian indicator. Could be also 'PM'
Oracle now has new built in functions to do this:
select systimestamp START_TIME, systimestamp + NUMTODSINTERVAL(30, 'minute') end_time from dual
Based on what you're asking for, you want the HH24:MI format for to_char.
To edit Date in oracle you can try
select to_char(<columnName> + 5 / 24 + 30 / (24 * 60),
'DD/MM/RRRR hh:mi AM') AS <logicalName> from <tableName>
SELECT to_char(sysdate + (1/24/60) * 30, 'dd/mm/yy HH24:MI am') from dual;
simply you can use this with various date format....

Resources