You can use regexp_substr
to extract only the 3rd and 4th comma-separated strings, using the subexpression parameter to get the 2nd colon-delimited word within that:
with demo (str) as
( select 'Error: P1_Date > P2_Date, Serial_Number:824354334344332, P2_Date:11/17/2019 6:07:00 PM, P1_Date:11/18/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:7777734, P2_Date:11/27/2019 8:47:00 PM, P1_Date:11/29/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:9788871212, P2_Date:11/25/2019 12:14:05 PM, P1_Date:1/8/2020' from dual
)
select regexp_substr(str, '(:)([^,]+)([^:]?)',1,4,null,2) as p1_date
, regexp_substr(str, '(:)([^,]+)([^:]+)',1,3,null,2) as p2_date
from demo;
P1_DATE P2_DATE
---------------------- ----------------------
11/18/2019 11/17/2019 6:07:00 PM
11/29/2019 11/27/2019 8:47:00 PM
1/8/2020 11/25/2019 12:14:05 PM
The subexpression parameter works with expressions containing subexpressions e.g. (x)(y)(z)
, where subexpression 2 would be y
.
The ?
in place of +
in my p1_date
expression was a bit of a guess to be honest, as using [^:]+
stripped the final character.
Once you have that, you can convert to dates as normal:
with demo (str) as
( select 'Error: P1_Date > P2_Date, Serial_Number:824354334344332, P2_Date:11/17/2019 6:07:00 PM, P1_Date:11/18/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:7777734, P2_Date:11/27/2019 8:47:00 PM, P1_Date:11/29/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:9788871212, P2_Date:11/25/2019 12:14:05 PM, P1_Date:1/8/2020' from dual
)
select to_date(regexp_substr(str, '(:)([^,]+)([^:]?)',1,4,null,2), 'MM/DD/YYYY') as p1_date
, to_date(regexp_substr(str, '(:)([^,]+)([^:]+)',1,3,null,2), 'MM/DD/YYYY HH:MI:SS PM') as p2_date
, to_date(regexp_substr(str, '(:)([^,]+)([^:]?)',1,4,null,2), 'MM/DD/YYYY') -
to_date(regexp_substr(str, '(:)([^,]+)([^:]+)',1,3,null,2), 'MM/DD/YYYY HH:MI:SS PM') as diff
from demo;
Or it might be more readable with the regex parsing and date conversion nested within an inline view/CTE, so that you can refer more simply to p1_date
and p2_date
in an outer query:
with demo (str) as
( select 'Error: P1_Date > P2_Date, Serial_Number:824354334344332, P2_Date:11/17/2019 6:07:00 PM, P1_Date:11/18/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:7777734, P2_Date:11/27/2019 8:47:00 PM, P1_Date:11/29/2019' from dual union all
select 'Error: P1_Date > P2_Date, Serial_Number:9788871212, P2_Date:11/25/2019 12:14:05 PM, P1_Date:1/8/2020' from dual
)
select p1_date
, p2_date
, p1_date - p2_date as diff
from ( select to_date(regexp_substr(str, '(:)([^,]+)([^:]?)',1,4,null,2), 'MM/DD/YYYY') as p1_date
, to_date(regexp_substr(str, '(:)([^,]+)([^:]+)',1,3,null,2), 'MM/DD/YYYY HH:MI:SS PM') as p2_date
from demo );
REGEXP_SUBSTR