This post provides an example of using PostgreSQL’s REGEXP_MATCH function, which works very much like the REGEXP_LIKE function in Oracle and a verify_date function that converts a string data type to date data type.
Here’s a basic function to show how to use a generic REGEXP_MATCH function:
DO
$$
DECLARE
lv_date_in DATE := '2022-10-22';
BEGIN
IF (REGEXP_MATCH('2022-10-02','^[0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2}$') IS NOT NULL) THEN
RAISE NOTICE '[%]', 'Truth';
END IF;
END;
$$;
The following is a verify_date function, which takes a string with the ‘YYYY-MM-DD’ or ‘YY-MM-DD’ format and returns a DATE data type.
CREATE FUNCTION verify_date
( IN pv_date_in TEXT) RETURNS DATE AS
$$
DECLARE
/* Local variable so changes can be made to the input variable. */
lv_date_in VARCHAR(11);
/* Local return variable. */
lv_date DATE;
BEGIN
/* Check for a YYYY-MM-DD or YYYY-MM-DD string. */
IF REGEXP_MATCH(pv_date_in,'^([0-9]{2,2}|[0-9]{4,4})-[0-9]{2,2}-[0-9]{2,2}$') IS NOT NULL THEN
/* If a 2-digit exists convert it to a 4-digit year. */
IF LENGTH(pv_date_in) = 8 AND SUBSTRING(pv_date_in,3,1) = '-' THEN
lv_date_in := TO_DATE(pv_date_in,'YY-MM-DD');
ELSE
lv_date_in := pv_date_in;
END IF;
/* Case statement checks for 28 or 29, 30, or 31 day month. */
CASE
/* Valid 31 day month date value. */
WHEN SUBSTRING(lv_date_in,6,2) IN ('01','03','05','07','08','10','12') AND
TO_NUMBER(SUBSTRING(lv_date_in,9,2),'99') BETWEEN 1 AND 31 THEN
lv_date := lv_date_in;
/* Valid 30 day month date value. */
WHEN SUBSTRING(lv_date_in,6,2) IN ('04','06','09','11') AND
TO_NUMBER(SUBSTRING(lv_date_in,9,2),'99') BETWEEN 1 AND 30 THEN
lv_date := lv_date_in;
/* Valid 28 or 29 day month date value. */
WHEN SUBSTRING(lv_date_in,6,2) = '02' THEN
/* Verify 4-digit year. */
IF MOD(TO_NUMBER(SUBSTRING(lv_date_in,1,4),'99'),4) = 0 AND
TO_NUMBER(SUBSTRING(lv_date_in,9,2),'99') BETWEEN 1 AND 29 THEN
lv_date := lv_date_in;
ELSE /* Not a leap year. */
IF TO_NUMBER(SUBSTRING(lv_date_in,9,2),'99') BETWEEN 1 AND 28 THEN
lv_date := lv_date_in;
END IF;
END IF;
ELSE
NULL;
END CASE;
END IF;
/* Return date. */
RETURN lv_date;
END;
$$ LANGUAGE plpgsql;
The following four SQL test cases:
SELECT verify_date('2020-07-04');
SELECT verify_date('71-05-31');
SELECT verify_date('2024-02-29');
SELECT verify_date('2019-04-31');
Return the following:
verify_date
-------------
2020-07-04
(1 row)
verify_date
-------------
1971-05-31
(1 row)
verify_date
-------------
2024-02-29
(1 row)
verify_date
-------------
(1 row)
As always, I hope the example code fills somebody’s need.