All files / utils/algorithms duration.js

92.18% Statements 59/64
16.66% Branches 1/6
50% Functions 1/2
92.18% Lines 59/64

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 651x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x     4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x 1x 1x 1x 1x       1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * @satisfies {{[unit in Intl.RelativeTimeFormatUnit]?:number}}
 * @constant
 */
const durationUnitsInMillis = {
  month: 1000 * 60 * 60 * 24 * 365 / 12,
  day: 1000 * 60 * 60 * 24,
  hour: 1000 * 60 * 60,
  minute: 1000 * 60,
  second: 1000,
}
 
/**
 * @param {number} time1 - timestamp 1, in milliseconds since Epoch
 * @param {number} time2 - timestamp 2, in milliseconds since Epoch
 * @returns {Duration} duration between timestamps
 */
export function getDurationBetweenTimestamps (time1, time2) {
  const durationInMillis = Math.abs(time1 - time2)
 
  const totalDays = Math.floor(durationInMillis / durationUnitsInMillis.day)
  const hours = Math.floor((durationInMillis % durationUnitsInMillis.day) / durationUnitsInMillis.hour)
  const minutes = Math.floor((durationInMillis % durationUnitsInMillis.hour) / durationUnitsInMillis.minute)
  const seconds = Math.floor((durationInMillis % durationUnitsInMillis.minute) / durationUnitsInMillis.second)
  const milliseconds = durationInMillis % durationUnitsInMillis.second
 
  if (totalDays === 0) {
    return { hours, minutes, seconds, milliseconds, totalDays, years: 0, months: 0, days: 0 }
  }
 
  const maxTimestamp = Math.max(time1, time2)
  const minTimestamp = Math.min(time1, time2)
  const maxDate = new Date(maxTimestamp)
  const minDate = new Date(minTimestamp)
  const diffYears = maxDate.getFullYear() - minDate.getFullYear()
  const diffMonths = maxDate.getMonth() - minDate.getMonth()
  const diffDays = maxDate.getDate() - minDate.getDate()
  const elapsedDays = diffDays < 0 ? daysInMonth(minDate.getMonth(), minDate.getFullYear()) - diffDays : diffDays
  const elapsedMonths = (diffMonths < 0 ? 12 - diffMonths : diffMonths) - (diffDays < 0 ? 1 : 0)
  const elapsedYears = diffYears - (diffMonths < 0 ? 1 : 0)
 
  return { hours, minutes, seconds, milliseconds, totalDays, years: elapsedYears, months: elapsedMonths, days: elapsedDays }
}
 
/**
 * @param {number} month - month to check, it is zero-based (January is 0)
 * @param {number} year - year to check, used to detect if it is a leap year
 * @returns {number} number of days in a month
 */
function daysInMonth (month, year) {
  return new Date(year, (month + 1) % 12, 0).getDate()
}
 
/**
 * @typedef {object} Duration
 * @property {number} hours - elapsed remaining hours
 * @property {number} minutes - elapsed remaining minutes
 * @property {number} seconds - elapsed remaining seconds
 * @property {number} milliseconds - elapsed remaining milliseconds
 * @property {number} days - elapsed remaining days
 * @property {number} months - elapsed remaining months
 * @property {number} years - elapsed years
 * @property {number} totalDays - elapsed days
 */