UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

180 lines (179 loc) 7.27 kB
import { DAY, HOUR, MINUTE, MONTH, SECOND, WEEK, YEAR } from "./constants.js"; import { getMidnight, requireDate } from "./date.js"; import { TIME_UNITS } from "./units.js"; /** Get the millisecond difference between two dates. */ export function getMilliseconds(from, to, caller = getMilliseconds) { return requireDate(to, caller).getTime() - requireDate(from, caller).getTime(); } /** Count the various time units between two dates and return a `Duration` format. */ export function getDuration(from, to, caller = getDuration) { const ms = getMilliseconds(from, to, caller); return { years: Math.trunc(ms / YEAR), months: Math.trunc((ms % YEAR) / MONTH), weeks: Math.trunc((ms % MONTH) / WEEK), days: Math.trunc((ms % WEEK) / DAY), hours: Math.trunc((ms % DAY) / HOUR), minutes: Math.trunc((ms % HOUR) / MINUTE), seconds: Math.trunc((ms % MINUTE) / SECOND), milliseconds: Math.trunc((ms % SECOND) / 1), }; } /** Get the various time units until a certain date. */ export function getUntil(target, current = "now", caller = getUntil) { return getDuration(current, target, caller); } /** Get the various time units since a certain date. */ export function getAgo(target, current = "now", caller = getAgo) { return getDuration(target, current, caller); } /** Count the milliseconds until a date. */ export function getMillisecondsUntil(target, current, caller = getMillisecondsUntil) { return getMilliseconds(current, target, caller); } /** Count the milliseconds since a date. */ export function getMillisecondsAgo(target, current, caller = getMillisecondsAgo) { return 0 - getMillisecondsUntil(target, current, caller); } /** * Count the whole seconds until a date. * - Rounds to the nearest whole second, i.e. `1 second 499 ms` returns `1` */ export function getSecondsUntil(target, current, caller = getSecondsUntil) { return Math.round(getMilliseconds(current, target, caller) / SECOND); } /** * Count the whole seconds since a date. * - Rounds to the nearest whole second, i.e. `1 second 499 ms` returns `1` */ export function getSecondsAgo(target, current, caller = getSecondsAgo) { return 0 - getSecondsUntil(target, current, caller); } /** * Count the whole minutes until a date. * - Rounds to the nearest whole minute, i.e. `1 min 29 seconds` returns `1` */ export function getMinutesUntil(target, current, caller = getMinutesUntil) { return Math.round(getMilliseconds(current, target, caller) / MINUTE); } /** * Count the whole minutes since a date. * - Rounds to the nearest whole minute, i.e. `1 min 29 seconds` returns `1` */ export function getMinutesAgo(target, current, caller = getMinutesAgo) { return 0 - getMinutesUntil(target, current, caller); } /** * Count the whole hours until a date. * - Rounds to the nearest whole hour, i.e. `1 hour 29 minutes` returns `1` */ export function getHoursUntil(target, current, caller = getHoursUntil) { return Math.round(getMilliseconds(current, target, caller) / HOUR); } /** * Count the whole hours since a date. * - Rounds to the nearest whole hour, i.e. `1 hour 29 minutes` returns `1` */ export function getHoursAgo(target, current, caller = getHoursAgo) { return 0 - getHoursUntil(target, current, caller); } /** * Count the calendar days until a date. * - e.g. from 23:59 to 00:01 is 1 day, even though it's only 1 minutes. */ export function getDaysUntil(target, current, caller = getDaysUntil) { return Math.round((getMidnight(target, caller).getTime() - getMidnight(current, caller).getTime()) / DAY); } /** * Count the calendar days since a date. * - Rounds to the nearest whole days. */ export function getDaysAgo(target, current, caller = getDaysAgo) { return 0 - getDaysUntil(target, current, caller); } /** * Count the whole weeks until a date. * - Rounds down to the nearest whole week, i.e. */ export function getWeeksUntil(target, current, caller = getWeeksUntil) { return Math.trunc(getDaysUntil(target, current, caller) / 7); } /** * Count the whole weeks since a date. * - Rounds to the nearest whole week. */ export function getWeeksAgo(target, current, caller = getWeeksAgo) { return 0 - getWeeksUntil(target, current, caller); } /** * Count the calendar months until a date. * - e.g. from March 31st to April 1st is 1 month, even though it's only 1 day. */ export function getMonthsUntil(target, current, caller = getMonthsUntil) { const t = requireDate(target, caller); const c = requireDate(current, caller); const years = t.getFullYear() - c.getFullYear(); const months = t.getMonth() - c.getMonth(); return years * 12 + months; } /** * Count the calendar months since a date. * - e.g. from March 31st to April 1st is 1 month, even though it's only 1 day. */ export function getMonthsAgo(target, current, caller = getMonthsAgo) { return 0 - getMonthsUntil(target, current, caller); } /** * Count the calendar years until a date. * - e.g. from December 31st to January 1st is 1 year, even though it's only 1 day. */ export function getYearsUntil(target, current, caller = getYearsUntil) { return requireDate(target, caller).getFullYear() - requireDate(current, caller).getFullYear(); } /** * Count the calendar years since a date. * - Note this counts calendar years, not 365-day periods. * - e.g. from December 31st to January 1st is -1 years, even though it's only 1 day. */ export function getYearsAgo(target, current, caller = getYearsAgo) { return 0 - getYearsUntil(target, current, caller); } /** Is a date in the past? */ export function isPast(target, current, caller = isPast) { return getMilliseconds(current, target, caller) < 0; } /** Is a date in the future? */ export function isFuture(target, current, caller = isFuture) { return getMilliseconds(current, target, caller) > 0; } /** Is a date today (taking into account midnight). */ export function isToday(target, current, caller = isToday) { return getDaysUntil(target, current, caller) === 0; } /** * Get a best-fit time unit based on an amount in milliseconds. * - Makes a sensible choice about the best time unit to use. * - Years will be used for anything 18 months or more, e.g. `in 2 years` * - Months will be used for anything 10 weeks or more, e.g. `in 14 months` * - Weeks will be used for anything 2 weeks or more, e.g. `in 9 weeks` * - Days will be used for anything 24 hours or more, e.g. `in 13 days` * - Hours will be used for anything 90 minutes or more, e.g. `in 23 hours` * - Minutes will be used for anything 1 second or more, e.g. `1 minute ago` or `in 59 minutes` * - Seconds will be used for anything 1000 milliseconds or more, e.g. `in 59 seconds` */ export function getBestTimeUnit(ms) { const abs = Math.abs(ms); if (abs > 18 * MONTH) return TIME_UNITS.require("year"); if (abs > 10 * WEEK) return TIME_UNITS.require("month"); if (abs > DAY) return TIME_UNITS.require("day"); if (abs > HOUR) return TIME_UNITS.require("hour"); if (abs > MINUTE * 90) return TIME_UNITS.require("minute"); if (abs > SECOND) return TIME_UNITS.require("second"); return TIME_UNITS.require("millisecond"); }