The Comprehensive Guide to Custom DateTime String Formats in C#

When working with C#, we can convert a DateTime object to a string. The default string format will be outputted if we don't specify any formatting options. However, C# lets you customise how the DateTime object should be outputted using custom format specifiers.

How do I format DateTime objects?

You can format a DateTime object in a few ways. We'll first go through some of these methods before going through how to use custom format strings to format DateTime objects.

Using DateTime.ToString()

This is probably the most common way of formatting a DateTime as a string in C#. It allows you to optionally pass the format to use as a string parameter. For example:

using System;

class MainClass {
    public static void Main (string[] args) {
        DateTime today = DateTime.Today;
        Console.WriteLine(today.ToString("yyyy-MM-dd"));
    }
}

You can read more information here.

Using string.Format()

You can also specify how a string should be formatted using string.Format() by passing in the DateTime object as one of the objects to be inserted. For example:

using System;

class MainClass {
    public static void Main (string[] args) {
        var today = DateTime.Today;
        Console.WriteLine(string.Format("{0:yyyy-MM-dd}", today));
    }
}

You can read more here.

Using String Interpolation

I prefer this method of formatting DateTime objects. It looks neat and is compact. Here's an example:

using System;

class MainClass {
    public static void Main (string[] args) {
        var today = DateTime.Today;
        Console.WriteLine($"{today:yyyy-MM-dd}");
    }
}

You can read more about string interpolation here.

Custom DateTime Format Strings

We can format a DateTime using a custom format string. A format string is simply a string in C# where sequences of characters (called format specifiers) in the string dictate what portions of the DateTime should be outputted and how they should be formatted. These format specifiers can be combined to output multiple portions of a DateTime object (as well as other objects in .NET) in a single string. This gives you granular control over how DateTime objects should be outputted.

Below is a table of all the string sequences used in custom format strings for DateTime objects:

Format Specifier DateTime Segment Description
"g" or "gg" Era Outputs the era ("B.C." or "A.D.").
Note: Only use "g" for the era when it is used with other format specifiers in the same string (adding "''" will work) otherwise it is interpreted as a standard date and time format specifier.
"y" Year The year from 0 to 99 (excluding the century) without any leading zeros
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "3" for 0903-03-25T08:02:08.6170000
  • "20" for 2020-06-07T13:45:32.0050000
"yy" Year The year from 00 to 99 (excluding the century) with a leading zero where necessary so that the year is always two characters.
Examples:
  • "03" for 0903-03-25T08:02:08.6170000
  • "20" for 2020-06-07T13:45:32.0050000
"yyy" Year The year, with a minimum of three digits.
Examples:
  • "903" for 0903-03-25T08:02:08.6170000
  • "2020" for 2020-06-07T13:45:32.0050000
"yyyy" Year The year as a four-digit number.
Examples:
  • "0903" for 1903-03-25T08:02:08.6170000
  • "2020" for 2020-06-07T13:45:32.0050000
"yyyyy" Year The year as a five-digit number.
Examples:
  • "00903" for 1903-03-25T08:02:08.6170000
  • "02020" for 2020-06-07T13:45:32.0050000
"M" Month The month of the year (from 1 to 12) without any leading zeros.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "3" for 1903-03-25T08:02:08.6170000
  • "6" for 2020-06-07T13:45:32.0050000
"MM" Month The month of the year (from 01 to 12) with a leading zero.
Examples:
  • "03" for 1903-03-25T08:02:08.6170000
  • "06" for 2020-06-07T13:45:32.0050000
"MMM" Month The abbreviated name of the month. This differs based on language and region.
Examples:
  • "Mar" for 1903-03-25T08:02:08.6170000 (en-US)
  • "Jun" for 2020-06-07T13:45:32.0050000 (en-US)
"MMMM" Month The full name of the month. This differs based on language and region.
Examples:
  • "March" for 1903-03-25T08:02:08.6170000 (en-US)
  • "June" for 2020-06-07T13:45:32.0050000 (en-US)
"d" Day The day of the month (from 1 to 31) without any leading zeros.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "25" for 1903-03-25T08:02:08.6170000
  • "7" for 2020-06-07T13:45:32.0050000
"dd" Day The day of the month (from 1 to 31) with a leading zero where necessary so that the date is always two characters.
Examples:
  • "25" for 1903-03-25T08:02:08.6170000
  • "07" for 2020-06-07T13:45:32.0050000
"ddd" Day The abbreviated name of the day of the week.
Examples: Mon, Tues
"dddd" Day The full name of the day of the week.
Examples: Monday, Tuesday
"t" AM/PM The first character of the AM/PM designator.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "A" for 0903-03-25T08:02:08.6170000
  • "P" for 2020-06-07T13:45:32.0050000
"tt" AM/PM The AM/PM designator.
Examples:
  • "AM" for 0903-03-25T08:02:08.6170000
  • "PM" for 2020-06-07T13:45:32.0050000
