Data and Formats · Lesson 23

Offsets represent instants without naming a time zone

Parse an explicit offset and preserve its relationship to UTC.

How it works

DateTimeOffset combines a local clock reading with an offset from UTC. The input says ten-thirty at plus two hours, which corresponds to eight-thirty UTC. ParseExact specifies the accepted representation, avoiding an accidental dependency on the device's current date-format culture.

The round-trip O format writes an explicit offset and fractional-second precision. Converting the same value to offset zero changes its clock representation, but the equality comparison remains true because both represent the same instant. This distinction is useful when systems display an event locally while comparing its actual occurrence time.

An offset is not a named time zone. Plus two hours does not identify which region's daylight-saving or historical rules apply. Scheduling a future recurring local appointment may require a time-zone identifier and a separate policy for ambiguous or invalid local times. A single fixed offset cannot encode all of those rules.

Do not discard offset information by extracting an unspecified local DateTime and later assuming it was UTC. That can shift the represented instant. Decide at the input boundary whether the data represents an instant, a local calendar date, or a local clock schedule; those are different domain types and should not be casually substituted.

Practice with the same instant written at offset zero and at minus five hours. Verify equality while printing each clock representation. Then change only the clock hour while keeping the offset and explain why the represented instant changes even though the textual date remains the same.

Finally, define the export format and precision required by a small event log. Test explicit positive and negative offsets, malformed input, and a boundary crossing midnight in UTC. The lesson's invariant formatting keeps behavior deterministic in the browser runtime, while the domain contract determines whether a more complete time-zone model is required.

A working example

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

const string text = "2026-11-06T10:30:00+02:00";
var value = DateTimeOffset.ParseExact(text, "yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
Console.WriteLine(value.ToString("O", CultureInfo.InvariantCulture));
Console.WriteLine(value.UtcDateTime.ToString("HH:mm", CultureInfo.InvariantCulture));
Console.WriteLine(value == value.ToOffset(TimeSpan.Zero));

Expected output

2026-11-06T10:30:00.0000000+02:00
08:30
True
Try this
An offset is part of an instant representation, but it is not a time-zone identifier.