C#
DateTime
programming
suffix
.NET

Getting day suffix when using DateTime.ToString

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

DateTime.ToString() can format day numbers, month names, and years, but it does not include ordinal suffixes such as st, nd, rd, or th. If you need output like March 4th, 2026, you have to add that rule yourself. The logic is short, but it needs to handle the special cases correctly, especially 11th, 12th, and 13th.

Why Format Strings Are Not Enough

Custom date format strings in .NET can easily produce the numeric day.

csharp
1using System;
2
3var date = new DateTime(2026, 3, 4);
4Console.WriteLine(date.ToString("MMMM d, yyyy"));

That prints:

text
March 4, 2026

There is no built-in format specifier that automatically transforms 4 into 4th. So the clean solution is to format the date and the suffix separately, then combine them.

Write a Small Suffix Helper

A helper method is usually the simplest and most reusable approach.

csharp
1using System;
2
3public static class DateFormatting
4{
5    public static string GetDaySuffix(int day)
6    {
7        if (day < 1 || day > 31)
8        {
9            throw new ArgumentOutOfRangeException(nameof(day));
10        }
11
12        if (day % 100 is 11 or 12 or 13)
13        {
14            return "th";
15        }
16
17        return (day % 10) switch
18        {
19            1 => "st",
20            2 => "nd",
21            3 => "rd",
22            _ => "th"
23        };
24    }
25
26    public static string ToOrdinalDateString(DateTime date)
27    {
28        return $"{date:MMMM} {date.Day}{GetDaySuffix(date.Day)}, {date:yyyy}";
29    }
30}

This is the main rule set you need for English ordinal formatting. The special handling for values ending in 11, 12, and 13 is what prevents mistakes such as 11st.

Use an Extension Method for Cleaner Call Sites

If ordinal dates are used across several views or email templates, an extension method can make the call more natural.

csharp
1using System;
2
3public static class DateTimeExtensions
4{
5    public static string ToOrdinalString(this DateTime date)
6    {
7        static string Suffix(int day)
8        {
9            if (day % 100 is 11 or 12 or 13) return "th";
10            return (day % 10) switch
11            {
12                1 => "st",
13                2 => "nd",
14                3 => "rd",
15                _ => "th"
16            };
17        }
18
19        return $"{date:dddd, MMMM} {date.Day}{Suffix(date.Day)}, {date:yyyy}";
20    }
21}

Then usage becomes straightforward:

csharp
var today = new DateTime(2026, 3, 21);
Console.WriteLine(today.ToOrdinalString());

That style is convenient when the formatting behavior belongs to the date itself from the caller's point of view.

Think About Localization Early

The suffix logic above is specifically for English. That is fine if the application is English-only, but it becomes incorrect the moment the output is expected to respect user culture. Many languages do not use these suffixes at all, and others express ordinals differently.

So a good design choice is:

  • keep ordinal suffix logic isolated in one place
  • use it only in English-specific output paths
  • avoid pretending it is a universal date-format feature

If your application is multilingual, you may be better off using culture-specific wording that avoids ordinal suffixes entirely.

Unit Tests Matter More Than the Code Size Suggests

The helper is short, but it is exactly the kind of logic people get wrong because the common cases look obvious.

csharp
1using Xunit;
2
3public class DateFormattingTests
4{
5    [Theory]
6    [InlineData(1, "st")]
7    [InlineData(2, "nd")]
8    [InlineData(3, "rd")]
9    [InlineData(4, "th")]
10    [InlineData(11, "th")]
11    [InlineData(12, "th")]
12    [InlineData(13, "th")]
13    [InlineData(21, "st")]
14    [InlineData(22, "nd")]
15    [InlineData(23, "rd")]
16    [InlineData(31, "st")]
17    public void GetDaySuffix_ReturnsExpectedValue(int day, string expected)
18    {
19        Assert.Equal(expected, DateFormatting.GetDaySuffix(day));
20    }
21}

These tests are small, but they lock down the edge cases that are easiest to forget.

Do Not Spread the Logic Around

One of the worst outcomes is duplicating the suffix logic in controllers, email builders, and UI templates. The code is short enough that duplication feels harmless, but it creates drift over time.

Centralizing the rule in one helper or extension method gives you one place to test, one place to localize, and one place to fix if requirements change.

Common Pitfalls

  • Assuming DateTime.ToString() has a built-in format token for ordinal day suffixes.
  • Forgetting the 11th, 12th, and 13th exceptions and applying only the last-digit rule.
  • Hardcoding English ordinal output in a multilingual application.
  • Copying the suffix logic into multiple files instead of reusing one helper.
  • Skipping tests because the helper seems too small to fail.

Summary

  • '.NET date format strings do not generate st, nd, rd, or th automatically.'
  • The normal solution is a small helper or extension method.
  • The teen values 11, 12, and 13 must be handled as special cases.
  • Ordinal suffix logic is English-specific and should be treated that way.
  • Centralizing and testing the rule prevents easy-to-miss formatting bugs.

Course illustration
Course illustration

All Rights Reserved.