Summary#
TimeSpan is a duration — a length of time — exactly as in C#. It is a first-class scalar: you can declare
a TimeSpan local, pass it to a function, and store it on an entity (persisted as an interval). Build one
with the TimeSpan.FromX factories or the new TimeSpan(…) constructor; read its total or component parts
through members.
Signature#
TimeSpan.FromDays(n) / FromHours(n) / FromMinutes(n) / FromSeconds(n) / FromMilliseconds(n) // factories
new TimeSpan(hours, minutes, seconds) // constructor (h/m/s)
new TimeSpan(days, hours, minutes, seconds) // constructor (d/h/m/s)
ts.TotalDays / TotalHours / TotalMinutes / TotalSeconds / TotalMilliseconds // fractional whole-span totals (double)
ts.Days / Hours / Minutes / Seconds // whole component parts (int)
TimeSpan.FromTicks(n) / ts.Ticks // the duration as one integer, in 100ns ticks (long)Description#
A factory takes a numeric count and returns the duration: TimeSpan.FromHours(2) is two hours. The constructor
takes whole components — new TimeSpan(1, 30, 0) is one hour thirty minutes (h, m, s), and the four-argument
form leads with days.
The .TotalX members give the whole span measured in that unit, as a fractional double — TimeSpan.FromMinutes(90).TotalHours
is 1.5. The component members (.Days, .Hours, .Minutes, .Seconds) give the whole-number parts of the
breakdown — for new TimeSpan(1, 2, 30, 0), .Days is 1 and .Hours is 2.
A TimeSpan entity property is stored and read back faithfully:
entity WorkItem {
[Required, MaxLength(200)] string Title;
TimeSpan Estimate;
}
TimeSpan DefaultEstimate() {
return new TimeSpan(1, 30, 0); // 1h30m — the (h, m, s) constructor
}
double EstimateInHours(WorkItem w) {
return w.Estimate.TotalHours; // 90 minutes → 1.5
}
TimeSpan Remaining(WorkItem w, TimeSpan spent) {
return w.Estimate - spent; // durations subtract, exactly as in C#
}
long EstimateTicks(WorkItem w) {
return w.Estimate.Ticks; // the whole duration as one integer — a `long`, always
}
TimeSpan SpanFromTicks(long ticks) {
return TimeSpan.FromTicks(ticks); // …and the exact way back
}The tick — a duration as one exact integer#
A tick is 100 nanoseconds, the unit .NET measures time in, and it is how a duration becomes a single whole
number you can store, compare or put on a wire. ts.Ticks reads one and TimeSpan.FromTicks(n) builds the
duration back, with no loss in either direction:
long precise = TimeSpan.FromMinutes(90).Ticks; // 54000000000
var same = TimeSpan.FromTicks(precise); // ninety minutes again⚠ .Ticks answers a long, never an int — one hour is already 36 billion ticks, well past int's range, so
the local or the field that holds one must say long.
It is the same unit an instant is read with: Date.Ticks(d) (see Reading a date — Year, Month, Day, Hour, Minute, Second, DayOfWeek, DayOfYear, Date) counts ticks since
0001-01-01, so the two agree — Date.Ticks(b) - Date.Ticks(a) and (b - a).Ticks are the same number.
Reach for ticks when you want exactness, an ordering key, or a compact interchange value. For anything a person
reads, prefer .TotalMinutes and the component members: a tick count is precise and unreadable.
Arithmetic and comparison are C#-faithful:
dateTime2 - dateTime1→ aTimeSpan(how much time elapsed).dateTime + timeSpan/dateTime - timeSpan→ a shiftedDateTime.timeSpan1 + timeSpan2/timeSpan1 - timeSpan2→ aTimeSpan;timeSpan * nscales one.<,<=,>,>=,==,!=compare twoTimeSpans (and twoDateTimes).
The same operators work inside a query that runs in the database: Order.Where(o => o.ShippedAt - o.PlacedAt > TimeSpan.FromDays(2)) is answered there, by the instant. A DateTimeOffset mixes in exactly as C# mixes it —
dateTime - dateTimeOffset is a TimeSpan too ([[types-datetimeoffset#mixing]]).
Examples#
Factories, components, and DateTime/TimeSpan arithmetic — the window/debounce shape:
double QuotaMinutes() {
var quota = TimeSpan.FromHours(2);
return quota.TotalMinutes; // 120.0
}
int LeadDays() {
var span = new TimeSpan(1, 2, 30, 0); // 1d 2h 30m
return span.Days; // 1
}
TimeSpan Elapsed(DateTime start, DateTime end) {
return end - start; // DateTime − DateTime → TimeSpan
}
bool LongEnough(DateTime start, DateTime end) {
return (end - start) >= TimeSpan.FromHours(2); // arithmetic + comparison
}A TimeSpan is also a normal entity column:
entity WorkItem {
string Title;
TimeSpan Estimate; // stored as an interval; read back as a TimeSpan
}See also#
- Numeric types & literal suffixes — the numeric counts the factories take
- namespace — where the built-in value types live