How to solve leap year in Persian calendar

1.1k Views Asked by At

Today is 1397/02/29 (yyyy/mm/dd) in Persian calendar. and my website reports his error:

'Year, Month, and Day parameters describe an un-representable DateTime.'

I used datetime2 in SQL database and saved Persian date in it by converting this date:

PersianCalendar pc = new PersianCalendar();
DateTime dateTime = DateTime.Now;
return new DateTime(pc.GetYear(dateTime), pc.GetMonth(dateTime), pc.GetDayOfMonth(dateTime), pc.GetHour(dateTime), pc.GetMinute(dateTime), pc.GetSecond(dateTime), 0);

What should i do?

2

There are 2 best solutions below

0
On

Quite ignorant here... but in general you should treat "internally" (in the program and in the db) all the dates using the normal Proleptic Gregorian calendar (per ISO 8601), and reformat them to Persian only when you read input from the user/write output to the user. There is a PersianCalendar class in .NET that helps converting persian-to-american and back.

For example

var pc = new PersianCalendar(); 
DateTime dt = pc.ToDateTime(1397, 02, 29, 0, 0, 0, 0); 

works correctly, but if you take a look at the dt variable you'll see that it shows as 2018-05-19.

If doing a ToString() on a DateTime variable you see a persian date, then you probably have an error in your code. If doing a SELECT on a table in the db you see a persian date, then you probably have an error in your db.

The interesting paradox is that internally both .NET and SQL save dates as a single number, representing how many units of time (where in .NET a unit of time is 100 nanoseconds, in SQL it is 1 day) have passed from a "zero point" to the date, but then all their "standard" methods for handling dates (both in .NET and SQL) use the gregorian calendar (because it is the most used in the world).

4
On

Use this solution

static void Main(string[] args)
{
    Console.WriteLine(GetIsLeapDateTime(1358));
    Console.WriteLine(GetIsLeapDateTime(1359));
    Console.WriteLine(GetIsLeapDateTime(1360));
    Console.WriteLine(GetIsLeapDateTime(1361));
    Console.WriteLine(GetIsLeapDateTime(1362));
    Console.WriteLine(GetIsLeapDateTime(1363));
    Console.WriteLine(GetIsLeapDateTime(1364));
    Console.WriteLine(GetIsLeapDateTime(1365));
    Console.WriteLine(GetIsLeapDateTime(1366));
    Console.ReadLine();
}

private static bool GetIsLeapDateTime(int year)
{
    PersianCalendar pc = new PersianCalendar();
    return pc.IsLeapYear(year);
}

in Jalali calendar

It seems that every 33 years, leap years happen once every 5 years and then back to once every 4 years.

1370 is a leap year, but 1374 is not a leap year, and instead, 1375 is a leap year. Also, 1403 is not a leap year and 1407 is not a leap year, and instead, 1408 leap years.