Summary#
Given a DateTime, these read one component out of it: Year, Month, Day, Hour, Minute, Second
(each an int), DayOfWeek (a DayOfWeek, as in C#), DayOfYear (an int, 1 January = 1), and Date (the same instant truncated to
midnight). The same readers also work on a TimeSpan, DateOnly, TimeOnly DateOnly or TimeOnly.
Signature#
d.Year / d.Month / d.Day -> int
d.Hour / d.Minute / d.Second -> int
d.DayOfWeek -> DayOfWeek // DayOfWeek.Sunday … DayOfWeek.Saturday; (int) gives 0 … 6
d.DayOfYear -> int // 1 January = 1, … 31 December = 365, or 366 in a leap year
d.Date -> DateTime // same date, time set to 00:00:00Description#
Each reader pulls a single field out of the value. Month is 1-based (January is 1, not 0 — unlike a
JavaScript Date), and Day is the day of the month.
DayOfWeek is the DayOfWeek enum, as in C#. 2024-03-15, a Friday, gives DayOfWeek.Friday, and
$"{d.DayOfWeek}" prints Friday. Compare it with a member (d.DayOfWeek == DayOfWeek.Sunday). For the number, cast
it: (int)d.DayOfWeek counts from Sunday, so Sunday is 0, Monday is 1, up to Saturday at 6.
DayOfYear counts from 1 January, which is 1. 31 December is 365, or 366 in a leap year, so
2024-03-15 gives 75 (a leap year) and 2025-03-15 gives 74. It is what an ISO week number is computed
from — week 1 is the week holding the year's first Thursday:
string IsoWeek(DateTime d) {
var thursday = d.Date.AddDays(3 - (((int)d.DayOfWeek + 6) % 7)); // the Thursday of d's Monday-first week
return $"{thursday.Year}-W{(thursday.DayOfYear - 1) / 7 + 1:D2}";
}Date truncates to midnight. It returns a DateTime on the same calendar day with the time cleared to
00:00:00, which is how you compare two timestamps "on the same day" or bucket by day.
The same readers work on a DateOnly and a TimeOnly. someDate.Month reads the month off a DateOnly;
someTime.Hour reads the hour off a TimeOnly — the part-reader widens to whichever value you give it.
The member syntax d.Month is the everyday spelling; the compiler knows these readers as Date.Year,
Date.Month, Date.Day, Date.Hour, Date.Minute, Date.Second, Date.DayOfWeek, Date.DayOfYear and Date.Date, and
they can also be written in that call form (Date.Month(d)).
All of these are pure functions of the value, so they run in the browser with no round trip (Crossing the network). For the current instant to read them off, see Current time (DateTime.UtcNow, DurableClock.Now).
The whole instant as one number — Date.Ticks#
When you want an instant as a single comparable/storable number rather than as parts, Date.Ticks(d) answers it —
one number that orders the same way the instants do. Use it for an ordering key or a compact stamp, not for
arithmetic you could write with the date operators themselves:
```osy title="an instant as one orderable number — and it is a long" syntax
long stamp = Date.Ticks(DateTime.UtcNow);
⚠ **It is a `long`, not an `int`** — the tick count passed `int`'s range in 1970, so a variable or a field holding
one must say `long`.
**Shifting by ticks** is `Date.AddTicks(d, n)`, written `d.AddTicks(n)` — the finest-grained of the `AddX` family,
below `AddMilliseconds`. A tick is 100 nanoseconds, so it is the member to reach for when you need to step an
instant by the smallest amount it can represent, most often to sit just inside or just outside a boundary:
```osy title="the last instant before midnight" syntax
var endOfDay = DateTime.UtcNow.Date.AddDays(1).AddTicks(-1);Like the rest of the family it keeps the receiver's type: given a DateTimeOffset it answers a
DateTimeOffset, still carrying its offset. The duration side of the same unit — TimeSpan.FromTicks and
ts.Ticks — is on TimeSpan (durations).
Examples#
bool IsWeekend(DateTime d) {
return d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday;
}[Test]
void Date_parts() {
var d = DateTime.New(2024, 3, 15, 13, 45, 30);
Assert.Equal(2024, d.Year);
Assert.Equal(3, d.Month); // 1-based
Assert.Equal(15, d.Day);
Assert.Equal(13, d.Hour);
Assert.Equal(45, d.Minute);
Assert.Equal(30, d.Second);
Assert.Equal(DayOfWeek.Friday, d.DayOfWeek);
Assert.Equal("Friday", d.DayOfWeek.ToString());
Assert.Equal(5, (int)d.DayOfWeek); // the number counts from Sunday = 0
Assert.False(IsWeekend(d)); // Friday is not a weekend…
Assert.True(IsWeekend(d.AddDays(2))); // …but the Sunday two days later is
// .Date truncates the time to midnight, same calendar day
Assert.Equal(0, d.Date.Hour);
Assert.Equal(15, d.Date.Day);
// the same readers widen to a DateOnly and a TimeOnly
Assert.Equal(3, DateOnly.New(2024, 3, 15).Month);
Assert.Equal(13, TimeOnly.New(13, 45, 30).Hour);
}See also#
- Date arithmetic — AddDays, AddMonths, AddYears, AddHours, AddMinutes, AddSeconds, AddMilliseconds — adding days/months/years, and its calendar clamping
- Current time (DateTime.UtcNow, DurableClock.Now) — reading the current instant to pull parts from
- DateTime — the
DateTimetype and how it is stored