npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

options-expiration

v1.0.0

Published

US listed options expiration dates — monthly third-Friday, weekly, 0DTE, quarterly, end-of-month and VIX expiries, shifted correctly for exchange holidays (Good Friday, Juneteenth), plus early-close-aware time to expiry.

Readme

options-expiration

US listed options expiration dates: monthly third-Friday, weekly, daily (0DTE), quarterly, end-of-month and VIX expiries, all shifted for exchange holidays (Good Friday, Juneteenth, July 3, Christmas on a Friday). Also time to expiry in years to the actual settlement instant, accounting for 1 p.m. early closes and DST. Built on us-equity-market-calendar; checked against Cboe's published calendars.

npm install options-expiration

Why

"Third Friday" is the rule people remember and the one their code gets wrong. When the third Friday is a holiday the expiry moves to Thursday: Good Friday on 2022-04-14, Juneteenth on 2026-06-18. That Thursday shift moves the VIX expiry from Wednesday to Tuesday 30 days earlier. A Christmas-Eve weekly settles at 1 p.m., not 4 p.m., so a naive time-to-expiry overstates T by three hours. This package gets these cases right by computing from the NYSE calendar, without a hard-coded date table.

import {
  monthlyExpiration, weeklyExpirations, expirations, nextExpiration,
  vixExpiration, isQuadWitching, timeToExpiry, tradingDaysToExpiry,
} from "options-expiration";

monthlyExpiration(2026, 6);   // "2026-06-18" — Juneteenth Friday → Thursday
monthlyExpiration(2022, 4);   // "2022-04-14" — Good Friday → Thursday
vixExpiration(2026, 5);       // "2026-05-19" — a Tuesday, because June's SPX expiry is a Thursday
isQuadWitching("2026-06-18"); // true

weeklyExpirations("2026-12-14", "2027-01-10");
// ["2026-12-18", "2026-12-24", "2026-12-31", "2027-01-08"] — Christmas and New Year's on Fridays

expirations("end-of-month", "2024-03-01", "2024-03-31"); // ["2024-03-28"] — Good Friday ends Q1
nextExpiration("2026-06-18", "monthly");                     // "2026-06-18" — on or after
nextExpiration("2026-06-18", "monthly", { inclusive: false }); // "2026-07-17"

// PM-settled weekly on Christmas Eve settles at the 13:00 ET early close
timeToExpiry(new Date("2026-12-23T21:00:00Z"), "2026-12-24"); // 21h / 365d = 0.002397…
timeToExpiry(new Date(), "2026-12-18", { settlement: "AM" }); // to the 09:30 ET open
tradingDaysToExpiry("2026-07-02", "2026-07-06");              // 1 — Jul 3 holiday + weekend

API

Dates are "YYYY-MM-DD" strings or Date objects read by their UTC calendar day (new Date("2026-06-18"), not new Date(2026, 5, 18)). Results are "YYYY-MM-DD" strings. Every function throws RangeError for a malformed date, a month outside 1–12, an unknown schedule, or a year outside MIN_YEAR–MAX_YEAR (1971–2200, the calendar's range).

Single expiries

  • monthlyExpiration(year, month): the standard monthly expiration. This is the third Friday, or the trading day before it when that Friday is a holiday. Before February 2015, standard contracts technically expired on the Saturday after the third Friday. This function returns the last trading day, which is the date that matters for trading and pricing.
  • endOfMonthExpiration(year, month): the last trading day of the month.
  • vixExpiration(year, month): the Cboe rule for VX futures final settlement and VIX options expiration. Take the third Friday of the following month, or the trading day before it if that Friday is a holiday. Count back 30 days to get a Wednesday (a Tuesday if the Friday shifted). If that day is itself a holiday, use the trading day before it (2024-06-18, when Juneteenth fell on the Wednesday).

Schedules

Schedule is "monthly" | "weekly" | "daily" | "quarterly" | "end-of-month":

| schedule | rule | |---|---| | monthly | third Friday, holiday → preceding trading day | | weekly | every Friday, holiday → preceding trading day | | daily | every trading day (0DTE) | | quarterly | last trading day of Mar / Jun / Sep / Dec | | end-of-month | last trading day of each month |

  • expirations(schedule, from, to): every expiry in [from, to] (both ends inclusive), sorted.
  • weeklyExpirations(from, to): shorthand for expirations("weekly", from, to).
  • nextExpiration(date, schedule, { inclusive = true }): the first expiry on or after date. On an expiration day you get that day back, which is what a 0DTE trader wants. Pass { inclusive: false } for strictly after.
  • isExpiration(date, schedule): whether date is an expiry under schedule.
  • isQuadWitching(date): whether date is the monthly expiration in March, June, September or December.

These functions generate dates from rules. They don't record which products listed which expiries, or when they started. SPX dailies, for example, only covered every weekday from 2022, and single-stock weeklies vary by underlying. Check the exchange's product listings for that.

Time to expiry

  • settlementTime(expiry, { settlement = "PM" }) → the settlement instant as a Date.
    • "PM": the session close, 16:00 ET, or 13:00 ET on an early-close day.
    • "AM": the session open, 09:30 ET. AM-settled index options (standard SPX) stop trading the day before, and this is the opening print they settle on.
    • Throws RangeError if expiry is not a trading day.
  • timeToExpiry(now, expiry, { settlement = "PM" }) → years from the instant now to settlement, ACT/365 (elapsed milliseconds ÷ 365 days). DST is handled. Returns 0 once settled.
  • tradingDaysToExpiry(from, expiry) → the trading days in (from, expiry]: 0 on expiration day, 1 the day before. Throws RangeError if from is after expiry.

Correctness

  • Checked against Cboe's own published calendars:
    • Standard monthly and end-of-month/quarter dates: the 2022, 2024, 2025 and 2026 options expiration calendars.
    • VX final settlement dates: the 2025 and 2026 futures settlement calendars.
    • The test fixtures cite the calendar each date came from.
  • Holiday shifts tested:
    • Good Friday: 2022, 2025 and 2026, plus the end of Q1 2024.
    • Juneteenth: on a Friday in 2026, on a Wednesday in 2024 (the VIX exception), and observed on Friday in 2027.
    • July 4 on a Friday (2025) and its observed Friday, July 3 (2026).
    • Christmas and New Year's on Fridays (2026).
    • Thanksgiving week, where the Friday trades with a 1 p.m. close.
    • The 2025-01-09 Day of Mourning.
  • Holidays and early closes come from us-equity-market-calendar, which matches the NYSE from 1971 onward. An unscheduled closure (a day of mourning, a hurricane) moves an expiry only once the calendar knows about it, so keep that dependency current.
  • Exchange discretion: these are the standard rules. An exchange can set a different date for a specific contract by notice, and that notice takes precedence over this package.

Related

The NYSE trading calendar underneath is us-equity-market-calendar. Siblings: options-greeks · futures-calendar. Part of a markets toolkit: sifma-holidays · day-count · fx-value-date.

Author

Built by Moshe Malka — engineering leader in New York City. Studio work at Quentin.Code.

MIT © Moshe Malka