How to Convert DateTime to an ISO 8601 String in C#? A Problem That Troubles Even Experienced Developers
\n\nHave you ever encountered a situation where your API returns a date in the format "2023-01-15T10:30:00", but the client doesn't understand it? Or, conversely, you receive a date from an external service that looks like "2023-01-15T10:30:00+03:00", and your parser breaks? Sound familiar? If you work with C# and the DateTime object, the issue of obtaining an ISO 8601 string is a classic. This question has garnered thousands of views on Stack Overflow, and for good reason. Today, we will once and for all figure out how to correctly convert DateTime to an ISO 8601 format string, avoiding common pitfalls.
We won't just show a couple of lines of code. We will break down the C# DateTime format for ISO 8601, examine working with time zones, milliseconds, and answer the most frequent questions. Let's go!
\n\nWhat is ISO 8601 and Why is it Important?
\n\nISO 8601 is an international standard for representing dates and times. It looks like this: 2023-12-25T14:30:00.0000000+03:00. Key features:
- \n
- T separator between date and time. \n
- Time zone is indicated at the end (Z for UTC or an offset like +05:00). \n
- Fractional part of seconds (milliseconds, ticks). \n
Why is this necessary? JSON, XML, REST APIs, databases — everywhere you need an unambiguous transmission of a point in time, without being tied to the server's local culture. An incorrect format — and your parser on the other side might discard hours or confuse the day with the month. Therefore, the ISO 8601 date format in C# is a must-have skill for any backend developer.
\n\nThe Simplest Way: DateTime.ToString() with the "o" Format
\n\nIn C#, there is a built-in format specifier for the round-trip format — the letter "o" (lowercase). It provides a complete ISO 8601 string with maximum precision.
\n\nDateTime now = DateTime.Now;\nstring isoString = now.ToString("o");\nConsole.WriteLine(isoString);\n// Example output: 2023-12-25T14:30:00.1234567+03:00\n\nThis is the simplest way to get an ISO 8601 string in C#. But there is a nuance: if your DateTime has Kind = Unspecified, then the time zone will not be indicated at the end of the string. This can be a problem for strict parsers. The solution is to always use DateTimeOffset or explicitly set the Kind.
How to Get ISO 8601 Without Milliseconds?
\n\nSometimes milliseconds (or even ticks) are not needed. For example, for logs or simple dates. Use a custom format:
\n\nDateTime now = DateTime.UtcNow;\nstring isoShort = now.ToString("yyyy-MM-ddTHH:mm:ssK");\nConsole.WriteLine(isoShort);\n// Example: 2023-12-25T14:30:00Z\n\nHere, K is the time zone specifier. For UTC it gives Z, for local time it gives the offset.
The Problem with Time Zones: DateTime vs DateTimeOffset
\n\nThe main pain point for developers is the confusion between DateTime and DateTimeOffset. If you want to get an ISO 8601 date in C# that will be unambiguously interpreted anywhere in the world, use DateTimeOffset. It always contains the offset from UTC.
\n\nDateTimeOffset nowOffset = DateTimeOffset.Now;\nstring isoOffset = nowOffset.ToString("o");\nConsole.WriteLine(isoOffset);\n// Example: 2023-12-25T14:30:00.1234567+03:00\n\nIf you are working with DateTime, always check its Kind property:
- \n
DateTimeKind.Utc— givesZat the end. \n DateTimeKind.Local— gives the local offset (e.g., +03:00). \n DateTimeKind.Unspecified— gives noth