{"version":3,"sources":["../src/timer.ts","../src/duration.ts"],"sourcesContent":["import { elapsed } from \"./duration\";\n\n/**\n * Create a new timer and starts the timing right away. Returns a closed object\n * instead of a class to make sure the variables are bound correctly.\n */\nexport function timer() {\n  const obj = {\n    startMs: Date.now(),\n    endMs: 0,\n\n    stop(): void {\n      obj.endMs = Date.now();\n    },\n\n    restart(): void {\n      obj.endMs = 0;\n      obj.startMs = Date.now();\n    },\n\n    elapsedMs(): number {\n      const stopMs = obj.endMs || Date.now();\n      return stopMs - obj.startMs;\n    },\n\n    toString(): string {\n      return elapsed(obj.elapsedMs());\n    },\n  };\n\n  return obj;\n}\n\n/** Defines the type of the Timer object. */\nexport type Timer = ReturnType<typeof timer>;\n","/**\n * Bunch of miscellaneous constants and utility functions related to handling\n * date and time durations.\n *\n * Note that month and year do not have fixed durations, and hence are excluded\n * from this file. Weeks have fixed durations, but are excluded because we\n * use days as the max duration supported.\n */\n\nimport {\n  HOURS_PER_DAY,\n  MINUTES_PER_HOUR,\n  MS_PER_DAY,\n  MS_PER_HOUR,\n  MS_PER_MINUTE,\n  MS_PER_SECOND,\n  SECONDS_PER_MINUTE,\n} from \"./timeConstants\";\n\nexport type Duration = {\n  days?: number;\n  hours?: number;\n  minutes?: number;\n  seconds?: number;\n  milliseconds?: number;\n};\n\n/**\n * One of: days, hours, minutes, seconds, milliseconds\n */\nexport type DurationType = keyof Duration;\n\n/**\n * Order in which the duration type appears in the duration string.\n */\nexport const DURATION_TYPE_SEQUENCE: DurationType[] = [\n  \"days\",\n  \"hours\",\n  \"minutes\",\n  \"seconds\",\n  \"milliseconds\",\n];\n\n/**\n * Follows the same format as Intl.DurationFormat.prototype.format().\n *\n * Short: 1 yr, 2 mths, 3 wks, 3 days, 4 hr, 5 min, 6 sec, 7 ms, 8 μs, 9 ns\n * Long: 1 year, 2 months, 3 weeks, 3 days, 4 hours, 5 minutes, 6 seconds,\n *       7 milliseconds, 8 microseconds, 9 nanoseconds\n * Narrow: 1y 2mo 3w 3d 4h 5m 6s 7ms 8μs 9ns\n */\nexport type DurationStyle = \"short\" | \"long\" | \"narrow\";\n\nexport type DurationSuffixMap = {\n  short: string;\n  shorts: string;\n  long: string;\n  longs: string;\n  narrow: string;\n};\n\nexport type DurationSuffixType = keyof DurationSuffixMap;\n\nexport const DURATION_STYLE_SUFFIX_MAP: Record<\n  DurationType,\n  DurationSuffixMap\n> = {\n  days: {\n    short: \"day\",\n    shorts: \"days\",\n    long: \"day\",\n    longs: \"days\",\n    narrow: \"d\",\n  },\n  hours: {\n    short: \"hr\",\n    shorts: \"hrs\",\n    long: \"hour\",\n    longs: \"hours\",\n    narrow: \"h\",\n  },\n  minutes: {\n    short: \"min\",\n    shorts: \"mins\",\n    long: \"minute\",\n    longs: \"minutes\",\n    narrow: \"m\",\n  },\n  seconds: {\n    short: \"sec\",\n    shorts: \"secs\",\n    long: \"second\",\n    longs: \"seconds\",\n    narrow: \"s\",\n  },\n  milliseconds: {\n    short: \"ms\",\n    shorts: \"ms\",\n    long: \"millisecond\",\n    longs: \"milliseconds\",\n    narrow: \"ms\",\n  },\n};\n\nfunction getDurationStyleForPlural(style: DurationStyle): DurationSuffixType {\n  return style == \"short\" ? \"shorts\" : style === \"long\" ? \"longs\" : style;\n}\n\nfunction getValueAndUnitSeparator(style: DurationStyle): string {\n  return style === \"narrow\" ? \"\" : \" \";\n}\n\nfunction getDurationTypeSeparator(style: DurationStyle): string {\n  return style === \"narrow\" ? \" \" : \", \";\n}\n\n/**\n * Convert a milliseconds duration into a Duration object. If the given ms is\n * zero, then return an object with a single field of zero with duration type\n * of durationTypeForZero.\n *\n * @param durationTypeForZero Defaults to 'milliseconds'\n */\nexport function msToDuration(\n  ms: number,\n  durationTypeForZero?: DurationType,\n): Duration {\n  if (ms === 0) {\n    durationTypeForZero = durationTypeForZero ?? \"milliseconds\";\n    return { [durationTypeForZero]: 0 };\n  }\n\n  const duration: Duration = {};\n\n  for (let i = 0; i < 1; i++) {\n    let seconds = Math.floor(ms / MS_PER_SECOND);\n    const millis = ms - seconds * MS_PER_SECOND;\n\n    if (millis > 0) {\n      duration[\"milliseconds\"] = millis;\n    }\n\n    if (seconds === 0) {\n      break;\n    }\n\n    let minutes = Math.floor(seconds / SECONDS_PER_MINUTE);\n    seconds -= minutes * SECONDS_PER_MINUTE;\n\n    if (seconds > 0) {\n      duration[\"seconds\"] = seconds;\n    }\n\n    if (minutes === 0) {\n      break;\n    }\n\n    let hours = Math.floor(minutes / MINUTES_PER_HOUR);\n    minutes -= hours * MINUTES_PER_HOUR;\n\n    if (minutes > 0) {\n      duration[\"minutes\"] = minutes;\n    }\n\n    if (hours === 0) {\n      break;\n    }\n\n    const days = Math.floor(hours / HOURS_PER_DAY);\n    hours -= days * HOURS_PER_DAY;\n\n    if (hours > 0) {\n      duration[\"hours\"] = hours;\n    }\n\n    if (days > 0) {\n      duration[\"days\"] = days;\n    }\n  }\n\n  return duration;\n}\n\n/**\n * Returns the number of milliseconds for the given duration.\n */\nexport function durationToMs(duration: Duration): number {\n  const daysMs = (duration.days ?? 0) * MS_PER_DAY;\n  const hoursMs = (duration.hours ?? 0) * MS_PER_HOUR;\n  const minsMs = (duration.minutes ?? 0) * MS_PER_MINUTE;\n  const secsMs = (duration.seconds ?? 0) * MS_PER_SECOND;\n  const msMs = duration.milliseconds ?? 0;\n\n  return daysMs + hoursMs + minsMs + secsMs + msMs;\n}\n\n/**\n * Convenience function to return a duration given an ms or Duration.\n */\nexport function durationOrMsToMs(duration: number | Duration): number {\n  return typeof duration === \"number\" ? duration : durationToMs(duration);\n}\n\n/**\n * Format a given Duration object into a string. If the object has no fields,\n * then returns an empty string.\n *\n * @param style Defaults to 'short'\n */\nexport function formatDuration(duration: Duration, style?: DurationStyle) {\n  style = style ?? \"short\";\n  const stylePlural = getDurationStyleForPlural(style);\n\n  const space = getValueAndUnitSeparator(style);\n\n  const a: string[] = [];\n\n  for (const unit of DURATION_TYPE_SEQUENCE) {\n    const value = duration[unit];\n    if (value === undefined) continue;\n\n    const suffixMap = DURATION_STYLE_SUFFIX_MAP[unit];\n    const suffix = value === 1 ? suffixMap[style] : suffixMap[stylePlural];\n    a.push(value + space + suffix);\n  }\n\n  const separator = getDurationTypeSeparator(style);\n  return a.join(separator);\n}\n\n/**\n * Convert a millisecond duration into a human-readable duration string.\n *\n * @param options.durationTypeForZero - Defaults to 'milliseconds'\n * @param options.style - Defaults to 'short'\n */\nexport function readableDuration(\n  ms: number,\n  options?: { durationTypeForZero?: DurationType; style?: DurationStyle },\n): string {\n  const duration = msToDuration(ms, options?.durationTypeForZero);\n\n  return formatDuration(duration, options?.style);\n}\n\n/** A shortened duration string useful for logging timings. */\nexport function elapsed(ms: number): string {\n  // Use long format for 1 minute or over.\n  if (ms > MS_PER_MINUTE) {\n    return readableDuration(ms);\n  }\n\n  // Use seconds format for over 100ms.\n  if (ms > 100) {\n    return `${(ms / 1000).toFixed(3)}s`;\n  }\n\n  // Use milliseconds format.\n  return ms + \"ms\";\n}\n"],"mappings":"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","names":["timer_exports","__export","timer","__toCommonJS","DURATION_TYPE_SEQUENCE","DURATION_STYLE_SUFFIX_MAP","getDurationStyleForPlural","style","getValueAndUnitSeparator","getDurationTypeSeparator","msToDuration","ms","durationTypeForZero","duration","seconds","millis","minutes","hours","days","formatDuration","duration","style","stylePlural","getDurationStyleForPlural","space","getValueAndUnitSeparator","a","unit","DURATION_TYPE_SEQUENCE","value","suffixMap","DURATION_STYLE_SUFFIX_MAP","suffix","separator","getDurationTypeSeparator","readableDuration","ms","options","msToDuration","elapsed","timer","obj","elapsed"]}