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

@alexstukovnikov/oz-time

v1.0.3

Published

Lightweight JavaScript date-time library

Readme

OzTime

JavaScript-библиотека для работы с датой и временем.

OzTime предоставляет неизменяемые объекты времени, фабричные функции создания экземпляров, арифметику по фиксированным и календарным единицам, сравнение, форматирование, работу с часовыми поясами, интервалы и длительности.

Содержание

Почему OzTime

OzTime подойдёт, если нужна небольшая и понятная библиотека без перегруженного API.

Основные идеи:

  • время хранится как Unix timestamp в миллисекундах;
  • экземпляры OzTime неизменяемы;
  • часовой пояс и локаль сохраняются как часть объекта;
  • арифметика, сравнение и форматирование работают через единый API.

Библиотека хорошо подходит для:

  • прикладных JavaScript-проектов;
  • учебных и дипломных проектов;
  • небольших библиотек и утилит;
  • кода, где важна предсказуемость и неизменяемость.

Возможности

  • Неизменяемые экземпляры OzTime
  • Фабричные функции: now, fromTimestamp, fromDate, fromISO, fromComponents
  • Арифметика по времени: add, subtract
  • Сравнение: isSame, isBefore, isAfter, isBetween
  • Форматирование по шаблону
  • Работа с часовыми поясами: setTimezone, getTimezoneOffset
  • Интервалы: Interval, interval
  • Длительности: Duration, duration
  • Календарные утилиты: isLeapYear, daysInMonth

Установка

npm install @alexstukovnikov/oz-time

Быстрый старт

import { now, fromISO, duration, interval } from '@alexstukovnikov/oz-time';

const current = now('Europe/Moscow', 'ru-RU');
const release = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');

const nextWeek = release.add(7, 'day');
const diffHours = nextWeek.diff(release, 'hour');

console.log(current.getTimezone()); // ожидаемый результат: Europe/Moscow
console.log(nextWeek.format('DD.MM.YYYY HH:mm')); // ожидаемый результат: 01.06.2024 12:00
console.log(diffHours); // ожидаемый результат: 168

const range = interval(release, nextWeek);
console.log(range.contains(release)); // ожидаемый результат: true

const oneHour = duration(1, 'hour');
console.log(oneHour.asMinutes()); // ожидаемый результат: 60

Цепочка операций

import { fromISO } from '@alexstukovnikov/oz-time';

const result = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU')
    .add(1, 'day')
    .add(2, 'hour')
    .subtract(30, 'minute')
    .setTimezone('Europe/Moscow')
    .format('DD.MM.YYYY HH:mm:ss');

console.log(result);

Основные сценарии

| Сценарий | Что использовать | Почему | | ----------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------- | | Нужен текущий момент времени | now() | Самый простой способ получить новый экземпляр OzTime для текущего момента | | Есть Unix timestamp в миллисекундах | fromTimestamp() | Подходит для работы с временем из API, БД и системных источников | | Есть нативный Date | fromDate() | Удобно интегрировать библиотеку в существующий JavaScript-код | | Есть ISO-строка | fromISO() | Подходит для внешних API и сериализованных значений времени | | Нужно создать дату вручную из компонентов | fromComponents() | Удобно, когда год, месяц, день и время приходят по отдельности | | Нужно прибавить или вычесть время | add() / subtract() | Возвращают новый экземпляр и не изменяют исходный объект | | Нужно сравнить два значения | isSame() / isBefore() / isAfter() | Дают читаемый API для логики сравнения | | Нужно проверить попадание в диапазон | isBetween() | Удобнее, чем писать проверку вручную | | Нужно получить строковое представление | format() | Форматирование по шаблону с токенами | | Нужно изменить отображаемый часовой пояс | setTimezone() | Меняет timezone у нового экземпляра, не меняя абсолютный момент времени | | Нужно узнать смещение относительно UTC | getTimezoneOffset() | Полезно для отображения, отладки и расчётов | | Нужно описать диапазон времени | Interval / interval() | Подходит для проверки попадания, пересечений и длительности интервала | | Нужно описать фиксированную длительность | Duration / duration() | Удобно для преобразования между миллисекундами, секундами, минутами, часами и днями | | Нужно проверить високосный год | isLeapYear() | Простая календарная утилита | | Нужно узнать число дней в месяце | daysInMonth() | Удобно для валидации и генерации дат |

Создание экземпляров

import { now, fromTimestamp, fromDate, fromISO, fromComponents } from '@alexstukovnikov/oz-time';

