# PingoLU's solution

## to Leap in the PL/SQL Track

Published at Jul 13 2018 · 1 comment
Instructions
Test suite
Solution

Given a year, report if it is a leap year.

The tricky thing here is that a leap year in the Gregorian calendar occurs:

``````on every year that is evenly divisible by 4
except every year that is evenly divisible by 100
unless the year is also evenly divisible by 400
``````

For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap year, but 2000 is.

If your language provides a method in the standard library that does this look-up, pretend it doesn't exist and implement it yourself.

## Notes

Though our exercise adopts some very simple rules, there is more to learn!

For a delightful, four minute explanation of the whole leap year phenomenon, go watch this youtube video.

## Setup

Go through the setup instructions for PL/SQL to get ready to code:

http://exercism.io/languages/plsql

## Running the Tests

Execute the tests by calling the `run` method in the respective `ut_<exercise>#` package. The necessary code should be contained at the end of the test package. As an example, the test for the hamming exercise would be run using

``````begin
ut_hamming#.run;
end;
/
``````

## Source

JavaRanch Cattle Drive, exercise 3 http://www.javaranch.com/leap.jsp

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### ut_leap#.plsql

``````create or replace package ut_year#
is
procedure run;
end ut_year#;
/

create or replace package body ut_year#
is
procedure test (
i_descn                                       varchar2
,i_exp                                         varchar2
,i_act                                         varchar2
)
is
begin
if i_exp = i_act then
dbms_output.put_line('SUCCESS: ' || i_descn);
else
dbms_output.put_line('FAILURE: ' || i_descn || ' - expected ' || nvl(i_exp, 'null') || ', but received ' || nvl(i_act, 'null'));
end if;
end test;

procedure run
is
begin
test(i_descn => 'test_leap_year'         , i_exp => 'Yes, 1996 is a leap year'   , i_act => year#.is_leap(1996));
test(i_descn => 'test_non_leap_year'     , i_exp => 'No, 1997 is not a leap year', i_act => year#.is_leap(1997));
test(i_descn => 'test_non_leap_even_year', i_exp => 'No, 1998 is not a leap year', i_act => year#.is_leap(1998));
test(i_descn => 'test_century'           , i_exp => 'No, 1900 is not a leap year', i_act => year#.is_leap(1900));
test(i_descn => 'test_fourth_century'    , i_exp => 'Yes, 2400 is a leap year'   , i_act => year#.is_leap(2400));
end run;
end ut_year#;
/

begin
ut_year#.run;
end;
/``````
``````REATE OR REPLACE PACKAGE year# AS
----------------------------------------
-- Declaration:
--   Public Functions.
----------------------------------------
----------------------------------------
-- is_leap:
--   Given a year,
--   Report if it is a leap year.
--
--   p_number: determine what the nth
--             prime is
----------------------------------------
FUNCTION is_leap (
p_number IN NUMBER)
RETURN VARCHAR2;
END year#;
/

CREATE OR REPLACE PACKAGE BODY year# AS
----------------------------------------
-- Implementation:
--   Public Functions.
----------------------------------------
----------------------------------------
-- is_leap:
--   Given a year,
--   Report if it is a leap year.
--
--   p_number: determine what the nth
--             prime is
----------------------------------------
FUNCTION is_leap (
p_number IN NUMBER)
RETURN VARCHAR2 IS
BEGIN
IF (p_number IS NULL) THEN
RAISE_APPLICATION_ERROR (-20001, 'Input Parameter is NULL.');
END IF;

IF ((REMAINDER(p_number, 4) = 0)
AND (REMAINDER(p_number, 100) <> 0)
OR (REMAINDER(p_number, 400) = 0)) THEN
RETURN ('Yes, ' || p_number || ' is a leap year');
ELSE
RETURN ('No, ' || p_number || ' is not a leap year');
END IF;
END is_leap;
END year#;
/

CREATE OR REPLACE PACKAGE ut_year# AS
PROCEDURE run;
END ut_year#;
/

CREATE OR REPLACE PACKAGE BODY ut_year# AS
PROCEDURE test (
i_descn VARCHAR2
, i_exp VARCHAR2
, i_act VARCHAR2) AS
BEGIN
IF (i_exp = i_act) THEN
dbms_output.put_line('SUCCESS: ' || i_descn);
ELSE
dbms_output.put_line('FAILURE: ' || i_descn || ' - expected ' || nvl(i_exp, 'null') || ', but received ' || nvl(i_act, 'null'));
END IF;
END test;

PROCEDURE run AS
BEGIN
test(i_descn => 'test_leap_year',          i_exp =>    'Yes, 1996 is a leap year', i_act => year#.is_leap(1996));
test(i_descn => 'test_non_leap_year',      i_exp => 'No, 1997 is not a leap year', i_act => year#.is_leap(1997));
test(i_descn => 'test_non_leap_even_year', i_exp => 'No, 1998 is not a leap year', i_act => year#.is_leap(1998));
test(i_descn => 'test_century',            i_exp => 'No, 1900 is not a leap year', i_act => year#.is_leap(1900));
test(i_descn => 'test_fourth_century',     i_exp =>    'Yes, 2400 is a leap year', i_act => year#.is_leap(2400));
END run;
END ut_year#;
/``````