DateTime
ToString
C#
date formatting
programming error

why does DateTime.ToStringdd/MM/yyyy give me dd-MM-yyyy?

Master System Design with Codemia

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

Introduction

In .NET date formatting, the slash character in a custom date pattern is not always treated as a literal slash. It is often interpreted as the date separator placeholder, which means the runtime can replace it with the current culture's actual date separator, such as a dash.

Why "dd/MM/yyyy" Can Become dd-MM-yyyy

When you call DateTime.ToString("dd/MM/yyyy"), the / is culture-sensitive in many formatting contexts. If the current culture uses - as its date separator, the result can come out as dd-MM-yyyy.

Example:

csharp
1using System;
2using System.Globalization;
3using System.Threading;
4
5Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
6DateTime dt = new DateTime(2025, 3, 7);
7
8Console.WriteLine(dt.ToString("dd/MM/yyyy"));

Depending on the culture, the output may show dashes even though the format string appears to contain slashes.

That surprises people because the format string looks literal, but / is acting as a date-separator token.

Use Literal Slashes If You Really Mean Slashes

If you want actual slash characters regardless of culture, escape them or quote them.

csharp
1using System;
2
3DateTime dt = new DateTime(2025, 3, 7);
4
5Console.WriteLine(dt.ToString("dd'/'MM'/'yyyy"));
6Console.WriteLine(dt.ToString("dd\/MM\/yyyy"));

Both approaches force literal slashes into the output.

This is the most direct fix when your format must stay exactly dd/MM/yyyy no matter what the current culture is.

Use InvariantCulture When Appropriate

Another useful approach is to specify a culture explicitly.

csharp
1using System;
2using System.Globalization;
3
4DateTime dt = new DateTime(2025, 3, 7);
5Console.WriteLine(dt.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));

InvariantCulture gives you a stable formatting baseline that is not tied to the current thread culture. That is often the right choice for:

  • serialization
  • logs
  • APIs
  • stable file names

But remember that if you still use unescaped /, the formatting system is still thinking in terms of a date separator token. In practice, the invariant culture uses /, so the result looks as you expect.

The Date Separator Comes from DateTimeFormatInfo

Under the hood, the culture provides a DateSeparator value through its date formatting settings. That is why / behaves like a placeholder rather than a hard-coded character.

You can see it directly:

csharp
1using System;
2using System.Globalization;
3
4var culture = new CultureInfo("da-DK");
5Console.WriteLine(culture.DateTimeFormat.DateSeparator);

If that separator is -, then an unescaped / in the custom date format can be rendered as -. Seeing the separator value directly often makes the behavior much less mysterious.

Culture-Specific Output Is Usually Correct

The format system is not malfunctioning when it swaps separators. It is doing what culture-aware formatting is designed to do.

That means the right question is not "why is .NET ignoring my format". The right question is "do I want culture-aware formatting or literal formatting".

If the answer is culture-aware display for users, let the culture choose the separator. If the answer is exact, machine-stable text, force literal characters or use an explicit culture.

A Quick Comparison

This short example makes the difference obvious:

csharp
1using System;
2using System.Globalization;
3
4DateTime dt = new DateTime(2025, 3, 7);
5
6Console.WriteLine(dt.ToString("dd/MM/yyyy", new CultureInfo("en-GB")));
7Console.WriteLine(dt.ToString("dd/MM/yyyy", new CultureInfo("da-DK")));
8Console.WriteLine(dt.ToString("dd'/'MM'/'yyyy", new CultureInfo("da-DK")));

The last line forces literal slashes even under a culture that prefers a different separator.

Common Pitfalls

  • Assuming / in a .NET date format string is always a literal slash.
  • Forgetting that DateTime.ToString is culture-sensitive by default.
  • Using user-facing culture-aware formatting where a machine-stable format is required.
  • Using InvariantCulture without understanding when localized formatting is actually desired.
  • Forgetting to escape or quote separators when the exact character matters.

Summary

  • In .NET date formats, / often means "date separator" rather than a literal slash.
  • The current culture can replace that placeholder with - or another separator.
  • Use quoted or escaped slashes when the output must literally contain /.
  • Use an explicit culture such as InvariantCulture when formatting must be stable.
  • Decide whether the output is for users or for machines before choosing the formatting approach.

Course illustration
Course illustration

All Rights Reserved.