Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Oracle SQL for Leap Years (knowledge sharing)

Christopher ChatmanJun 11 2025 — edited Jun 11 2025

Knowledge Sharing:

--The Leap Year Rule: Years evenly divisible by 4 are leap years, except for centurial years that are not evenly divisible by 400.
--E.g., the years 1700, 1800, 1900 and 2100 are not leap years, but 1600, 2000, and 2400 are leap years.

--accounts for leap day births for code executions on last day of feb. in non-leap year (months_between does not).
floor( (to_number(to_char(sysdate,'yyyymmdd')) - to_number(to_char(person.dob,'yyyymmdd'))) / 10000 ) age
---------------------
--find birthdays today with leap babies celebrating 1st march
select *
from person
where 1=1
and to_char ( sysdate, 'dd-mon' ) = to_char ( person.dob, 'dd-mon' ) --dob matched today
or --leap logic
(
    -- they are a leapling and it's march 1st --
    to_char ( person.dob, 'dd-mon' ) = '29-FEB' and to_char ( sysdate, 'dd-mon' ) = '01-MAR'
    -- and it's not a leap year --
    and not -- check it's (not) a leap year
    (
        --if divisible by 100, it should be divisible by 400
        ( mod ( extract ( year from sysdate ), 400 ) = 0 )
        or
        --not divisible by 100, but divisible by 4
        ( mod ( extract ( year from sysdate ), 4 ) = 0 and mod ( extract ( year from sysdate ), 100 ) <> 0 )
    )
)
;
---------------------
--not leap year logic
not
(   --if divisible by 100, it should be divisible by 400
    mod ( extract ( year from sysdate ), 400 ) = 0
    or
    --not divisible by 100, but divisible by 4
    ( mod ( extract ( year from sysdate ), 4 ) = 0 and mod ( extract ( year from sysdate ), 100 ) <> 0 )
)
---------------------
--cte to store leap years
with t as (select 1900+rownum-1 as yr from dual connect by rownum <= 200)
select
    yr
    ,case
        --1st WHEN: mod(yr,100) = 0 here is optional since always true for 100 if true for 400.
        when mod(yr,400)=0 and mod(yr,100) = 0 then 'leap year'
        when mod(yr,4) = 0 and mod(yr,100) != 0 then 'leap year'
        else null
    end as leap
from t
order by yr
;
This post has been answered by Christopher Chatman on Jun 11 2025
Jump to Answer
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jul 3 2025
Added on Jun 11 2025
15 comments
265 views