Microsoft Y2K  
Microsoft
 This static CD-based web site is representative of the www.microsoft.com/y2k site as of October 15, 1999.

Microsoft Year 2000 Readiness Disclosure & Resource Center
Preparing Office Solutions for the Year 2000
Verifying Leap Year Algorithms

The year 2000 is a leap year. Additionally, many custom routines to determine leap years are not Year 2000 compliant because they only work with two digits of the year. If your application requires logic to determine leap years, be sure to test your routine to ensure it works in the 20th and 21st centuries. This is a Year 2000 problem because many developers still believe (incorrectly) that 2000 is not a leap year. Because of this, many custom leap year algorithms will incorrectly identify 2000 as a non-leap year.

History Lesson

The calculation of leap years is one of the more misunderstood issues in computer science. Before jumping into the subject, let's take a brief look at why leap years exist at all.

The strict definition of a year is "the interval between two successive passages of the Sun through the vernal equinox." The vernal equinox is the exact moment when the Sun is above the equator moving south to north. This definition of a year is known as the "tropical year" and is 365.24219 days in length (365 days, 5 hours, 48 minutes, and 46 seconds.)

With the introduction of the Julian calendar in 46 BC, the number of days in a year was rounded up to 365.25. With the Julian calendar, a simple leap year rule was used: if the year was evenly divisible by four, it was a leap year. Unfortunately, the difference between a tropical year (365.24219 days) and the Julian year (365.25 days) introduced errors that over time added up. This error resulted in a year that was 11 minutes and 14 seconds too long, which adds up to a whole day every 128 years.

By the 1500's, this error added up to approximately 10 days. This problem was addressed in the Gregorian calendar instituted in 1582 by Pope Gregory XIII. The fix was to make the determination of leap years a bit more accurate. In the Gregorian calendar, a year is defined as being 365.2425 days in length. This is not exactly equal to a tropical year, but is so close that the error amounts only to about 3 days in 10,000 years. If this error is a problem for you (you are tracking the decay of atomic particles in your Access application for example), you may need to switch to Coordinated Universal Time (UTC) and employ "leap seconds". The coverage of this is unfortunately beyond the scope of this paper.

Since we now use the Gregorian calendar, we use the rule made official by papal decree: "Every fourth year is a leap year except for century years that are not evenly divisible by 400." What does this mean to you? Simply put, the Year 2000 is absolutely a leap year! Don't let anybody tell you differently. If they do, they don't understand how to correctly determine a leap year.

Determining Leap Years

So, if a leap year is every fourth year except for century years that are not evenly divisible by 400, the following algorithm correctly deduces leap years.

If MyYear Mod 4 = 0 Then
   ' Is it a century?
   If MyYear Mod 100 = 0 Then
     ' If a century, must be evenly divisible by 400
     If MyYear Mod 400 = 0 Then
       LeapYear = True
     Else
       LeapYear = False
     End If
   Else
     LeapYear = True
   Endif
Else
   LeapYear = False
End If

Code Listing 8   Pseudocode for Determining Leap Years

Note that using the formula tells us that 1900 is not a leap year. However, for compatibility with incorrect historical standards in computer software, some programs consider, such as Microsoft Excel, consider 1900 to be a leap year. How you handle this issue is determined by whether you want to be correct or compatible. The following code samples show two different ways to determine leap years.

The first procedure uses the VBA DateSerial function to determine leap years. This approach is widely accepted, but may cause problems because it is relying on side effect behavior of how DateSerial is implemented. Because we have seen that Microsoft date time logic can change between versions, or when system-level components (such as the OLE Automation libraries) change, this approach should not be considered 100% reliable:

Function IsLeapYear (intYear As Integer) As Integer
   ' Comments : Determines if the year is a leap year using the
   '     internal DateSerial function
   ' Parameters: intYear - integer year
   '     Note: Always specify the full four digits of the year
   '     or the code cannot be considered Year 2000 compliant.
   ' Returns : True - year is a leap year, False otherwise
   '
On Error GoTo PROC_ERR

   IsLeapYear = Month(DateSerial(intYear, 2, 29)) = 2

PROC_EXIT:
   Exit Function

PROC_ERR:
   MsgBox "Error: " & Err & ". " & Error$
   Resume PROC_EXIT

End Function

Code Listing 9   Determining Leap Years using DateSerial

A better approach is to write your own routine that does not rely on language or operating system components.

Function IsLeapYear2 (intYear As Integer) As Integer
   ' Comments : Determines if the specified year is a leap year without
   '     relying on the DateSerial method.
   ' Parameters: intYear - integer year
   '     Note: Always specify the full four digits of the year
   '     or the code cannot be considered Year 2000 compliant.
   ' Returns : True - year is a leap year, False otherwise
   '
On Error GoTo PROC_ERR

   IsLeapYear2 = False

   If intYear Mod 4 = 0 Then
    If intYear Mod 100 = 0 Then
     If intYear Mod 400 = 0 Then
      IsLeapYear2 = True
     End If
    Else
     IsLeapYear2 = True
    End If
 End If

PROC_EXIT:
   Exit Function

PROC_ERR:
   MsgBox "Error: " & Err & ". " & Error$
   Resume PROC_EXIT

End Function

Code Listing 10   Determining Leap Years with Simple Math

<< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 >>


Send This To a Friend


 

Tuesday, March 16, 1999
1998 Microsoft Corporation. All rights reserved. Terms of use.

This site is being designated as a Year 2000 Readiness Disclosure and the information contained herein is provided pursuant to the terms hereof and the Year 2000 Information and Readiness Disclosure Act.