Skip to content
native-dates

API / Classes

MonthDay class

A calendar month and day with no year, for birthdays, anniversaries, and annual holidays.

import { MonthDay } from 'native-dates'core 12.1 kB min+br

Creating a MonthDay

Create an instance month-first with monthDay() or day-first with dayMonth(). Instances are immutable, so every method returns a new value.

create.js
import { dayMonth, monthDay } from 'native-dates';

const birthday = monthDay(10, 17);
const fromIso = monthDay('10-17');
const european = dayMonth('17/10');

Read the month and day off any calendar date or moment through its monthDay property, or convert inside a chain with as('monthDay'):

import { date, datetime, today } from 'native-dates';

date('1990-10-17').monthDay.toString(); // '10-17'
datetime('2026-10-18T02:00:00Z', 'America/Los_Angeles').as('monthDay').toString(); // '10-17'
const currentMonthDay = today().monthDay;

Properties

Properties read the 1-indexed month and day of the month.

Property Type Description
text string Locale-formatted month and day, such as 'Oct 17'.
month, day number Calendar month from 1 through 12, and day of the month from 1 through 31.
MonthDay.presets object Named format presets read by format(), open to custom entries.

Placing in a year and stepping

Combine a recurring month and day with a year to get a concrete date, or step forward and backward to nearby occurrences.

in()

md.in(year): CalendarDate

Places this month and day in a calendar year and returns a CalendarDate. February 29 lands on February 28 in common years that have no leap day.

yearnumber | stringrequired

Whole calendar year such as 2027.

CalendarDate

The CalendarDate this month-day falls on in year.

const birthday = monthDay(10, 17);
const leapDay = monthDay(2, 29);

birthday.in(2027).toString(); // '2027-10-17'
leapDay.in(2027).toString(); // '2027-02-28'
leapDay.in(2028).toString(); // '2028-02-29'

next()

md.next(day?): CalendarDate

Returns the next occurrence strictly after a reference date, defaulting to today(). When the reference date already falls on this month and day, the method advances to the following year.

Calendar dates and moments also accept a month-day directly in d.next(md) and dt.next(md).

dayCalendarDateInputdefault today()

Starting date to count forward from.

CalendarDate

Upcoming CalendarDate strictly after day.

import { date, monthDay } from 'native-dates';

const birthday = monthDay(10, 17);

birthday.next('2026-05-01').toString(); // '2026-10-17'
birthday.next('2026-10-17').toString(); // '2027-10-17'
date('2026-11-16').next(birthday).toString(); // '2027-10-17'

previous()

md.previous(day?): CalendarDate

Returns the most recent occurrence strictly before a reference date, defaulting to today(). Calendar dates and moments also accept a month-day directly in previous().

dayCalendarDateInputdefault today()

Reference date to count backward from.

CalendarDate

Most recent CalendarDate strictly before day.

import { date, monthDay } from 'native-dates';

const birthday = monthDay(10, 17);

birthday.previous('2026-10-17').toString(); // '2025-10-17'
date('2026-11-16').previous(birthday).toString(); // '2026-10-17'

after()

md.after(day): CalendarDate

Returns the next occurrence strictly after a required reference date. Behaves like next() without defaulting to today.

dayCalendarDateInputrequired

Reference date to step forward past.

CalendarDate

First CalendarDate occurrence after day.

monthDay(2, 29).after('2026-03-01').toString(); // '2027-02-28'

before()

md.before(day): CalendarDate

Returns the most recent occurrence strictly before a required reference date. Behaves like previous() without defaulting to today.

monthDay(10, 17).before('2026-10-01').toString(); // '2025-10-17'

Matching and equality

Because a month-day repeats every year rather than sitting at one point on a timeline, ordering methods like isBefore() do not apply.

Choosing equals or fallsOn

Use fallsOn() to check whether a calendar date is that year’s observance, since February 29 lands on February 28 in common years. Reserve equals() for checking whether two values write the exact same month and day numbers.

fallsOn()

md.fallsOn(day): boolean

Returns true when the given date is this month-day’s occurrence in that date’s own year. In a common year, February 29 falls on February 28, whereas in a leap year it falls only on February 29.

dayCalendarDateInputrequired

Date string, CalendarDate, DateTime, fields object, or Date.

boolean

true when day is this month-day's date in that year.

const leapDay = monthDay(2, 29);

leapDay.fallsOn('2027-02-28'); // true
leapDay.fallsOn('2028-02-28'); // false
leapDay.fallsOn('2028-02-29'); // true

equals()

md.equals(other): boolean

Returns true when both values carry the exact same month and day numbers, extracting the month and day when given a full date or timestamp.

Ambiguous slash or dot strings like '05/10' throw a RangeError. Parse them with month-first or day-first factories before comparing.

otherMonthDayInputrequired

Another MonthDay, ISO '10-17' string, fields object, or date value.

boolean

true when both values have the same month and day.

const birthday = monthDay(10, 17);

birthday.equals('10-17'); // true
birthday.equals('1990-10-17'); // true
monthDay(2, 29).equals('2027-02-28'); // false

isToday()

md.isToday(zone?): boolean

Returns true when this month-day falls on today’s date in the given or configured time zone.

import { today } from 'native-dates';

today('UTC').monthDay.isToday('UTC'); // true

isTomorrow()

md.isTomorrow(zone?): boolean

Returns true when this month-day falls on tomorrow’s date in the given or configured time zone.

import { tomorrow } from 'native-dates';

tomorrow('UTC').monthDay.isTomorrow('UTC'); // true

isYesterday()

md.isYesterday(zone?): boolean

Returns true when this month-day falls on yesterday’s date in the given or configured time zone.

import { yesterday } from 'native-dates';

yesterday('UTC').monthDay.isYesterday('UTC'); // true

Formatting and conversion

format()

md.format(spec?, locale?): string

Formats the month and day in the locale’s own order, or with a built-in token pattern such as 'MMM Do'. Shared options objects ignore year, clock, and zone keys automatically.

Custom named presets can be added on MonthDay.presets, and non-Gregorian locales format Gregorian month names so annual dates stay stable. See Formatting for all preset and token options.

specFormatSpecdefault 'medium'

Preset name such as 'short' or 'long', Intl options object, or token pattern.

localeLocale

BCP 47 locale tag overriding the configured default for this call.

string

Formatted month-and-day string.

const oct17 = monthDay(10, 17);

oct17.format('short', 'en-US'); // '10/17'
oct17.format('short', 'en-GB'); // '17/10'
oct17.format('medium', 'en-US'); // 'Oct 17'
oct17.format('long', 'en-US'); // 'October 17'
oct17.format('MMM Do', 'en-US'); // 'Oct 17th'

as()

md.as('monthDay'): MonthDay

Returns this instance when 'monthDay' is requested in generic conversion chains, throwing a RangeError for other kinds.

toString()

md.toString(): string
md.toJSON(): string

Returns the two-digit ISO month-day string 'MM-DD', which round-trips month-first under both month-day factories. toJSON() returns the same string for JSON serialization.

string

ISO month-day string such as '10-17'.

monthDay(5, 6).toString(); // '05-06'
JSON.stringify({ birthday: monthDay(10, 17) }); // '{"birthday":"10-17"}'

toTemporal()

md.toTemporal(): Temporal.PlainMonthDay

Returns the underlying Temporal.PlainMonthDay instance.

valueOf()

md.valueOf(): never

Throws a RangeError so numeric operators never coerce a month-day to a number. Narrow unknown values with isMonthDay() or kindOf().

Edit this pageUpdated Nov 12, 2026