const a = now('Europe/Moscow', 'ru-RU');
const b = fromTimestamp(1716638400000, 'UTC', 'ru-RU');
const c = fromDate(new Date('2024-05-25T12:00:00Z'), 'UTC', 'ru-RU');
const d = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
const e = fromComponents(2024, 5, 25, 12, 0, 0, 0, 'UTC', 'ru-RU');
  • now() — создаёт экземпляр OzTime для текущего момента времени.
  • fromTimestamp() — создаёт экземпляр из Unix timestamp в миллисекундах.
  • fromDate() — создаёт экземпляр из объекта Date.
  • fromISO() — создаёт экземпляр из ISO-строки.
  • fromComponents() — создаёт экземпляр из отдельных компонентов даты и времени.

Арифметика

Все арифметические операции возвращают новый экземпляр OzTime и не изменяют исходный объект.

Добавление и вычитание

import { fromISO } from '@alexstukovnikov/oz-time';

const time = fromISO('2024-05-25T12:00:00Z');

console.log(time.add(1, 'day').toISOString()); // ожидаемый результат: 2024-05-26T12:00:00.000Z
console.log(time.subtract(2, 'hour').toISOString()); // ожидаемый результат: 2024-05-25T10:00:00.000Z

Разница между датами

import { fromISO } from '@alexstukovnikov/oz-time';

const start = fromISO('2024-05-25T12:00:00Z');
const end = fromISO('2024-05-25T15:00:00Z');

console.log(end.diff(start, 'hour')); // ожидаемый результат: 3

Календарная арифметика

import { fromISO } from '@alexstukovnikov/oz-time';

const date = fromISO('2024-01-31T00:00:00Z');
const result = date.add(1, 'month');

console.log(result.toISOString()); // ожидаемый результат: 2024-02-29T00:00:00.000Z

Сравнение

import { fromISO } from '@alexstukovnikov/oz-time';

const a = fromISO('2024-05-25T12:00:00.100Z');
const b = fromISO('2024-05-25T12:00:00.900Z');
const c = fromISO('2024-05-26T12:00:00Z');

console.log(a.isSame(b, 'second')); // ожидаемый результат: true
console.log(a.isBefore(c)); // ожидаемый результат: true
console.log(c.isAfter(a)); // ожидаемый результат: true
console.log(a.isBetween(a.subtract(1, 'day'), c)); // ожидаемый результат: true

Форматирование

Функция format() и метод OzTime#format() поддерживают шаблоны форматирования.

import { fromISO } from '@alexstukovnikov/oz-time';

const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');

console.log(time.format('DD.MM.YYYY HH:mm')); // ожидаемый результат: 25.05.2024 12:00
console.log(time.format('dddd, D MMMM YYYY', 'ru-RU')); // пример: суббота, 25 мая 2024

Часовые пояса

OzTime хранит абсолютное время как timestamp, а часовой пояс используется как метаданные для отображения и форматирования.

Смена часового пояса

import { fromISO } from '@alexstukovnikov/oz-time';

const time = fromISO('2024-05-25T12:00:00Z', 'UTC', 'ru-RU');
const moscow = time.setTimezone('Europe/Moscow');

console.log(moscow.getTimezone()); // ожидаемый результат: Europe/Moscow

Смещение относительно UTC

import { fromISO } from '@alexstukovnikov/oz-time';

const time = fromISO('2024-05-25T12:00:00Z', 'Europe/Moscow', 'ru-RU');
console.log(time.getTimezoneOffset()); // ожидаемый результат: 180

Интервалы и длительности

Интервалы

Интервал представляет диапазон между двумя экземплярами OzTime, включая границы.

import { interval, fromISO } from '@alexstukovnikov/oz-time';

const start = fromISO('2024-05-25T10:00:00Z');
const end = fromISO('2024-05-25T12:00:00Z');
const range = interval(start, end);

console.log(range.contains(fromISO('2024-05-25T11:00:00Z'))); // ожидаемый результат: true
console.log(range.duration('hour')); // ожидаемый результат: 2

Пересечение интервалов

import { Interval, fromISO } from '@alexstukovnikov/oz-time';

const a = new Interval(fromISO('2024-05-25T10:00:00Z'), fromISO('2024-05-25T12:00:00Z'));

const b = new Interval(fromISO('2024-05-25T11:00:00Z'), fromISO('2024-05-25T13:00:00Z'));

console.log(a.overlaps(b)); // ожидаемый результат: true

Длительности

Duration используется для работы с фиксированными единицами времени.

import { duration } from '@alexstukovnikov/oz-time';

const twoHours = duration(2, 'hour');

console.log(twoHours.asMilliseconds()); // ожидаемый результат: 7200000
console.log(twoHours.asMinutes()); // ожидаемый результат: 120
console.log(twoHours.asHours()); // ожидаемый результат: 2

