Day Suffix Using a Custom Formatter — Digitteck
Day Suffix Using a Custom Formatter
dotnet·28 May 2019·2 min read

Day Suffix Using a Custom Formatter

When displaying a formatted date with a day suffix (1st, 2nd, 3rd, 4th…) it is tempting to use string manipulation helpers. .NET provides a cleaner mechanism for this: implementing IFormatProvider and ICustomFormatter — the same extensibility point used by string.Format and string interpolation.

How It Works

  • IFormatProvider.GetFormat is called by string.Format to discover what formatter object it should use. Return this when ICustomFormatter is requested.
  • ICustomFormatter.Format receives the format string and the argument. Use custom tokens — nn (lowercase) and NN (uppercase) — that standard DateTime.ToString passes through unchanged, then replace them with the correct suffix.

Usage

csharp
// Using the custom formatter with string.Format
// The "nn" token in the format string will be replaced by the day suffix (st, nd, rd, th)
static void Main(string[] args)
{
    Console.WriteLine(string.Format(new DaySuffixFormatter(), "{0:ddnn MMMM}", DateTime.Now));
    // Output example: 28th May
}

Implementation

csharp
public class DaySuffixFormatter : IFormatProvider, ICustomFormatter
{
    // IFormatProvider — return this instance when ICustomFormatter is requested
    public object GetFormat(Type formatType)
    {
        return (formatType == typeof(ICustomFormatter)) ? this : null;
    }

    // ICustomFormatter — intercept DateTime values and expand the "nn" / "NN" token
    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg is DateTime dateTime)
        {
            string formatted = dateTime.ToString(format);

            // Replace nn with lowercase suffix, NN with uppercase suffix
            formatted = formatted.Replace("nn", AddDaySuffix(dateTime.Day).ToLower());
            formatted = formatted.Replace("NN", AddDaySuffix(dateTime.Day).ToUpper());

            if (formatted.StartsWith("0"))
                formatted = formatted.Remove(0, 1);

            return formatted;
        }

        return string.Format(format, arg);
    }

    private string AddDaySuffix(int integer)
    {
        // 11th, 12th, 13th are exceptions to the last-digit rule
        switch (integer % 100)
        {
            case 11:
            case 12:
            case 13:
                return "th";
        }

        switch (integer % 10)
        {
            case 1:  return "st";
            case 2:  return "nd";
            case 3:  return "rd";
            default: return "th";
        }
    }
}

Tags

.NETC#Formatting
digitteck

© 2026 Digitteck