"h" Hour The hour, using a 12-hour clock (from 1 to 12) without a leading zero.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples: 11 for 11:00:00AM, 1 for 1:00:00PM
"hh" Hour The hour, using a 12-hour clock (from 01 to 12) with a leading zero.
Examples: 11 for 11:00:00AM, 01 for 1:00:00PM
"H" Hour The hour, using a 24-hour clock (from 0 to 23) without a leading zero.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples: 9 for 9:00:00AM, 11 for 11:00:00AM, 13 for 1:00:00PM
"HH" Hour The hour, using a 24-hour clock (from 00 to 23) with a leading zero.
Examples: 09 for 9:00:00AM, 11 for 11:00:00AM, 13 for 1:00:00PM
"m" Minute The minute, from 0 to 59, without a leading zero.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples: 8 for 9:08:00AM, 20 for 1:20:00PM
"mm" Minute The minute, from 00 to 59, with a leading zero.
Examples: 08 for 9:08:00AM, 20 for 1:20:00PM
"s" Second The second, from 0 to 59, without a leading zero.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples: 3 for 9:08:03AM, 45 for 1:20:45PM
"ss" Second The second, from 00 to 59, with a leading zero.
Examples: 03 for 9:08:03AM, 45 for 1:20:45PM
"f" Fraction of Second The tenths of a second, from 0 to 9
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "6" for 1903-03-25T08:02:08.6170000
  • "0" for 2020-06-07T13:45:32.0050000
"ff" Fraction of Second The hundredths of a second, from 00 to 99
Examples:
  • "61" for 0903-03-25T08:02:08.6170000
  • "00" for 2020-06-07T13:45:32.0050000
"fff" Fraction of Second The milliseconds, from 000 to 999
Examples:
  • "617" for 0903-03-25T08:02:08.6170000
  • "000" for 2020-06-07T13:45:32.0005000
"ffff" Fraction of Second The ten thousandths of a second, from 0000 to 9999
Examples:
  • "6170" for 0903-03-25T08:02:08.6170000
  • "0000" for 2020-06-07T13:45:32.0000500
"fffff" Fraction of Second The hundred thousandths of a second, from 00000 to 99999
Examples:
  • "61700" for 0903-03-25T08:02:08.6170000
  • "00000" for 2020-06-07T13:45:32.0000050
"ffffff" Fraction of Second The millionths of a second, from 000000 to 999999
Examples:
  • "617000" for 0903-03-25T08:02:08.6170000
  • "000000" for 2020-06-07T13:45:32.0000005
"fffffff" Fraction of Second The ten millionths of a second, from 0000000 to 9999999
Examples:
  • "6170000" for 0903-03-25T08:02:08.6170000
  • "0000000" for 2020-06-07T13:45:32.0000000
"F" Fraction of Second The tenths of a second, from 0 to 9. Only outputted if the value is non-zero otherwise an empty is outputted.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "6" for 1903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0050000
"FF" Fraction of Second The hundredths of a second, from 00 to 99. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "61" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0050000
"FFF" Fraction of Second The milliseconds, from 000 to 999. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "617" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0005000
"FFFF" Fraction of Second The ten thousandths of a second, from 0000 to 9999. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "6170" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0000500
"FFFFF" Fraction of Second The hundred thousandths of a second, from 00000 to 99999. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "61700" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0000050
"FFFFFF" Fraction of Second The millionths of a second, from 000000 to 999999. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "617000" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0000005
"FFFFFFF" Fraction of Second The ten millionths of a second, from 0000000 to 9999999. Only outputted if the value is non-zero otherwise an empty is outputted.
Examples:
  • "6170000" for 0903-03-25T08:02:08.6170000
  • "" for 2020-06-07T13:45:32.0000000
"K" Time zone This depends on the Kind of DateTime object.
Kinds:
  • Unspecified: ""
  • Utc: "Z"
  • Local: "+02:00"
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
"z" Time zone Hours offset from UTC, with no leading zeros
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "+2" for 0903-03-25T08:02:08+02:00
  • "-7" for 2020-06-07T13:45:32-07:00
"zz" Time zone Hours offset from UTC, with a leading zero for single-digit values
Examples:
  • "+02" for 0903-03-25T08:02:08+02:00
  • "-07" for 2020-06-07T13:45:32-07:00
"zzz" Time zone Hours and minutes offset from UTC
Examples:
  • "+02:00" for 0903-03-25T08:02:08+02:00
  • "-07:00" for 2020-06-07T13:45:32-07:00
"/" Misc The date separator. This is determined based on the region and language.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • "/" for 0903-03-25T08:02:08+02:00 (en-US)
  • "-" for 2020-06-07T13:45:32-07:00 (ar-DZ)
