Monday, October 13, 2008

Persian Calendar Problem

If you've read my older posts, you already know about the problem of FA-IR culture and the default calendar. When creating applications that run in different cultures and languages, Date specific controls like DatePickers, Scheduling controls, etc usually use current Culture's calendar to calculate dates, and to represent a DateTime instance to string representation. Also, control developers use DateTime.MinValue as a default (not set) value. But what happens when a culture's calendar does not accept DateTime.MinValue as a valid date? One example, of course, is our PersianCalendar in which the least possible date is 22/03/622 (in Gregorian calendar) that maps to 1/1/1 in Persian calendar.

Presentation1

It gets worse when you storing data in the database! Suppose a user that uses Gregorian Calendar has logged-in and selected a date in the valid range for Gregorian Calendar, but invalid for Persian Calendar (the red arrows in the picture). What happens when the first user saves the data, and then the user logged in with Persian Calendar tries to load it? You'll have a nice exception on your hand! (This, of course is a hypothetical example. It *might* not be possible to save the date prior to 1753 in some RDBMS). You can't even call ToString() method on DateTime instance that falls in the invalid range!

[Fact]
public void UsingInvalidDateRangeThrows()
{
using (new CultureSwitchContext(new PersianCultureInfo()))
{
DateTime dt = DateTime.MinValue;
Assert.Throws<ArgumentOutOfRangeException>(() => dt.ToString());
}
}
[Fact]
public void CanConvertToStringWithInvariantCulture()
{
using (new CultureSwitchContext(new PersianCultureInfo()))
{
DateTime dt = DateTime.MinValue;
Assert.DoesNotThrow(() => dt.ToString(CultureInfo.InvariantCulture));
}
}

You'll get an exception complaining :

Specified time is not supported in this calendar. It should be between 03/21/0622 00:00:00 (Gregorian date) and 12/31/9999 23:59:59 (Gregorian date), inclusive.

I think I understand why guys at Microsoft BCL decided not to set PersianCalendar as the default calendar of FA-IR culture : Because your application / component may break if you switch to FA-IR culture, but why not set it as an OptionalCalendar?

Lesson learned : Avoid calling DateTime.ToString recklessly, specially if you're developing a Custom Control or creating a multi-cultured application. Pay attension to Calendar.MinSupportedDateTime property.


Submit this story to DotNetKicks Shout it

No comments: