Skip to main content

Quarter Operations

IValiDateQuarter provides comprehensive quarter-of-year operations. It is included in the Vali-Time package and registered automatically when you call AddValiTime() or AddValiTempo().

IValiDateQuarter API

QuarterOf

Return the quarter number (1–4) of the given date:

int q = quarter.QuarterOf(new DateTime(2025, 5, 15));
// → 2 (April–June)

int q2 = quarter.QuarterOf(new DateTime(2025, 11, 1));
// → 4 (October–December)

Signature: int QuarterOf(DateTime dt)

QuarterStart

Return the first day of the quarter that contains the given date:

DateTime start = quarter.QuarterStart(new DateTime(2025, 8, 20));
// → 2025-07-01 (Q3 starts July 1)

Signature: DateTime QuarterStart(DateTime dt)

QuarterEnd

Return the last day of the quarter that contains the given date:

DateTime end = quarter.QuarterEnd(new DateTime(2025, 8, 20));
// → 2025-09-30 (Q3 ends September 30)

Signature: DateTime QuarterEnd(DateTime dt)

QuarterName

Return the short name of the quarter ("Q1", "Q2", "Q3", or "Q4"):

string name = quarter.QuarterName(new DateTime(2025, 4, 1));
// → "Q2"

Signature: string QuarterName(DateTime dt)

QuarterNameFull

Return the full descriptive name including year:

string full = quarter.QuarterNameFull(new DateTime(2025, 4, 1));
// → "Q2 2025 (Apr – Jun)"

Signature: string QuarterNameFull(DateTime dt)

DaysInQuarter

Return the total number of days in the quarter containing the given date:

int days = quarter.DaysInQuarter(new DateTime(2024, 2, 1)); // Q1 of leap year
// → 91 (Jan 31 + Feb 29 + Mar 31)

int days2 = quarter.DaysInQuarter(new DateTime(2025, 4, 1)); // Q2
// → 91 (Apr 30 + May 31 + Jun 30)

Signature: int DaysInQuarter(DateTime dt)

DaysElapsedInQuarter

Return the number of days elapsed since the start of the quarter (1-based):

int elapsed = quarter.DaysElapsedInQuarter(new DateTime(2025, 4, 15));
// → 15 (April 15 is the 15th day of Q2)

Signature: int DaysElapsedInQuarter(DateTime dt)

DaysRemainingInQuarter

Return the number of days remaining until the end of the quarter (inclusive of the last day):

int remaining = quarter.DaysRemainingInQuarter(new DateTime(2025, 9, 28));
// → 3 (Sep 28, 29, 30 remaining)

Signature: int DaysRemainingInQuarter(DateTime dt)

ProgressInQuarter

Return a value between 0.0 and 1.0 representing how far through the quarter the date is:

decimal progress = quarter.ProgressInQuarter(new DateTime(2025, 7, 1));
// → 0.0 (first day of Q3)

decimal progress2 = quarter.ProgressInQuarter(new DateTime(2025, 9, 30));
// → ~1.0 (last day of Q3)

Signature: decimal ProgressInQuarter(DateTime dt)

IsFirstDayOfQuarter

Return true if the date is the first calendar day of its quarter:

bool first = quarter.IsFirstDayOfQuarter(new DateTime(2025, 10, 1));
// → true (Oct 1 starts Q4)

bool notFirst = quarter.IsFirstDayOfQuarter(new DateTime(2025, 10, 2));
// → false

Signature: bool IsFirstDayOfQuarter(DateTime dt)

IsLastDayOfQuarter

Return true if the date is the last calendar day of its quarter:

bool last = quarter.IsLastDayOfQuarter(new DateTime(2025, 6, 30));
// → true (Jun 30 ends Q2)

Signature: bool IsLastDayOfQuarter(DateTime dt)

IsInSameQuarter

Return true if two dates fall in the same quarter of the same year:

bool same = quarter.IsInSameQuarter(
new DateTime(2025, 4, 1),
new DateTime(2025, 6, 30));
// → true (both in Q2 2025)

