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

@neaps/tide-predictor

v0.8.0

Published

Tide predictor

Readme

@neaps/tide-predictor

A tide harmonic calculator written in TypeScript.

[!WARNING] Not for navigational use

Do not use calculations from this project for navigation, or depend on them in any situation where inaccuracies could result in harm to a person or property. Tide predictions are only as good as the harmonics data available, and these can be inconsistent and vary widely based on the accuracy of the source data and local conditions. The tide predictions do not factor events such as storm surge, wind waves, uplift, tsunamis, or sadly, climate change. 😢

Installation

npm install @neaps/tide-predictor

Usage

@neaps/tide-predictor requires that you provide your own tidal harmonics information to generate a prediction. For a complete tide prediction solution, including finding nearby stations and their harmonics, check out the neaps package.

import { createTidePredictor } from "@neaps/tide-predictor";

const constituents = [
  {
    phase: 98.7,
    amplitude: 2.687,
    name: "M2",
    speed: 28.984104,
  },
  //....there are usually many, read the docs
];

const highLowTides = createTidePredictor(constituents).getExtremesPrediction({
  start: new Date("2019-01-01"),
  end: new Date("2019-01-10"),
});

Note that all times internally are evaluated as UTC, so be sure to specify a timezone offset when constructing dates if you want to work in a local time. For example, to get tides for January 1st, 2019 in New York (UTC-5), create a date new Date('2019-01-01T00:00:00-05:00')

Tide prediction object

Calling createTidePredictor will generate a new tide prediction object. It accepts the following arguments:

  • constituents - An array of constituent objects
  • options - An object with one of:
    • offset - A value to add to all values predicted. This is useful if you want to, for example, offset tides by mean high water, etc.

Tide prediction methods

The returned tide prediction object has various methods. All of these return regular JavaScript objects.

High and low tide - getExtremesPrediction

Returns the predicted high and low tides between a start and end date.

const startDate = new Date();
const endDate = new Date(startDate.getTime() + 3 * 24 * 60 * 60 * 1000);
const tides = createTidePredictor(constituents).getExtremesPrediction({
  start: startDate,
  end: endDate,
  labels: {
    //optional human-readable labels
    high: "High tide",
    low: "Low tide",
  },
});

If you want predictions for a subordinate station, use the reference station's constituents and pass the subordinate station offsets to the getExtremesPrediction method:

const tides = createTidePredictor(constituents).getExtremesPrediction({
  start: startDate,
  end: endDate,
  offsets: {
    height: {
      high: 1.1,
      low: 0.9,
      type: "ratio", // or "fixed" for additive offsets
    },
    time: {
      high: 15, // minutes
      low: 20,
    },
  },
});
Options

The getExtremesPrediction accepts a single object with options:

  • start - **Required ** - The date & time to start looking for high and low tides
  • end - **Required ** - The date & time to stop looking for high and low tides
  • labels - An object to define the human-readable labels for the tides
    • high - The human-readable label for high tides
    • low - The human-readable label for low tides
  • offsets - The offset values if these predictions are for a subordinate station
Return values

High and low tides are returned as arrays of objects:

  • time - A Javascript Date object of the time
  • level - The water level
  • high - true if this is a high tide, false if not
  • low - true if this is a low tide, false if not
  • label - The human-readable label (by default, 'High' or 'Low')

Timeline - getTimelinePrediction

Returns water level predictions at regular intervals between a start and end date.

const timeline = createTidePredictor(constituents).getTimelinePrediction({
  start: new Date("2019-01-01"),
  end: new Date("2019-01-02"),
  timeFidelity: 600, // seconds between points (default: 600 = 10 minutes)
});
Options
  • start - Required - The start date & time
  • end - Required - The end date & time
  • timeFidelity - Seconds between data points (default: 600)
  • offsets - The offset values if these predictions are for a subordinate station
Return values

An array of objects:

  • time - A JavaScript Date object
  • level - The predicted water level
  • hour - Hours since the requested start time (number)

