problem with persian calendar in year 1400

753 views Asked by At

I want to change Persian date to standard DateTime format in C# using Persian calendar class. but because of changing the year to 1400, it throws an exception like this:

ArgumentOutOfRangeException: Specified time is not supported in this calendar. It should be between 22/03/22 12:00:00 AM (Gregorian date) and 99/12/31 11:59:59 PM (Gregorian date), inclusive. (Parameter 'time')
Actual value was 0.

I checked the persian calendar class and I found this:

if (year < 1 || year > MaxCalendarYear || month < 1 || month > 12)
{
  throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
}

that throws exception. now what should I do to solve this problem?

2

There are 2 answers

0
Dmitry Bychenko On

Why not explict conversion with a help of PersianCalendar class?

using System.Globalization;

...

// What does Gregorian date correspond to Persian new year (1400)? 
int year = 1400;
int month = 1;
int day = 1;

DateTime result = new PersianCalendar().ToDateTime(year, month, day, 0, 0, 0, 0);

Console.WriteLine($"{result:dd MMMM yyyy}");

Outcome:

21 March 2021

ArgumentOutOfRangeException is thrown when at least one of arguments is out of range: month should be within 1..12 etc.

0
tmaj On

Summary

You're passing an empty DateTime (e.g. new DateTime()) to one of the methods of the mighty PersianCalendar.

Please note that DateTime is a struct (not a class) and any property or variable that's of type DateTime that was not initialised/set will have this min value.

Maybe you're deserialising a json that doesn't have this value but the property of the class is not nullable. Maybe the column in the database is null but the model's property is not nullable etc.

Details

The exception is thrown by PersianCalendar's CheckTicksRange method called by many methods in the class:

internal static void CheckTicksRange(long ticks)
{
    if (ticks < s_minDate.Ticks || ticks > s_maxDate.Ticks)
    {
        throw new ArgumentOutOfRangeException(
            "time",
            ticks,
            SR.Format(SR.ArgumentOutOfRange_CalendarRange, s_minDate, s_maxDate));
    }
}

The error message you got ends with string: Actual value was 0.. This means that the passed in DateTime had 0 ticks which means it is empty.

For example:

try
{
    new PersianCalendar().GetYear(time: new DateTime());
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

This results in:

Specified time is not supported in this calendar. It should be between 22/03/0622 00:00:00 (Gregorian date) and 31/12/9999 23:59:59 (Gregorian date), inclusive. (Parameter 'time')
Actual value was 0.  

Please note the 'Actual value was 0.`.

Please also note that with my locale the exception is a bit more clear because the dates contain a 4 digit year.

If we use an invalid date, but one that's not empty the end of the exception message will be different:

new PersianCalendar().GetYear(time: new DateTime(year: 622, month: 1, day: 1));

results in:

Specified time is not ... 
... 'time')
Actual value was 195968160000000000.