Pure SQL solution for Oracle 12.2, where the handy default null on conversion error
option avoids the need to write functions and handle exceptions:
with demo (date_string) as
( select '2018081' from dual union all
select '01/8/2018' from dual union all
select '01-8-2018' from dual union all
select 'ABCD' from dual union all
select '2018-08-01' from dual union all
select '2018-01-8' from dual union all
select '2017081' from dual union all
select '01-AUG-2018' from dual
)
select t.date_string
, coalesce
( to_date(t.date_string default null on conversion error)
, case sys_context('USERENV','NLS_TERRITORY')
when 'AMERICA' then to_date(t.date_string default null on conversion error,'MM/DD/YYYY')
else to_date(t.date_string default null on conversion error,'DD/MM/YYYY')
end
, to_date(t.date_string default null on conversion error,'DD/MM/YYYY')
, to_date(t.date_string default null on conversion error,'YYYY/MM/DD')
, to_date(t.date_string default null on conversion error,'YYYYMMDD')
, to_date(t.date_string default null on conversion error,'DD/MON/YYYY')
) as converted_date
from demo t
Results:
DATE_STRING CONVERTED_DATE
----------- --------------
2018081 01-AUG-2018
01/8/2018 08-JAN-2018
01-8-2018 08-JAN-2018
ABCD
2018-08-01 01-AUG-2018
2018-01-8 08-JAN-2018
2017081 01-AUG-2017
01-AUG-2018 01-AUG-2018
The first test does not specify any format in order to use the session default (DD-MON-RRRR
etc).
The next test attempts to handle the North American habit of placing the month first. (I'm not sure if sys_context('USERENV','NLS_TERRITORY') = 'AMERICA'
is a reliable test though, as that tends to be the default setting regardless of actual territory. However it illustrates how you can inject some conditional logic if desired.)
to_date
is pretty forgiving about separator characters so I haven't specified different formats for DD-MON-YYYY
vs DD/MON/YYYY
etc.