{
  "version": 3,
  "sources": ["cached_stamp_core.js"],
  "sourcesContent": ["// @ts-check\n/*\n * static/js/cached_stamp_core.js \u2014 when was this cached copy made? (SNOW-1139)\n *\n * Three panels repaint from a cache when their list request fails \u2014 the\n * favourites panel (favourites_offline.js), the reports panel (report.js) and\n * the routes panel (routes.js) \u2014 and each stamped its cached copy with a\n * private HH:MM formatter. A time alone reads the same whether the copy was\n * made this morning or a week ago, so yesterday's cache looked like today's.\n * The downloads surfaces had the opposite gap: a download records when it\n * fetched its bulletins (``contentAt``) and nothing but the /offline/ report\n * ever said so.\n *\n * This module is the one answer to both. It holds no state and touches no\n * DOM; the consumers call it at paint time, and it is loaded in\n * ``public/base.html``'s ``<head>`` so it precedes every one of them however\n * their own tags move.\n *\n *   - ``formatStamp`` \u2014 \"HH:MM\" when the instant is today, \"<day> HH:MM\"\n *     otherwise, '' for a missing or unparseable value. The time stays a\n *     zero-padded 24-hour clock, as the three copies it replaces wrote it.\n *   - ``formatDay`` \u2014 the day alone (\"18 Oct\"), in the page's language.\n *   - ``isBeforeToday`` \u2014 whether an instant falls on an earlier calendar day\n *     than now. A missing, unparseable or future instant is not \"before\n *     today\": a surface that cannot tell says nothing rather than raising a\n *     staleness it cannot prove.\n *\n * \"Today\" is the device's own local day. ``now`` is injectable so tests do\n * not depend on the clock.\n */\n(function () {\n  'use strict';\n\n  /**\n   * Parse an ISO value into a Date, or null when it is missing or invalid.\n   *\n   * @param {unknown} value\n   * @returns {Date | null}\n   */\n  function toDate(value) {\n    if (!value || (typeof value !== 'string' && !(value instanceof Date))) return null;\n    const d = new Date(value);\n    return Number.isNaN(d.valueOf()) ? null : d;\n  }\n\n  /**\n   * The local calendar day of a Date, as a comparable number (YYYYMMDD).\n   *\n   * @param {Date} d\n   * @returns {number}\n   */\n  function dayKey(d) {\n    return d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();\n  }\n\n  /**\n   * The language to format in: the caller's, else the page's, else the\n   * runtime default.\n   *\n   * @param {string | undefined} locale\n   * @returns {string | undefined}\n   */\n  function resolveLocale(locale) {\n    if (locale) return locale;\n    const lang =\n      typeof document !== 'undefined' && document.documentElement\n        ? document.documentElement.lang\n        : '';\n    return lang || undefined;\n  }\n\n  /**\n   * Whether ``value`` falls on an earlier local day than ``now``.\n   *\n   * @param {unknown} value An ISO 8601 instant.\n   * @param {Date} [now] Defaults to the current time.\n   * @returns {boolean}\n   */\n  function isBeforeToday(value, now) {\n    const d = toDate(value);\n    if (!d) return false;\n    return dayKey(d) < dayKey(now || new Date());\n  }\n\n  /**\n   * A short, locale-aware day (\"18 Oct\") for an instant, in local time.\n   *\n   * @param {unknown} value An ISO 8601 instant.\n   * @param {{locale?: string}} [options]\n   * @returns {string} '' when the value cannot be parsed.\n   */\n  function formatDay(value, options) {\n    const d = toDate(value);\n    if (!d) return '';\n    try {\n      return new Intl.DateTimeFormat(resolveLocale(options && options.locale), {\n        day: 'numeric',\n        month: 'short',\n      }).format(d);\n    } catch (_err) {\n      return d.toDateString();\n    }\n  }\n\n  /**\n   * \"HH:MM\" today, \"<day> HH:MM\" on any other day, '' when unparseable.\n   *\n   * @param {unknown} value An ISO 8601 instant.\n   * @param {{now?: Date, locale?: string}} [options]\n   * @returns {string}\n   */\n  function formatStamp(value, options) {\n    const d = toDate(value);\n    if (!d) return '';\n    const opts = options || {};\n    /** @param {number} n */\n    const pad = (n) => String(n).padStart(2, '0');\n    const time = `${pad(d.getHours())}:${pad(d.getMinutes())}`;\n    if (dayKey(d) === dayKey(opts.now || new Date())) return time;\n    return `${formatDay(d.toISOString(), { locale: opts.locale })} ${time}`;\n  }\n\n  window.pwaCachedStampCore = Object.freeze({\n    isBeforeToday: isBeforeToday,\n    formatDay: formatDay,\n    formatStamp: formatStamp,\n  });\n})();\n"],
  "mappings": "CA8BC,UAAY,CACX,aAQA,SAASA,EAAOC,EAAO,CACrB,GAAI,CAACA,GAAU,OAAOA,GAAU,UAAY,EAAEA,aAAiB,MAAQ,OAAO,KAC9E,MAAMC,EAAI,IAAI,KAAKD,CAAK,EACxB,OAAO,OAAO,MAAMC,EAAE,QAAQ,CAAC,EAAI,KAAOA,CAC5C,CAQA,SAASC,EAAOD,EAAG,CACjB,OAAOA,EAAE,YAAY,EAAI,KAASA,EAAE,SAAS,EAAI,GAAK,IAAMA,EAAE,QAAQ,CACxE,CASA,SAASE,EAAcC,EAAQ,CAC7B,OAAIA,IAEF,OAAO,SAAa,KAAe,SAAS,gBACxC,SAAS,gBAAgB,KACzB,KACS,MACjB,CASA,SAASC,EAAcL,EAAOM,EAAK,CACjC,MAAML,EAAIF,EAAOC,CAAK,EACtB,OAAKC,EACEC,EAAOD,CAAC,EAAIC,EAAOI,GAAO,IAAI,IAAM,EAD5B,EAEjB,CASA,SAASC,EAAUP,EAAOQ,EAAS,CACjC,MAAMP,EAAIF,EAAOC,CAAK,EACtB,GAAI,CAACC,EAAG,MAAO,GACf,GAAI,CACF,OAAO,IAAI,KAAK,eAAeE,EAAcK,GAAWA,EAAQ,MAAM,EAAG,CACvE,IAAK,UACL,MAAO,OACT,CAAC,EAAE,OAAOP,CAAC,CACb,MAAe,CACb,OAAOA,EAAE,aAAa,CACxB,CACF,CASA,SAASQ,EAAYT,EAAOQ,EAAS,CACnC,MAAMP,EAAIF,EAAOC,CAAK,EACtB,GAAI,CAACC,EAAG,MAAO,GACf,MAAMS,EAAOF,GAAW,CAAC,EAEnBG,EAAOC,GAAM,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EACtCC,EAAO,GAAGF,EAAIV,EAAE,SAAS,CAAC,CAAC,IAAIU,EAAIV,EAAE,WAAW,CAAC,CAAC,GACxD,OAAIC,EAAOD,CAAC,IAAMC,EAAOQ,EAAK,KAAO,IAAI,IAAM,EAAUG,EAClD,GAAGN,EAAUN,EAAE,YAAY,EAAG,CAAE,OAAQS,EAAK,MAAO,CAAC,CAAC,IAAIG,CAAI,EACvE,CAEA,OAAO,mBAAqB,OAAO,OAAO,CACxC,cAAeR,EACf,UAAWE,EACX,YAAaE,CACf,CAAC,CACH,GAAG",
  "names": ["toDate", "value", "d", "dayKey", "resolveLocale", "locale", "isBeforeToday", "now", "formatDay", "options", "formatStamp", "opts", "pad", "n", "time"]
}
