Zmplr.Chronometry 2026.0.0

dotnet add package Zmplr.Chronometry --version 2026.0.0
                    
NuGet\Install-Package Zmplr.Chronometry -Version 2026.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Zmplr.Chronometry" Version="2026.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Zmplr.Chronometry" Version="2026.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Zmplr.Chronometry" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Zmplr.Chronometry --version 2026.0.0
                    
#r "nuget: Zmplr.Chronometry, 2026.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Zmplr.Chronometry@2026.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Zmplr.Chronometry&version=2026.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Zmplr.Chronometry&version=2026.0.0
                    
Install as a Cake Tool

Zmplr.Chronometry

Zmplr.Chronometry is a small .NET library of DateTime helpers, inclusive date intervals, calendar slicing, and Christian movable-feast dates. Use it when you need weekday navigation, period boundaries (week / month / quarter / season), day enumeration between two dates, or interval set operations without pulling in a heavy calendar framework.

It is deliberately focused on calendar dates (day granularity). It is not a time-zone database, NodaTime replacement, or business-holiday calendar for every country.


What it does

  • Date navigation — next/previous Monday–Sunday (nth occurrence), first/last day of week/month/year
  • Period boundaries — calendar quarter, half-year, and season as Interval values
  • Inclusive ranges — enumerate days, weekdays, weekends, months, and years between two dates
  • Duration counts — days/weeks/months/quarters/years left or until a date; hour spans with DST-aware UTC conversion
  • Intervals — contain, intersect, except, and slice a range into calendar units
  • Movable feasts — Easter and related Western Christian dates for a given year
  • EU daylight-saving markers — last Sunday of March / October helpers

Mental model

Concept Meaning
DateTime extensions Operate on a single instant/date; many methods use .Date semantics (calendar day)
Interval Inclusive [Start, Stop] range of calendar days
CalendarUnit Unit used when slicing an interval (day, week, month, …)
Week Monday–Sunday (ISO-style week start)

Requirements

Multi-targets:

TFM Supported
net8.0 Yes
net48 Yes
netstandard2.0 Yes
netstandard2.1 Yes

No extra runtime packages are required.


Install

dotnet add package Zmplr.Chronometry
using Zmplr.Chronometry;

Quick start

using Zmplr.Chronometry;

var today = new DateTime(2026, 8, 9); // Sunday

// Week boundaries (Monday–Sunday)
var weekStart = today.FirstDayOfWeek();  // 2026-08-03
var weekEnd   = today.LastDayOfWeek();   // 2026-08-09

// Next / previous weekday
var nextMonday = today.NextMonday();     // 2026-08-10
var prevFriday = today.PrevFriday(2);    // second Friday before today

// Period containing a date
Interval q3 = today.Quarter();           // 2026-07-01 .. 2026-09-30
int q       = today.QuarterOrdinal();    // 3

// Inclusive day walk and weekday filter
var days = new DateTime(2026, 2, 15).WeekDaysUntil(new DateTime(2026, 2, 28));
// 10 weekdays

// Slice a multi-year span into decades
var span = new Interval(new DateTime(1968, 10, 4), new DateTime(2018, 10, 4));
Interval[] decades = span.Slice(CalendarUnit.Decade).ToArray();

// Easter family for a year
DateTime easter = HolidayExtensions.EasterSunday(2026);
DateTime goodFriday = HolidayExtensions.GoodFriday(2026);

DateTime extensions

All methods are in DateTimeExtensions under Zmplr.Chronometry.

Week, month, and year boundaries

Method Returns
FirstDayOfWeek() / LastDayOfWeek() Monday / Sunday of the containing week
FirstDayOfMonth() / LastDayOfMonth() 1st / last calendar day of the month (leap-year aware for February)
FirstDayOfYear() 1 January of self.Year
FirstDayOfQuarter() / FirstDayOfHalfYear() / FirstDayOfSeason() Start of the period containing self
new DateTime(2019, 3, 5).FirstDayOfWeek(); // 2019-03-04 (Monday)
new DateTime(2019, 3, 5).LastDayOfWeek();  // 2019-03-10 (Sunday)
new DateTime(2000, 2, 15).LastDayOfMonth(); // 2000-02-29