Water level at time - getWaterLevelAtTime

Gives you the predicted water level at a specific time.

const waterLevel = createTidePredictor(constituents).getWaterLevelAtTime({
  time: new Date(),
});
Options

The getWaterLevelAtTime accepts a single object of options:

  • time - A Javascript date object of the time for the prediction
Return values

A single object is returned with:

  • time - A Javascript date object
  • level - The predicted water level

Data definitions

Constituent definition

Tidal constituents should be an array of objects with at least:

  • name - string - The NOAA constituent name, all upper-case.
  • amplitude - float - The constituent amplitude
  • phase - float - The phase of the constituent.
[
  {
    "name": "[constituent name]",
    "amplitude": 1.3,
    "phase": 1.33
  },
  {
    "name": "[constituent name 2]",
    "amplitude": 1.3,
    "phase": 1.33
  }
]

Subordinate station definitions

Some stations do not have defined harmonic data, but do have published offsets and a reference station. These include the offsets in time or amplitude of the high and low tides. Subordinate station offset objects include:

  • height - object - Height offsets
    • high - number - Adjustment for high tide
    • low - number - Adjustment for low tide
    • type - string - "ratio" (multiplicative, default) or "fixed" (additive)
  • time - object - Time offsets in minutes
    • high - number - Minutes to add to high tide times (can be negative)
    • low - number - Minutes to add to low tide times (can be negative)
{
  height: {
    high: 1.1,
    low: 0.9,
    type: "ratio",
  },
  time: {
    high: 15,
    low: 20,
  },
}

Architecture Internals

Detailed notes on the internal constituent and node correction systems. For high-level project context, see CONTRIBUTING.md.

Tidal Constituent System

Constituents are loaded from src/constituents/data.json, which contains 395 entries derived from the IHO TWCWG Constituent List.

Each entry has:

  • name — canonical name (e.g. "M2")
  • speed — tidal frequency in degrees/hour
  • xdo — 7-digit IHO Extended Doodson Number (array of ints, or null for compound constituents)
  • nodalCorrection — IHO letter code dispatching how f/u are computed
  • aliases — alternate names (Unicode Greek variants, NOAA conventions)
  • members — optional explicit compound member references (array of [name, factor] pairs)

How constituents are built

src/constituents/index.ts imports data.json and calls defineConstituent() from definition.ts for each entry. This:

  1. Converts XDO digits to Doodson coefficients via xdoToCoefficients()
  2. Resolves compound members from the IHO letter code via resolveMembers()
  3. Attaches a value() function that computes V₀ (astronomical argument)
  4. Attaches a correction() function that computes nodal corrections (f, u)
  5. Registers the constituent under its canonical name and all aliases

XDO to Doodson conversion

xdoToCoefficients() in definition.ts:

  • D₁ (τ coefficient) is used directly (not offset)
  • D₂–D₆ are offset by −5 (IHO encodes 0 as 5)
  • D₇ (90° phase) is negated (5 - xdo[6]) to convert from IHO to the Schureman/NOAA sign convention
  • V₀ is computed as the dot product of coefficients with astronomical arguments [τ, s, h, p, −N, p', 90°]

Node corrections

Both the IHO and Schureman systems compute the same two values per constituent (f amplitude factor, u phase correction in degrees) but use different math:

Nodal correction dispatch

The IHO letter codes from data.json are resolved at constituent definition time in resolveMembers() within definition.ts. Each code maps to structural member constituents (e.g., code m → M2, code x → compound decomposition). At prediction time, constituent.correction() recursively computes f/u from these members.

Compound constituent decomposition

src/constituents/compound.ts implements the IHO Annex B algorithm: parses compound names like "MS4" into component letters, resolves signs using a progressive right-to-left algorithm, and maps each to its fundamental constituent.

Shout out

  • @kevee for his work on the original version of this project.
  • Xtide
  • pytides.