Получение дробных значений

В работе с датами и временем в JavaScript основная сложность связана с тем, что большинство встроенных представлений времени оперирует целыми числами. Базовая единица — миллисекунда, однако при преобразовании в секунды, минуты и часы часто требуется сохранение точности в виде дробных значений. Библиотека Day.js сохраняет этот подход: внутреннее хранение всегда основано на миллисекундах, а дробная точность формируется на уровне вычислений.

Ключевая особенность заключается в том, что любые дробные значения в Day.js не хранятся напрямую, а вычисляются при преобразованиях и операциях разности.


Получение дробной разницы через diff

Метод diff поддерживает возврат дробных значений при использовании дополнительного параметра точности.

dayjs(end).diff(dayjs(start), 'second', true)

Третий аргумент true включает режим дробного результата.

Пример:

import dayjs from 'dayjs';

const start = dayjs('2026-01-01T10:00:00.000');
const end = dayjs('2026-01-01T10:00:01.750');

const diffSeconds = end.diff(start, 'second', true);

console.log(diffSeconds); // 1.75

При отключённой точности результат округляется до целого:

end.diff(start, 'second'); // 1

Поддерживаемые единицы для дробных значений включают:

  • millisecond
  • second
  • minute
  • hour
  • day

Поведение точности в разных единицах измерения

Дробные значения становятся особенно заметны при переходе между единицами.

const start = dayjs('2026-01-01T00:00:00.000');
const end = dayjs('2026-01-01T00:01:30.000');

end.diff(start, 'minute', true); // 1.5
end.diff(start, 'second', true); // 90
end.diff(start, 'hour', true);   // 0.025

При этом Day.js всегда вычисляет разницу через миллисекунды, а затем делит на соответствующий коэффициент единицы измерения.


Перевод миллисекунд в дробные секунды

Базовая единица хранения — миллисекунда, поэтому получение дробных значений часто выполняется вручную через деление.

const start = dayjs('2026-01-01T00:00:00.000');
const end = dayjs('2026-01-01T00:00:02.250');

const diffMs = end.valueOf() - start.valueOf();
const diffSeconds = diffMs / 1000;

console.log(diffSeconds); // 2.25

Метод valueOf() возвращает Unix-время в миллисекундах, что делает его основой для точных вычислений.


Работа с Unix-временем и потеря точности

Метод unix() возвращает время в секундах, но без дробной части:

const t = dayjs('2026-01-01T00:00:01.900');

t.unix(); // 1767225601

Любая информация о миллисекундах теряется, поэтому для сохранения дробной точности используется valueOf():

t.valueOf() / 1000; // 1767225601.9

Таким образом, unix() подходит только для целочисленных сценариев, тогда как valueOf() — для точных расчётов.


Формирование дробных значений через кастомные вычисления

Day.js не предоставляет отдельного API для форматирования дробных секунд, поэтому такие значения формируются вручную.

const start = dayjs('2026-01-01T00:00:00.000');
const end = dayjs('2026-01-01T00:00:03.456');

const seconds = (end.valueOf() - start.valueOf()) / 1000;
const minutes = seconds / 60;

console.log(seconds); // 3.456
console.log(minutes); // 0.0576

При необходимости округления используются стандартные методы Jav * aScript:

const rounded = seconds.toFixed(2); // "3.46"

Duration plugin и дробные компоненты

Плагин duration позволяет работать с временными интервалами, включая дробные значения, через миллисекунды.

import duration from 'dayjs/plugin/duration';
dayjs.extend(duration);

const d = dayjs.duration(2500); // 2500 мс

console.log(d.seconds()); // 2
console.log(d.milliseconds()); // 500

Для получения дробного значения в секундах используется комбинирование:

const d = dayjs.duration(2500);

const totalSeconds = d.asSeconds();
console.log(totalSeconds); // 2.5

Метод asSeconds() возвращает точное дробное значение, что делает его основным инструментом для высокоточных расчётов длительностей.


Работа с промежутками высокой точности

При обработке временных интервалов с высокой частотой обновления (таймеры, анимации, измерение задержек) дробные значения становятся критически важными.

const start = dayjs();

setTimeout(() => {
  const end = dayjs();
  const elapsed = end.diff(start, 'second', true);

  console.log(elapsed); // например 1.003
}, 1000);

Такая модель позволяет учитывать реальную задержку выполнения, а не только округлённые секунды.


Ограничения точности и поведение округления

Несмотря на поддержку дробных значений, Day.js опирается на JavaScript Number, что накладывает ограничения IEEE-754. При длительных вычислениях возможно появление плавающих погрешностей:

0.1 + 0.2 // 0.30000000000000004

В контексте Day.js это проявляется при множественных преобразованиях:

const diff = dayjs(end).diff(start, 'second', true);
const shifted = diff * 100;

console.log(shifted);

Для устранения подобных эффектов применяется округление на финальном этапе вычислений.


Сводная модель получения дробных значений

Дробные значения во времени в Day.js формируются через три основных механизма:

  • diff(..., true) — дробная разница между датами
  • valueOf() — базовое миллисекундное представление
  • duration.asX() — точные интервалы через Duration API

Комбинация этих подходов обеспечивает единый математический слой поверх неизменяемой модели хранения времени в миллисекундах.