":" Misc The time separator. This is determined based on the region and language.
Note: This will only work when used with other format specifiers in the same string (adding "''" will work).
Examples:
  • ":" for 0903-03-25T08:02:08+02:00 (en-US)
  • "." for 2020-06-07T13:45:32-07:00 (it-IT)
"'<STRING>'" Misc Literal string delimiter. This can be used to escape a string.
"\<CHAR>" Misc Escape character. This can be used to escape a single character in a format specifier

Here's a code snippet demonstrating all the formats described above:

using System;

class MainClass {
    public static void Main(string[] args)
    {
        var today = DateTime.Now;

        Console.WriteLine($"Using date and time: {today.ToString(@"yyyy-MM-dd\THH:mm:ss.fffffffK")}");
        Console.WriteLine();

        // Individual Format Specifiers
        Console.WriteLine("Individual Format Specifiers");
        Console.WriteLine($"1.  {today.ToString("gg")}");
        Console.WriteLine($"2.  {today.ToString("''y")}");
        Console.WriteLine($"3.  {today.ToString("yy")}");
        Console.WriteLine($"4.  {today.ToString("yyy")}");
        Console.WriteLine($"5.  {today.ToString("yyyy")}");
        Console.WriteLine($"6.  {today.ToString("yyyyy")}");
        Console.WriteLine($"7.  {today.ToString("''M")}");
        Console.WriteLine($"8.  {today.ToString("MM")}");
        Console.WriteLine($"9.  {today.ToString("MMM")}");
        Console.WriteLine($"10. {today.ToString("MMMM")}");
        Console.WriteLine($"11. {today.ToString("''d")}");
        Console.WriteLine($"12. {today.ToString("dd")}");
        Console.WriteLine($"13. {today.ToString("ddd")}");
        Console.WriteLine($"14. {today.ToString("dddd")}");
        Console.WriteLine($"15. {today.ToString("''t")}");
        Console.WriteLine($"16. {today.ToString("tt")}");
        Console.WriteLine($"17. {today.ToString("''h")}");
        Console.WriteLine($"18. {today.ToString("hh")}");
        Console.WriteLine($"19. {today.ToString("''H")}");
        Console.WriteLine($"20. {today.ToString("HH")}");
        Console.WriteLine($"21. {today.ToString("''m")}");
        Console.WriteLine($"22. {today.ToString("mm")}");
        Console.WriteLine($"23. {today.ToString("''s")}");
        Console.WriteLine($"24. {today.ToString("ss")}");
        Console.WriteLine($"25. {today.ToString("''f")}");
        Console.WriteLine($"26. {today.ToString("ff")}");
        Console.WriteLine($"27. {today.ToString("fff")}");
        Console.WriteLine($"28. {today.ToString("ffff")}");
        Console.WriteLine($"29. {today.ToString("fffff")}");
        Console.WriteLine($"30. {today.ToString("ffffff")}");
        Console.WriteLine($"31. {today.ToString("fffffff")}");
        Console.WriteLine($"32. {today.ToString("''F")}");
        Console.WriteLine($"33. {today.ToString("FF")}");
        Console.WriteLine($"34. {today.ToString("FFF")}");
        Console.WriteLine($"35. {today.ToString("FFFF")}");
        Console.WriteLine($"36. {today.ToString("FFFFF")}");
        Console.WriteLine($"37. {today.ToString("FFFFFF")}");
        Console.WriteLine($"38. {today.ToString("FFFFFFF")}");
        Console.WriteLine($"39. {today.ToString("''K")}");
        Console.WriteLine($"40. {today.ToString("''z")}");
        Console.WriteLine($"41. {today.ToString("zz")}");
        Console.WriteLine($"42. {today.ToString("zzz")}");
        Console.WriteLine($"43. {today.ToString("''/")}");
        Console.WriteLine($"44. {today.ToString("'':")}");
        Console.WriteLine($"45. {today.ToString("'The date is' yyyy-MM-dd")}");
        Console.WriteLine($"46. {today.ToString(@"\T\h\e \d\a\t\e \i\s yyyy-MM-dd")}");
        Console.WriteLine();

        // Combined Format Specifiers
        Console.WriteLine("Combined Format Specifiers");
        Console.WriteLine($"47. {today.ToString("yyyy-MM-dd")}");
        Console.WriteLine($"48. {today.ToString("d MMMM yyyy")}");
        Console.WriteLine($"49. {today.ToString("dddd, d MMMM yyyy")}");
        Console.WriteLine($"50. {today.ToString("hh:mm:ss tt")}");
        Console.WriteLine($"51. {today.ToString("HH:mm:ss.fffffff")}");
    }
}

You can also run this example in Replit below:

Conclusion

C# comes with helpful default formatting options when working with DateTime objects. However, you're not limited to these defaults. The DateTime object can be formatted using various format specified, giving you the flexibility to format the date and time any way you choose.