.netstring.formatordinaldatetimeformatinfo

Is String.Format and DateTimeFormatInfo pluggable/extensible?


So for example lets say when I string.format a date and use the string "or" in format pattern I want that converted to the ordinal value of the Date.

ie

string.Format("{0:ddor MMM yyyy}.", DateTime.Now)

should output

1st Jan 2010

See below for how to derive the ordinal numbers

Is there an easy way in .NET to get "st", "nd", "rd" and "th" endings for numbers?


Solution

  • It seems there isn't something like it.

    The most recommended way to do it:

    var d = DateTime.Now;
    var result2 = String.Format("{0:dd}{1} {2:MMM yyyy}", d, Ordinal(d.Day), d);
    

    A very hacky way to achieve it is to create a custom IFormatProvider. IMO it's just a lot of trouble, but just to show an alternative way... (I don't have much experience with this, It might not be very "correct")

    using System;
    
    namespace Test
    {
        class Program
        {
            public static string Ordinal(int number)
            {
                string suffix = String.Empty;
    
                int ones = number % 10;
                int tens = (int)Math.Floor(number / 10M) % 10;
    
                if (tens == 1)
                {
                    suffix = @"\t\h";
                }
                else
                {
                    switch (ones)
                    {
                        case 1:
                            suffix = @"\s\t";
                            break;
    
                        case 2:
                            suffix = @"\n\d";
                            break;
    
                        case 3:
                            suffix = @"\r\d";
                            break;
    
                        default:
                            suffix = @"\t\h";
                            break;
                    }
                }
                return suffix;
            }
    
            public class MyFormat : IFormatProvider, ICustomFormatter
            {
                public object GetFormat(Type formatType)
                {
                    return (formatType == typeof(ICustomFormatter)) ? this : null;
    
                }
    
                public string Format(string format, object arg, IFormatProvider formatProvider)
                {
                    var d = (DateTime)arg;
    
                    var or = Ordinal(d.Day);
    
                    format = format.Replace("or", or);
    
                    return d.ToString(format);
                }
            }
            static void Main(string[] args)
            {
                var result = String.Format(new MyFormat(), "{0:ddor MMM yyyy}.", DateTime.Now);
    
                return;
            }
        }
    }
    

    More info on Custom IFormatProvider