bool notSame = quarter.IsInSameQuarter(
new DateTime(2025, 3, 31),
new DateTime(2025, 4, 1));
// → false (Q1 vs Q2)

Signature: bool IsInSameQuarter(DateTime a, DateTime b)

WeeksInQuarter

Return the number of ISO weeks that overlap with the quarter:

int weeks = quarter.WeeksInQuarter(new DateTime(2025, 1, 1));
// → ~13

Signature: int WeeksInQuarter(DateTime dt)

DayOfQuarter

Return the ordinal day position within the quarter (1-based):

int day = quarter.DayOfQuarter(new DateTime(2025, 4, 5));
// → 5 (5th day of Q2)

Signature: int DayOfQuarter(DateTime dt)

NextQuarterStart

Return the first day of the next quarter:

DateTime next = quarter.NextQuarterStart(new DateTime(2025, 8, 15));
// → 2025-10-01 (start of Q4)

DateTime next2 = quarter.NextQuarterStart(new DateTime(2025, 12, 31));
// → 2026-01-01 (start of Q1 next year)

Signature: DateTime NextQuarterStart(DateTime dt)

PreviousQuarterStart

Return the first day of the previous quarter:

DateTime prev = quarter.PreviousQuarterStart(new DateTime(2025, 8, 15));
// → 2025-04-01 (start of Q2)

DateTime prev2 = quarter.PreviousQuarterStart(new DateTime(2025, 1, 15));
// → 2024-10-01 (start of Q4 of previous year)

Returns DateTime.MinValue when no previous quarter exists (i.e. the date is in Q1 of year 1). Use TryPreviousQuarterStart to distinguish this sentinel from a real date.

Signature: DateTime PreviousQuarterStart(DateTime dt)

TryNextQuarterStart

Safe alternative to NextQuarterStart for use near DateTime.MaxValue. Returns false (and sets result to DateTime.MaxValue) when the next quarter would overflow past year 9999; otherwise returns true and the first day of the next quarter.

var valiDate = new ValiDate();

if (valiDate.TryNextQuarterStart(new DateTime(2025, 8, 15), out var next))
Console.WriteLine(next); // 2025-10-01

// Returns false near DateTime.MaxValue
bool ok = valiDate.TryNextQuarterStart(new DateTime(9999, 10, 1), out _); // false

Signature: bool TryNextQuarterStart(DateTime date, out DateTime result)

TryPreviousQuarterStart

Safe alternative to PreviousQuarterStart for use near DateTime.MinValue. Returns false (and sets result to DateTime.MinValue) when the date is in Q1 of year 1 and there is no previous quarter; otherwise returns true and the first day of the previous quarter.

var valiDate = new ValiDate();

if (valiDate.TryPreviousQuarterStart(new DateTime(2025, 5, 1), out var prev))
Console.WriteLine(prev); // 2025-01-01 00:00:00

// Returns false near DateTime.MinValue
bool ok = valiDate.TryPreviousQuarterStart(new DateTime(1, 2, 1), out _); // false

Signature: bool TryPreviousQuarterStart(DateTime date, out DateTime result)

Complete Example

public class QuarterlyReportService(IValiDateQuarter quarter)
{
public void PrintQuarterSummary(DateTime date)
{
int q = quarter.QuarterOf(date);
string name = quarter.QuarterNameFull(date);
DateTime qStart = quarter.QuarterStart(date);
DateTime qEnd = quarter.QuarterEnd(date);
int total = quarter.DaysInQuarter(date);
int elapsed = quarter.DaysElapsedInQuarter(date);
int remaining = quarter.DaysRemainingInQuarter(date);
decimal progress = quarter.ProgressInQuarter(date);

Console.WriteLine($"Quarter: {name}");
Console.WriteLine($"Span: {qStart:MMM dd}{qEnd:MMM dd}");
Console.WriteLine($"Total: {total} days");
Console.WriteLine($"Elapsed: {elapsed} days ({progress:P1})");
Console.WriteLine($"Left: {remaining} days");

DateTime next = quarter.NextQuarterStart(date);
Console.WriteLine($"Next Q starts: {next:yyyy-MM-dd}");
}
}