UNPKG

nhb-toolbox

Version:

A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.

81 lines (80 loc) 3.88 kB
import { roundToNearest } from '../../number/utilities.js'; import { INTERNALS, MS_PER_DAY } from '../constants.js'; export const roundPlugin = ($Chronos) => { const { internalDate, withOrigin, offset } = $Chronos[INTERNALS]; $Chronos.prototype.round = function (unit, nearest = 1) { const date = new Date(internalDate(this)); switch (unit) { case 'millisecond': { const rounded = roundToNearest(date.getMilliseconds(), nearest); date.setMilliseconds(rounded); break; } case 'second': { const fullSecond = date.getSeconds() + date.getMilliseconds() / 1000; const rounded = roundToNearest(fullSecond, nearest); date.setSeconds(rounded, 0); break; } case 'minute': { const fullMinute = date.getMinutes() + date.getSeconds() / 60 + date.getMilliseconds() / 60000; const rounded = roundToNearest(fullMinute, nearest); date.setMinutes(rounded, 0, 0); break; } case 'hour': { const fullHour = date.getHours() + date.getMinutes() / 60 + date.getSeconds() / 3600 + date.getMilliseconds() / 3600000; const rounded = roundToNearest(fullHour, nearest); date.setHours(rounded, 0, 0, 0); break; } case 'day': { const fullDay = date.getDate() + (date.getHours() / 24 + date.getMinutes() / 1440 + date.getSeconds() / 86400 + date.getMilliseconds() / MS_PER_DAY); const rounded = roundToNearest(fullDay, nearest); date.setDate(rounded); date.setHours(0, 0, 0, 0); break; } case 'week': { const weekday = date.getDay(); const offsetToMonday = (weekday + 6) % 7; const startOfWeek = new Date(date); startOfWeek.setDate(startOfWeek.getDate() - offsetToMonday); startOfWeek.setHours(0, 0, 0, 0); const endOfWeek = new Date(startOfWeek); endOfWeek.setDate(endOfWeek.getDate() + 7); const diffToStart = Math.abs(date.getTime() - startOfWeek.getTime()); const diffToEnd = Math.abs(endOfWeek.getTime() - date.getTime()); const rounded = diffToEnd < diffToStart ? endOfWeek : startOfWeek; return withOrigin(new $Chronos(rounded), 'round', offset(this), this.timeZoneName, this.timeZoneId, this.$tzTracker); } case 'month': { const fullMonth = date.getMonth() + date.getDate() / this.lastDateOfMonth; const roundedMonth = roundToNearest(fullMonth, nearest); date.setMonth(roundedMonth, 1); date.setHours(0, 0, 0, 0); break; } case 'year': { const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 1).getTime()) / MS_PER_DAY); const isLeap = new Date(date.getFullYear(), 1, 29).getDate() === 29; const totalDays = isLeap ? 366 : 365; const fullYear = date.getFullYear() + dayOfYear / totalDays; const roundedYear = roundToNearest(fullYear, nearest); date.setFullYear(roundedYear, 0, 1); date.setHours(0, 0, 0, 0); break; } default: return this; } return withOrigin(new $Chronos(date), 'round', offset(this), this.timeZoneName, this.timeZoneId, this.$tzTracker); }; };