Quantcast
Channel: PostgreSQL – MacLochlainns Weblog
Viewing all articles
Browse latest Browse all 50

PL/pgSQL Date Function

$
0
0

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.


Viewing all articles
Browse latest Browse all 50

Trending Articles