Сложение длительностей

import { duration } from '@alexstukovnikov/oz-time';

const a = duration(30, 'minute');
const b = duration(45, 'minute');

console.log(a.add(b).asMinutes()); // ожидаемый результат: 75

Поддерживаемые единицы времени

Поддерживаются канонические имена и алиасы.

| Единица | Каноническое имя | Алиасы | | ------------ | ---------------- | -------------------- | | Миллисекунда | millisecond | milliseconds, ms | | Секунда | second | seconds, s | | Минута | minute | minutes, m | | Час | hour | hours, h | | День | day | days, d | | Месяц | month | months | | Год | year | years, y |

Фиксированные единицы:

  • millisecond
  • second
  • minute
  • hour
  • day

Календарные единицы:

  • month
  • year

Токены форматирования

| Токен | Описание | Пример | | ------ | ---------------------------------- | ------------- | | YYYY | Год из 4 цифр | 2024 | | YY | Короткий год | 24 | | MMMM | Полное название месяца | май / May | | MMM | Короткое название месяца | мая / May | | MM | Месяц с ведущим нулём | 05 | | M | Месяц без ведущего нуля | 5 | | dddd | Полное название дня недели | суббота | | ddd | Короткое название дня недели | сб | | DD | День месяца с ведущим нулём | 25 | | D | День месяца без ведущего нуля | 25 | | HH | Часы в 24-часовом формате | 09, 18 | | H | Часы в 24-часовом формате без нуля | 9, 18 | | hh | Часы в 12-часовом формате | 01, 12 | | h | Часы в 12-часовом формате без нуля | 1, 12 | | mm | Минуты | 07 | | ss | Секунды | 05 | | SSS | Миллисекунды | 123 | | A | AM/PM | AM, PM |

FAQ

Чем fromISO() отличается от fromTimestamp()?

fromISO() принимает строку в формате ISO 8601 и сначала парсит её, а fromTimestamp() принимает уже готовое число миллисекунд. Если данные приходят из JSON API как строка, чаще удобнее fromISO(). Если уже есть timestamp из базы, системы или вычислений, лучше использовать fromTimestamp().

Меняет ли setTimezone() сам момент времени?

Нет. setTimezone() не меняет абсолютный момент времени. Он возвращает новый экземпляр с тем же timestamp, но с другим часовым поясом для форматирования и вычисления смещения.

Изменяют ли методы add() и subtract() текущий объект?

Нет. OzTime построен как неизменяемый объект. Все операции возвращают новый экземпляр, а исходный объект остаётся без изменений.

Почему Duration не поддерживает month и year?

Потому что Duration предназначен только для фиксированных единиц времени, которые можно точно перевести в миллисекунды. Месяцы и годы имеют переменную длину, поэтому для них используется календарная арифметика через OzTime#add() и OzTime#diff().

Почему diff(..., 'month') и diff(..., 'year') работают не так, как разница в миллисекундах?

Потому что для месяцев и лет применяется календарная логика, а не деление на фиксированное число миллисекунд. Это позволяет корректнее учитывать разную длину месяцев и переходы между датами.

Что лучше использовать: метод экземпляра или функцию модуля?

Если уже есть экземпляр OzTime, обычно удобнее использовать методы экземпляра: time.add(...), time.format(...), time.isBefore(...). Если нужен функциональный стиль или работаешь с импортированными утилитами напрямую, можно использовать функции модулей.

В каком часовом поясе хранится время внутри OzTime?

Внутри хранится Unix timestamp в миллисекундах. Это абсолютное значение времени. Часовой пояс хранится отдельно как метаданные экземпляра.

Можно ли использовать библиотеку без locale и timezone?

Да. По умолчанию используются:

  • timezone = 'UTC'
  • locale = 'en-US'

Когда использовать Interval, а когда Duration?

Используй Interval, когда есть начало и конец диапазона. Используй Duration, когда нужна именно фиксированная длина времени, например 2 часа, 30 минут или 7 дней.

Ограничения и особенности

  • Внутреннее значение времени хранится как Unix timestamp в миллисекундах
  • Часовой пояс не меняет абсолютный момент времени, а влияет на форматирование и вычисление смещения
  • Методы add, subtract, setTimezone и другие операции не изменяют текущий экземпляр, а возвращают новый
  • Duration поддерживает только фиксированные единицы времени
  • Календарная арифметика через month и year учитывает реальную длину месяцев
  • Разница в month и year считается календарно, а не через точное число миллисекунд
  • Поддержка часовых поясов зависит от Intl и доступных IANA time zone в среде выполнения

Лицензия

ISC