# Reading a date — Year, Month, Day, Hour, Minute, Second, DayOfWeek, DayOfYear, Date

> Read a component off a DateTime — its year, month, day, hour, minute, second — or its day of the week (a DayOfWeek, as in C#), its day of the year (1 January is 1), or truncate it to midnight with .Date. The same part-readers work on a DateOnly and a TimeOnly. All are pure and run in the browser.

<!-- id: function-date-parts · area: function · stability: stable · html: https://osysharp.com/reference/function/date-parts/ -->

## Summary        {#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](https://osysharp.com/reference/types/duration-and-parts/) `DateOnly` or `TimeOnly`.

## Signature      {#signature}
```osy syntax
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:00
```

## Description    {#description}
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:

```osy title="the ISO week an instant falls in, e.g. 2026-W36" syntax
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](https://osysharp.com/reference/function/execution-side/)). For the current instant to read them off, see [Current time (DateTime.UtcNow, DurableClock.Now)](https://osysharp.com/reference/function/current-time/).

### The whole instant as one number — `Date.Ticks`   {#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)](https://osysharp.com/reference/types/timespan/).

## Examples       {#examples}
```osy title="is a timestamp on a weekend?" test app=date-parts
bool IsWeekend(DateTime d) {
  return d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday;
}
```

```osy title="the exact answers, pinned" run app=date-parts
[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       {#see-also}
- [Date arithmetic — AddDays, AddMonths, AddYears, AddHours, AddMinutes, AddSeconds, AddMilliseconds](https://osysharp.com/reference/function/date-arithmetic/) — adding days/months/years, and its calendar clamping
- [Current time (DateTime.UtcNow, DurableClock.Now)](https://osysharp.com/reference/function/current-time/) — reading the current instant to pull parts from
- [DateTime](https://osysharp.com/reference/types/datetime/) — the `DateTime` type and how it is stored