Quarters, half-years, and seasons

Method Meaning
QuarterOrdinal() 14 for calendar quarters
Quarter() Interval for Q1–Q4 of the year
HalfYear() Jan–Jun or Jul–Dec as an Interval
Season() Summer Apr 1 – Sep 30, winter Oct 1 – Mar 31 (winter may cross the year boundary)
var d = new DateTime(2026, 11, 15);
d.Quarter();   // 2026-10-01 .. 2026-12-31
d.HalfYear();  // 2026-07-01 .. 2026-12-31
d.Season();    // 2026-10-01 .. 2027-03-31

Next and previous weekdays

NextMondayNextSunday and PrevMondayPrevSunday take an optional count (default 1) for the nth occurrence strictly after or strictly before self. count must be > 0.

var today = new DateTime(2016, 10, 4); // Tuesday
today.NextMonday();    // 2016-10-10
today.NextTuesday(2);  // 2016-10-18
today.PrevFriday();    // 2016-09-30

Enumerate and count until a date

Ranges are inclusive of both endpoints unless noted.

Method Result
DaysUntil(to) Every calendar day from from through to
WeekDaysUntil(to) Monday–Friday only
WeekendDaysUntil(to) Saturday–Sunday only
MonthsUntil(to) First of each month from from’s month through to’s month
YearsUntil(to) 1 January for each year from from.Year through to.Year
NumberOfDaysUntil(to) Inclusive day count ((to.Date - from.Date).Days + 1)
NumberOfWeeksUntil(to) Whole weeks spanning Monday–Sunday alignment of the range
NumberOfMonthsUntil(to) Count of months from MonthsUntil
NumberOfQuartersUntil / NumberOfHalfYearsUntil / NumberOfSeasonsUntil / NumberOfYearsUntil Period counts over the span
NumberOfDaysLeftInMonth() / NumberOfDaysLeftInYear() Remaining days after from in that month/year
HoursUntil(to) Hours from start of from’s date through end of to’s date, via UTC (accounts for DST transitions when DateTime conversion does)
var from = new DateTime(2010, 2, 15);
var to   = new DateTime(2010, 2, 28);

from.NumberOfDaysLeftInMonth();           // 13
from.WeekDaysUntil(to).Count();           // 10
from.HoursUntil(new DateTime(2003, 3, 31)); // 743 in a European spring-forward month

Daylight saving (EU-style)

Method Meaning
IsDayLightSavingBegin(day) true if day is the last Sunday of March in that year
IsDayLightSavingEnd(day) true if day is the last Sunday of October in that year

These match common EU transition dates, not arbitrary IANA zones. Use a proper time-zone library when you need zone rules.

Misc

Method / field Meaning
IsLeapYear() Gregorian leap-year test for self.Year
IsSameMonth(other) Same year and month
NumberOfDaysInMonth Static lookup array (index 112; February is 28 — use LastDayOfMonth for leap years)

Interval

Interval is an inclusive calendar-day range with Start, Stop, and TimeSpan (Stop - Start).

var interval = new Interval(new DateTime(2026, 1, 1), new DateTime(2026, 1, 31));
interval.Contains(new DateTime(2026, 1, 15)); // true
interval.TimeSpan; // 30 days in ticks

Containment and set operations

Method Behaviour
Contains(DateTime) Start <= day <= Stop
Contains(from, to, day) Static helper over a temporary interval
HasIntersectionWith(other) Whether Intersect is non-null
Intersect(other) Inclusive overlapping day range, or null
Except(other) Remaining day runs after removing other’s days (may yield multiple intervals)
IsEnclosedBy(other) Overlap check against other (shared days)
var a = new Interval(new DateTime(2026, 1, 1), new DateTime(2026, 1, 20));
var b = new Interval(new DateTime(2026, 1, 10), new DateTime(2026, 1, 31));

