Question
Given a C# DateTime value such as:
DateTime.UtcNow
how can you convert it to a string in an ISO 8601-compliant format?
The specific format needed is:
yyyy-MM-ddTHH:mm:ssZ
In other words, the result should look like a UTC timestamp such as 2026-06-10T14:30:00Z.
Short Answer
By the end of this page, you will understand how to format a C# DateTime as an ISO 8601 string, especially in the yyyy-MM-ddTHH:mm:ssZ UTC format. You will also learn why UTC matters, how custom date format strings work, when to use standard format specifiers like o and s, and how to avoid common mistakes with time zones and literal characters.
Concept
In C#, a DateTime stores a date and time value, but that value is not automatically displayed in a specific string format. To turn it into text, you must format it.
ISO 8601 is an international standard for writing dates and times in a predictable, machine-friendly way. A common UTC form is:
yyyy-MM-ddTHH:mm:ssZ
This means:
yyyy= 4-digit yearMM= 2-digit monthdd= 2-digit dayT= separator between date and timeHH= hour in 24-hour formatmm= minutesss= secondsZ= UTC indicator
In C#, you usually create this output with ToString(...) and a format string.
A correct example is:
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
However, there is an important detail: the Z in ISO 8601 means the time is in UTC. So this format should only be used when the value is actually UTC, such as or a value converted with .
Mental Model
Think of a DateTime as a moment written on a note, and formatting as choosing how that note should be printed.
- The
DateTimeis the actual value. - The format string is the template.
- The final string is the printed label.
For ISO 8601:
2026-06-10T14:30:00Zis like a shipping label with a strict international format.- Everyone reading it knows where the year, month, day, hour, minute, and second are.
- The
Ztells everyone, "this time is in UTC."
If you put Z on a local time, it is like labeling a package with the wrong destination country. The label looks valid, but the meaning is wrong.
Syntax and Examples
In C#, you format a DateTime with ToString().
Basic syntax
dateTime.ToString("format")
ISO 8601 UTC format
DateTime now = DateTime.UtcNow;
string iso = now.ToString("yyyy-MM-ddTHH:mm:ssZ");
Console.WriteLine(iso);
Possible output:
2026-06-10T14:30:00Z
This works because:
nowis already UTC- the format matches the requested pattern exactly
Safer version with explicit UTC conversion
DateTime date = DateTime.Now;
string iso = date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ");
Use this when your starting value may be local time.
Using invariant culture
For machine-readable timestamps, it is common to be explicit:
using System.Globalization;
DateTime now = DateTime.UtcNow;
string iso = now.ToString(, CultureInfo.InvariantCulture);
Step by Step Execution
Consider this example:
DateTime dt = new DateTime(2026, 6, 10, 14, 30, 45, DateTimeKind.Utc);
string result = dt.ToString("yyyy-MM-ddTHH:mm:ssZ");
Console.WriteLine(result);
Step by step:
dtis created with the value2026-06-10 14:30:45.DateTimeKind.Utcmarks the value as UTC.ToString("yyyy-MM-ddTHH:mm:ssZ")applies the custom format.- Each part of the format string is replaced:
yyyy→2026MM→06dd→10T→THH→14
Real World Use Cases
ISO 8601 timestamps are used everywhere because they are easy for both humans and systems to read.
Common uses
- Web APIs: sending timestamps in JSON responses
- Logging: recording events in a standard timezone
- Databases: storing exported timestamps consistently
- Distributed systems: avoiding confusion across time zones
- File naming: generating sortable date strings
Example: API response
var response = new
{
createdAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
};
Example: application log
string logLine = $"[{DateTime.UtcNow:yyyy-MM-ddTHH:mm:ssZ}] User logged in";
Console.WriteLine(logLine);
Example: export record timestamp
string exportedAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
Using UTC makes timestamps consistent even when servers and users are in different countries.
Real Codebase Usage
In real projects, developers rarely format dates randomly. They usually follow a few patterns.
1. Convert to UTC before serialization
string timestamp = someDate.ToUniversalTime()
.ToString("yyyy-MM-ddTHH:mm:ssZ");
This avoids accidental local-time output.
2. Use helper methods
Teams often centralize formatting logic:
using System.Globalization;
public static class DateFormatting
{
public static string ToIsoUtc(DateTime dateTime)
{
return dateTime.ToUniversalTime()
.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture);
}
}
This reduces duplication and keeps output consistent.
3. Use guard clauses for nullable values
public static string? ToIsoUtc(DateTime? dateTime)
{
if (dateTime == null)
return null;
return dateTime.Value.ToUniversalTime()
.ToString();
}
Common Mistakes
1. Adding Z to a non-UTC time
Broken example:
DateTime local = DateTime.Now;
string text = local.ToString("yyyy-MM-ddTHH:mm:ssZ");
Why it is wrong:
DateTime.Nowis local timeZmeans UTC- the string claims something false
Fix:
string text = local.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ");
2. Using hh instead of HH
Broken example:
DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")
Problem:
hhis 12-hour clockHHis 24-hour clock- ISO 8601 uses 24-hour format
Fix:
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
Comparisons
| Option | Example output | Includes timezone info | Exact match for yyyy-MM-ddTHH:mm:ssZ? | Notes |
|---|---|---|---|---|
Custom format "yyyy-MM-ddTHH:mm:ssZ" | 2026-06-10T14:30:00Z | Yes, by literal Z | Yes | Use only for UTC values |
Custom format "yyyy-MM-dd'T'HH:mm:ss'Z'" | 2026-06-10T14:30:00Z | Yes, by literal Z | Yes | Clearer because literals are escaped |
Standard "s" | 2026-06-10T14:30:00 |
Cheat Sheet
Quick syntax
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
Safer explicit literal version
DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'")
Convert local time to UTC first
DateTime.Now.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'")
Common format parts
yyyy= yearMM= monthdd= dayHH= 24-hour hourmm= minutesss= seconds'T'= literalT'Z'= literalZ
Important rules
- Use
Zonly for UTC values - Prefer if the source is not already UTC
FAQ
How do I format a DateTime as ISO 8601 in C#?
Use ToString() with a custom format:
DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'")
Why should I use UtcNow instead of Now?
UtcNow already represents UTC time. If you use Now, you should convert it with .ToUniversalTime() before adding Z.
Is "o" an ISO 8601 format in C#?
Yes. The o format specifier produces a round-trip ISO 8601 string, usually including fractional seconds.
What does the Z mean at the end of a timestamp?
It means the time is in UTC, also called Zulu time.
Should I escape T and Z in the format string?
It is a good idea for clarity:
Mini Project
Description
Build a small C# utility that formats timestamps for an API log. The project demonstrates how to safely convert DateTime values to UTC and output them in the exact ISO 8601 format yyyy-MM-ddTHH:mm:ssZ.
Goal
Create a reusable method that accepts a DateTime and returns a correctly formatted UTC timestamp string.
Requirements
- Create a method that accepts a
DateTimeparameter. - Convert the value to UTC before formatting.
- Return the result in the exact format
yyyy-MM-ddTHH:mm:ssZ. - Test the method with both
DateTime.NowandDateTime.UtcNow. - Print the formatted results to the console.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.