Get the Quarter of the Year from a Date in JavaScript

To get the quarter, compute Math.ceil(plainDate.month / 3) — 1 for Jan-Mar through 4 for Oct-Dec. Part of Date Arithmetic Without Mutations.

Why this scenario is tricky

The only sharp edge here is month indexing: Temporal.PlainDate.month is 1-based (1 = January), so Math.ceil(month / 3) gives the quarter directly. Do the same maths on a legacy Date and getMonth()'s 0-based value shifts every quarter by one.

Mind the month indexinggetMonth() is 0-based and shifts quartersMind the month indexingceil(getMonth()/3)off by oneceil(plainDate.month/3)1..4 correctTemporal months are 1-based, so the quarter formula works directly.

Minimal working solution

import { Temporal } from '@js-temporal/polyfill';
const q = Math.ceil(Temporal.PlainDate.from('2024-05-15').month / 3); // 2

Quarter from monthceil(month / 3) gives 1-4Quarter from monthPlainDateceil(month/3)quarter

Full production version

import { Temporal } from '@js-temporal/polyfill';
function quarterBounds(d: Temporal.PlainDate) {
  const q = Math.ceil(d.month / 3);
  const start = Temporal.PlainDate.from({ year: d.year, month: (q - 1) * 3 + 1, day: 1 });
  return { quarter: q, start, end: start.add({ months: 3 }) }; // half-open
}

Quarter boundsDerive the quarter's start and endQuarter boundsPlainDatequarterstart month[start,end)

Verification snippet

Quarter of the Year assertionsKey cases assert correctlyAssertions that prove the edge caseMayQ2JanuaryQ1DecemberQ4Q2 startApril 1

Common pitfalls

Quarter of the Year pitfallsCommon mistakes and their fixesWrongRightceil(getMonth()/3)0-based → off by oneceil(month/3) on Temporal1-based, correctinclusive endoverlaps next quarterhalf-open boundsclean periods

Frequently Asked Questions

How do I get the quarter of the year from a date?

Compute Math.ceil(plainDate.month / 3) on a Temporal.PlainDate. Because Temporal months are 1-based, this returns 1 for January-March up to 4 for October-December without any adjustment.

How do I get the start and end of a quarter?

Derive the quarter with Math.ceil(month / 3), build a PlainDate for day 1 of that quarter's first month ((q-1)*3+1), and add three months for the exclusive end. Query the half-open range [start, end) for the reporting period.