Interval overlap = a.Intersect(b);
// Start = 2026-01-10, Stop = 2026-01-20

Slice by calendar unit

IEnumerable<Interval> Slice(CalendarUnit calendarUnit);
static IEnumerable<Interval> Slice(DateTime from, DateTime to, CalendarUnit calendarUnit);

Splits the interval into sub-intervals of the given unit. The first and last pieces may be partial (e.g. a week that does not start on Monday).

Supported by Slice:

CalendarUnit Grouping
Day One interval per day
Week Monday-aligned weeks where possible
Month Calendar months
Quarter Calendar quarters
Year Calendar years
Decade Ten-year bands (year / 10)
Century Hundred-year bands
Millenium Thousand-year bands
Aeon Single interval covering the whole span

HalfYear and Season exist on the enum for use with DateTime helpers (HalfYear(), Season()); they are not implemented in Interval.Slice.

var from = new DateTime(1968, 10, 4);
var to   = new DateTime(2018, 10, 4);
var decades = new Interval(from, to).Slice(CalendarUnit.Decade).ToArray();
// 6 decade slices across the span

Weekdays inside an interval

interval.Mondays();
interval.Tuesdays();
// ...
interval.Sundays();
interval.FilterOnDayOfWeek(DayOfWeek.Wednesday);

Returns ordered DateTime[] of matching calendar days in [Start, Stop].


Holidays (movable feasts)

HolidayExtensions computes Western Christian movable dates from Easter for a given year (Computus). These are not a full public-holiday calendar (no fixed national holidays, no Orthodox Easter).

Method Relative to Easter Sunday
EasterSunday(year)
PalmSunday(year) −7 days
MaundyThursday(year) −3 days
GoodFriday(year) −2 days
EasterMonday(year) +1 day
AscensionDay(year) Whit Sunday − 10 days
WhitSunday(year) +7 weeks
WhitMonday(year) Whit Sunday + 1 day
AshWednesday(year) −47 days
FirstSundayOfAdvent(year) Four Sundays before Christmas (25 Dec)
int year = 2026;
var easter = HolidayExtensions.EasterSunday(year);
var advent = HolidayExtensions.FirstSundayOfAdvent(year);

Design notes and caveats

  1. Calendar days, not instants — Most helpers ignore time-of-day or normalize to dates. Prefer DateTime.Date inputs when mixing with timestamps.
  2. Inclusive intervalsInterval and *Until enumerations include both ends.
  3. Monday-based weeks — Consistent with ISO week start; differs from CultureInfo calendars that start on Sunday.
  4. HoursUntil and DST — Converts date bounds to UTC so spring-forward / fall-back days can yield 23 or 25 hours. Behaviour depends on the local system’s time-zone conversion rules.
  5. No IANA / NodaTime — For zone-safe scheduling across regions, compose this library with TimeZoneInfo or NodaTime; do not treat EU DST helpers as global truth.
  6. Holiday scope — Easter-derived dates only; build country-specific holiday sets yourself on top if needed.
  7. CalendarUnit.HalfYear / Season in Slice — Use DateTime.HalfYear() / Season() (or custom grouping); Slice does not expand those units today.

Package contents

Type Role
DateTimeExtensions Navigation, periods, enumeration, counts, DST markers
Interval Inclusive range, set ops, slicing, weekday filters
CalendarUnit Units for Interval.Slice
HolidayExtensions Easter and related movable feasts

Source: github.com/mtanneryd/zmplr.chronometry


Versioning

Package versions are produced with GitVersion (same scheme as other Zmplr libraries):

Branch Example
master / main 2026.1.0
develop 2026.1.0-beta.20260809.43371
feature/* 2026.1.0-alpha.…
release/* 2026.1.0-rc.N

License

Licensed under the Apache License, Version 2.0.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.8

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.0.0 82 8/9/2026