Search code examples
c#silverlightdatetimegregorian-calendar

How to get "DateTime.Now" in the Gregorian format when client calendar is non-Gregorian?


How can I get DateTime.Now in Gregorian calender when client calendar is non-Gregorian?

My project is a Silverlight with C# code and client default calender is not predicted.


Solution

  • A DateTime value has no format. Internally it's just a count of ticks since the epoch, 0001-01-01 00:00 in .NET. Formatting is when you call ToString.

    Just use a different CultureInfo for the culture that has the calendar you want, e.g.

    CultureInfo french = CultureInfo.GetCultureInfo( "fr-FR" );
        
    String nowStr = DateTime.Now.ToString( french );
    Console.WriteLine( nowStr ); // "16/09/2012 05:58:00"
    

    Use CultreInfo.InvariantCulture if you just to use a predictable Western culture with a Gregorian calendar.

    While InvariantCulture is invariant it uses en-US's MM/dd/yyyy date format which the entire rest of the world doesn't use so I recommend always using ISO 8601 instead...

    Copy this code into your project:

    using System;
    using System.Globalization;
    
    public static class CultureInfo2
    {
        /// <summary>A read-only clone of <see cref="P:System.Globalization.CultureInfo.InvariantCulture" />, except the <see cref="P:System.Globalization.CultureInfo.DateTimeFormat" /> is replaced with a <see cref="T:System.Globalization.DateTimeFormatInfo" /> configured to use ISO 8601 formatting for dates and times.</summary>
        public static CultureInfo InvariantCultureWithIso8601 { get; } = CreateInvariantCultureWithIso8601();
    
        private static CultureInfo CreateInvariantCultureWithIso8601()
        {
            CultureInfo obj = (CultureInfo)CultureInfo.InvariantCulture.Clone();
            obj.DateTimeFormat = new DateTimeFormatInfo
            {
                AMDesignator = "AM",
                DateSeparator = "-",
                FirstDayOfWeek = DayOfWeek.Monday,
                CalendarWeekRule = CalendarWeekRule.FirstFourDayWeek,
                FullDateTimePattern = "yyyy-MM-dd HH':'mm':'ss", // NOTE: Use `"yyyy-MM-DD'T'HH:mm:ss"` for stricter ISO 8601 compliance.
                LongDatePattern = "yyyy-MM-dd ddd", // <-- This is subjective.
                LongTimePattern = "HH':'mm':'ss",
                MonthDayPattern = "MMMM dd",
                PMDesignator = "PM",
                ShortDatePattern = "yyyy-MM-dd",
                ShortTimePattern = "HH:mm",
                TimeSeparator = ":",
                YearMonthPattern = "yyyy MMMM"
            };
            return CultureInfo.ReadOnly(obj);
        }
    
        public static String ToStringInvariant( this DateTime value )
        {
            return value.ToString( provider: InvariantCultureWithIso8601 );
        }
    
        public static String ToStringInvariant( this DateTime value, String format )
        {
            return value.ToString( format: format, provider: InvariantCultureWithIso8601 );
        }
    }
    

    And use it like so:

    String nowStr = DateTime.Now.ToStringInvariant();
    Console.WriteLine( nowStr ); // "2012-09-16 05:58:00"