Rasool Aghajani
Rasool Aghajani

Reputation: 441

not a valid calendar for the given culture.parameter name: value maybe PC or Windows Problem?

I had a problem with DataGridView to show Date as the Persian calendar. After using this code:

using System.Globalization;
using System.Threading;

...

CultureInfo info = new CultureInfo("fa-Ir")
{
    DateTimeFormat = {Calendar = new PersianCalendar()}
};

Thread.CurrentThread.CurrentCulture = info;

My problem is solved, no problem occurs with my PC or Laptop both are Windows 10 and .netFramwork 4.8

My customer PC with Windows 7 has a problem with only Culture.. Why is that?

Exception Message : not a valid calendar for the given culture.parameter name: value

Upvotes: 2

Views: 977

Answers (2)

Ali Dehghani
Ali Dehghani

Reputation: 176

Based on Rasool Aghajani's answer, I've implemented a new CultureInfo class that you can set as the default culture of your application and all the date times will be in Persian culture format.

using System;
using System.Globalization;
using System.Reflection;

namespace SomeNamespace
{
    public class PersianCulture : CultureInfo
    {
        public PersianCulture() : base("fa-IR")
        {
            if (this.Calendar is PersianCalendar)
                return;

            //do hack here to set the default culture's calendar to PersianCalender on OS versions that are not supporting PersianCalendar as default culture calendar
            var dateTimeFormat = this.DateTimeFormat;

            dateTimeFormat.AMDesignator = "قبل‌ازظهر";
            dateTimeFormat.AbbreviatedDayNames = new string[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" };
            dateTimeFormat.AbbreviatedMonthGenitiveNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
            dateTimeFormat.AbbreviatedMonthNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
            dateTimeFormat.CalendarWeekRule = CalendarWeekRule.FirstDay;
            dateTimeFormat.DateSeparator = "/";
            dateTimeFormat.DayNames = new string[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" };
            dateTimeFormat.FirstDayOfWeek = DayOfWeek.Saturday;
            dateTimeFormat.FullDateTimePattern = "yyyy MMMM d, dddd H:mm:ss";
            dateTimeFormat.LongDatePattern = "yyyy MMMM d, dddd";
            dateTimeFormat.LongTimePattern = "H:mm:ss";
            dateTimeFormat.MonthDayPattern = "MMMM d";
            dateTimeFormat.MonthGenitiveNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
            dateTimeFormat.MonthNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
            dateTimeFormat.PMDesignator = "بعدازظهر";
            dateTimeFormat.ShortDatePattern = "yyyy/M/d";
            dateTimeFormat.ShortTimePattern = "H:mm";
            dateTimeFormat.ShortestDayNames = new string[] { "ی", "د", "س", "چ", "پ", "ج", "ش" };
            dateTimeFormat.TimeSeparator = ":";
            dateTimeFormat.YearMonthPattern = "yyyy MMMM";

            var persianCalendar = new PersianCalendar();

            var dateTimeFormatInfoCalendar = typeof(DateTimeFormatInfo).GetField("calendar", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);

            dateTimeFormatInfoCalendar?.SetValue(dateTimeFormat, persianCalendar);

            var cultureTableRecord = typeof(DateTimeFormatInfo).GetField("m_cultureTableRecord", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
            if (cultureTableRecord != null)
            {
                var dateTimeFormatValue = cultureTableRecord.GetValue(dateTimeFormat);

                var useCurrentCalendarMethodInfo = dateTimeFormatValue.GetType().GetMethod("UseCurrentCalendar", BindingFlags.NonPublic | BindingFlags.Instance);
                if (
                    useCurrentCalendarMethodInfo !=
                    null)
                {
                    var persianCalendarIdPropertyInfo = persianCalendar.GetType().GetProperty("ID", BindingFlags.Instance | BindingFlags.NonPublic);
                    if (
                        persianCalendarIdPropertyInfo !=
                        null)
                        useCurrentCalendarMethodInfo.Invoke(dateTimeFormatValue, new object[] { persianCalendarIdPropertyInfo.GetValue(persianCalendar, null) });
                }
            }

            var cultureCalendar = typeof(CultureInfo).GetField("calendar", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
            cultureCalendar?.SetValue(this, persianCalendar);

            this.DateTimeFormat = dateTimeFormat;
        }
    }
}

Upvotes: 1

Rasool Aghajani
Rasool Aghajani

Reputation: 441

I did replace my old code with this :

        System.Globalization.CultureInfo calture = new System.Globalization.CultureInfo("fa-Ir");
        System.Globalization.DateTimeFormatInfo info = calture.DateTimeFormat;
        info.AbbreviatedDayNames = new string[] { "ی", "د", "س", "چ", "پ", "ج", "ش" };
        info.DayNames = new string[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" };
        info.AbbreviatedMonthNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
        info.MonthNames = new string[] { "فروردین", "ارديبهشت", "خرداد", "تير", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", "" };
        info.AMDesignator = "ق.ظ";
        info.PMDesignator = "ب.ظ";
        info.ShortDatePattern = "yyyy/MM/dd";
        info.FirstDayOfWeek = DayOfWeek.Saturday;
        System.Globalization.PersianCalendar cal = new System.Globalization.PersianCalendar();

        var field = typeof(System.Globalization.DateTimeFormatInfo).GetField("calendar", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        field?.SetValue(info, cal);
        var fieldInfo = typeof(System.Globalization.DateTimeFormatInfo).GetField("m_cultureTableRecord", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        if (fieldInfo != null)
        {
            object obj = fieldInfo.GetValue(info);
            var methodInfo = obj.GetType().GetMethod("UseCurrentCalendar", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            if (
                methodInfo !=
                null)
            {
                var propertyInfo = cal.GetType().GetProperty("ID", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                if (
                    propertyInfo !=
                    null)
                    methodInfo.Invoke(obj, new object[] { propertyInfo.GetValue(cal, null) });
            }
        }
        var field1 = typeof(System.Globalization.CultureInfo).GetField("calendar", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        field1?.SetValue(calture, cal);
        var fieldInfo1 = typeof(System.Globalization.CultureInfo).GetField("calendar", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fieldInfo1?.SetValue(calture, cal);

        System.Threading.Thread.CurrentThread.CurrentCulture = calture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = calture;
        System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat = info;
        System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat = info;

and it's worked as well in all computers... but I dunno .. if some code is true should be worked in all Computers! else if has a problem should not be worked in any computers...

Upvotes: 2

Related Questions