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

@adaskothebeast/http-params-processor-value-from-moment

v12.0.0

Published

Moment date and duration input strategies for HttpParamsProcessor value conversion.

Readme

⏱️ @adaskothebeast/http-params-processor-value-from-moment

Moment.js input strategies for HttpParamsProcessor: normalize Moment instants and moment.Duration objects before they are serialized.

npm license

Peer dependencies: core and moment (^2.30.1). ESM + CJS. sideEffects: false.


📦 Install

npm i @adaskothebeast/http-params-processor-value-from-moment @adaskothebeast/http-params-processor-core moment

moment-timezone is only needed if your code builds moments in named IANA zones (moment.tz(...)); the strategies themselves never touch zone data.


🎯 What it does

These are value-from strategies: the first half of the conversion pipeline. Each one normalizes a Moment type into a neutral shape and must be paired with a value-to strategy (-value-to-iso, -value-to-nodatime, -value-to-unix-timestamp, -value-to-ms-timestamp, -value-to-date-fns) through createValueConverter.

| Class | Accepts | Produces | | --------------------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | MomentDateValueFromStrategy | Moment (detected by moment.isMoment) | Date (value.toDate()) | | MomentDurationValueFromStrategy | moment.Duration (detected by moment.isDuration) | DurationComponents (years, months, days, hours, minutes, seconds, milliseconds) |

Detection is exact and mutually exclusive: a Moment is never claimed by the duration strategy and vice versa, so both converters can be registered side by side.


⚡ Usage

import { DefaultDateValueFromStrategy, ParamsProcessor, createValueConverter } from '@adaskothebeast/http-params-processor-core';
import { MomentDateValueFromStrategy, MomentDurationValueFromStrategy } from '@adaskothebeast/http-params-processor-value-from-moment';
import { IsoDateValueToStrategy, IsoDurationValueToStrategy } from '@adaskothebeast/http-params-processor-value-to-iso';
import moment from 'moment';

const processor = new ParamsProcessor({
  valueConverters: [
    createValueConverter(new MomentDateValueFromStrategy(), new IsoDateValueToStrategy()),
    createValueConverter(new MomentDurationValueFromStrategy(), new IsoDurationValueToStrategy()),
    // keep native Dates working too
    createValueConverter(new DefaultDateValueFromStrategy(), new IsoDateValueToStrategy()),
  ],
});

processor.process('p', {
  from: moment.utc('2024-01-15T10:30:00.000Z'),
  window: moment.duration({ hours: 1, minutes: 30, seconds: 45 }),
});
// [['p.from', '2024-01-15T10:30:00.000Z'], ['p.window', 'PT1H30M45S']]

🎛️ Options and configuration

Neither strategy takes constructor options - both are stateless and safe to share between processors.

Zones and UTC mode collapse into an instant. toDate() returns a native Date, so moment.utc(...), moment.parseZone(...) and moment.tz(..., 'Asia/Tokyo') all serialize to the same moment in time; the offset itself is not carried. The paired writer decides the rendering (-value-to-iso always emits UTC with Z).

Moment normalizes durations for you. Unlike Luxon and Day.js, moment.duration carries units on construction, so what you get out can differ from what you put in - see the table below.

Output format is decided by the paired value-to strategy:

import { MsTimestampValueToStrategy } from '@adaskothebeast/http-params-processor-value-to-ms-timestamp';

createValueConverter(new MomentDateValueFromStrategy(), new MsTimestampValueToStrategy());

📤 Output examples

Paired with -value-to-iso:

| Value passed to process | Normalized shape | Serialized | | ---------------------------------------------------- | ---------------------------------------- | -------------------------- | | moment.utc('2024-01-15T10:30:00.000Z') | Date (instant) | 2024-01-15T10:30:00.000Z | | moment.duration({ hours: 1, minutes: 30 }) | { hours: 1, minutes: 30 } | PT1H30M | | moment.duration({ minutes: 90 }) | { hours: 1, minutes: 30 } | PT1H30M | | moment.duration({ months: 18 }) | { years: 1, months: 6 } | P1Y6M | | moment.duration({ days: 45 }) | { months: 1, days: 14 } | P1M14D | | moment.duration({ weeks: 2 }) | { days: 14 } | P14D | | moment.duration({ seconds: 1, milliseconds: 500 }) | { seconds: 1, milliseconds: 500 } | PT1.5S | | moment.duration('PT1H30M45S') | { hours: 1, minutes: 30, seconds: 45 } | PT1H30M45S |

p.from    = 2024-01-15T10:30:00.000Z
p.window  = PT1H30M45S

⚠️ Edge cases

  • Moment carries units, so values change shape. { minutes: 90 } comes back as 1 hour 30 minutes, { months: 18 } as 1 year 6 months, and large day counts roll into months ({ days: 45 } becomes 1 month 14 days, using Moment's approximate 30.4-day month). Send asDays()/asSeconds() numbers instead if the backend needs the exact unit you authored.
  • Weeks are folded into days. Moment reports moment.duration({ weeks: 2 }).days() as 14, and the strategy does not map a weeks field at all, so you get P14D, never P2W.
  • Zero components are converted to undefined, so { hours: 1 } never emits 0 days or minutes, and moment.duration(0) normalizes to an empty object (PT0S with the ISO writer).
  • Invalid moments still pass canHandle. moment('nope') and moment.invalid() are Moment objects, so they are claimed and normalized to Invalid Date; IsoDateValueToStrategy then throws RangeError: Invalid time value (timestamp writers emit NaN). Guard with .isValid() before building your params object.
  • Fractional seconds are carried into the millisecond field ({ seconds: 1.5 } becomes { seconds: 1, milliseconds: 500 }), which the ISO writer renders as PT1.5S.
  • Negative durations keep their sign per component, which produces non-standard output such as PT-1H - normalize with .abs() and send the sign separately if that matters.
  • moment.Duration values are not instants; never pair MomentDurationValueFromStrategy with a date writer such as IsoDateValueToStrategy - the converter always runs the paired writer, it does not re-check the shape.
  • Moment is in maintenance mode upstream; for new code prefer -value-from-luxon or -value-from-dayjs. Both can be registered next to this package during a gradual migration.

🔗 Related packages

Full matrix and adapter recipes: main README.


📄 License

MIT © Adam Pluciński