Engineering

Mar 6, 2020

Is Leap year a threat?

a calendar with the word jan on it
a calendar with the word jan on it
DateTime sampleDate = new DateTime(2019, 1, 1);
DateTime nextSampleDate = date.AddYears(1); //the next date will be 2020 Jan 1

We have an algorithm that generates data for present day of next year. This algorithm is executed daily which ensures the availability of data for the forthcoming year.
But here the leap year became an edge case and put a hole in our algorithm.

Current Day

Data generated for the day

February 27 2019

February 27 2020

February 28 2019

February 28 2020

March 1 2019

March 1 2020

Unfortunately, 2020 is a leap year and the data generation was skipped for the 29th of February. We didn't realize it until the day came. On February 29th of 2020, there was no data in the database. As we handled the case when there is no data, there were no crashes reported.

One way we could have solved the issue was by using
AddDays(365) instead of AddYears(1). After evaluating the outcomes of this implementation, we observed the generation of anti-pattern dates.

Current Day

Data generated day

February 27 2019

February 27 2020

February 28 2019

February 28 2020

March 1 2019

February 29 2020

March 2 2019

March 1 2020

January 1 2020

December 31 2020


There were fewer concerns about the performance since it is executing once in a day. So we decided to generate for both days if there is a possibility of skipping the leap day.


public async Task GenerateData()
{
    //Get current utc date
    DateTime currentDate = DateTime.UtcNow;
    DateTime nextYearDate = currentDate.AddYears(1);
    
    //Generate data for the current date
    await GenerateData(nextYearDate);

    //check if there is any upcoming leap day
    if (nextYearDate.Day == 28 && nextYearDate.Month == 2
    && DateTime.IsLeapYear(nextYearDate.Year))
    {
        await GenerateData(nextYearDate.AddDays(1));
    }
}

public async Task GenerateData(DateTime date)
{
    /* 
    code for generating data for the given date    
    */

The output of this updated algorithm shows that the data of the leap day gets generated at the right time.

RecurringJob.AddOrUpdate<IGenerationService>("IGenerationService-GenerateData",
gs => gs.GenerateData(), Cron.Daily);     //Generate data for the day

Current Day

Data generated days

February 27 2019

February 27 2020

February 28 2019

February 28 2020, February 29 2020

March 1 2019

March 1 2020

March 2 2019

March 2 2020

There exists a significant amount of leap year issues reported around the world. Even though the problem we encountered may seem small, the impact it can create was almost huge. We were able to identify the issue at an early stage and was able to release a Hotfix. Mistakes can happen to anyone. We grow when we learn from our mistakes, and sharing it will help others grow along.



Ready to Build something epic

Start your journey with Fantacode today.