PageSourceSearch

https://site.nl/_static/cb72311f9a74ee42/shared/date-core.js

js site.nl collected 2026-09-25 02:54:54 UTC 5,621 bytes, 160 lines download raw bytes

1const DEFAULT_DATE_FORMAT = 'mm-dd-yyyy';
2const DATE_FORMAT_BY_LANGUAGE = Object.freeze({
3  de: 'dd-mm-yyyy',
4  en: DEFAULT_DATE_FORMAT,
5  es: 'dd-mm-yyyy',
6  fr: 'dd-mm-yyyy',
7  nl: 'dd-mm-yyyy',
8  pl: 'dd-mm-yyyy',
9  sl: 'dd-mm-yyyy',
10  sv: 'dd-mm-yyyy',
11});
12const intlFormatterCache = new Map();
13const localeDateFormatCache = new Map();
14
15// API dates are independent of the host's display format and browser timezone.
16// Never guess whether localized text such as 01-12-2028 is day- or month-first.
17const parseApiDate = (value) => {
18  if (value instanceof Date) {
19    return Number.isFinite(value.getTime()) ? new Date(value.getTime()) : null;
20  }
21  if (typeof value !== 'string') return null;
22
23  const text = value.trim();
24  const match = text.match(
25    /^(\d{4}-\d{2}-\d{2})(?:[T ]([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d)(\.\d+)?)?(Z|[+-](?:[01]\d|2[0-3]):?[0-5]\d)?)?$/i,
26  );
27  if (!match) return null;
28
29  const calendarDay = new Date(`${match[1]}T00:00:00Z`);
30  if (!Number.isFinite(calendarDay.getTime()) || calendarDay.toISOString().slice(0, 10) !== match[1]) {
31    return null;
32  }
33  const offset = (match[6] || 'Z').toUpperCase().replace(/^([+-]\d{2})(\d{2})$/, '$1:$2');
34  const fraction = match[5] ? match[5].padEnd(4, '0').slice(0, 4) : '';
35  const timestamp = match[2]
36    ? `${match[1]}T${match[2]}:${match[3]}:${match[4] || '00'}${fraction}${offset}`
37    : `${match[1]}T00:00:00Z`;
38  const date = new Date(timestamp);
39  return Number.isFinite(date.getTime()) ? date : null;
40};
41
42const padDatePart = (value, length = 2) => String(value).padStart(length, '0');
43
44const getIntlFormatter = (locale, options) => {
45  const normalizedLocale = locale || 'en';
46  const cacheKey = JSON.stringify([normalizedLocale, options]);
47  if (intlFormatterCache.has(cacheKey)) {
48    return intlFormatterCache.get(cacheKey);
49  }
50
51  try {
52    const formatter = new Intl.DateTimeFormat(normalizedLocale, options);
53    intlFormatterCache.set(cacheKey, formatter);
54    return formatter;
55  } catch {
56    if (normalizedLocale !== 'en') {
57      return getIntlFormatter('en', options);
58    }
59    return null;
60  }
61};
62
63const formatWithIntl = (date, locale, options) => {
64  const formatter = getIntlFormatter(locale, options);
65  return formatter ? formatter.format(date) : '';
66};
67
68const getLocaleDateFormat = (locale) => {
69  const normalizedLocale = locale || 'en';
70  if (localeDateFormatCache.has(normalizedLocale)) {
71    return localeDateFormatCache.get(normalizedLocale);
72  }
73
74  const language = String(normalizedLocale).trim().toLowerCase().split(/[-_]/)[0];
75  let format = DATE_FORMAT_BY_LANGUAGE[language];
76  if (!format) {
77    format = DEFAULT_DATE_FORMAT;
78    try {
79      const parts = new Intl.DateTimeFormat(normalizedLocale, {
80        day: '2-digit',
81        month: '2-digit',
82        year: 'numeric',
83      }).formatToParts(new Date(2000, 10, 22));
84      const dayIndex = parts.findIndex((part) => part.type === 'day');
85      const monthIndex = parts.findIndex((part) => part.type === 'month');
86      format = dayIndex >= 0 && monthIndex >= 0 && dayIndex < monthIndex ? 'dd-mm-yyyy' : DEFAULT_DATE_FORMAT;
87    } catch {}
88  }
89
90  localeDateFormatCache.set(normalizedLocale, format);
91  return format;
92};
93
94const getPublicAppLocale = () => {
95  if (typeof globalThis === 'undefined' || !globalThis) {
96    return '';
97  }
98
99  const publicEnv = globalThis.PUBLIC_ENV || globalThis.window?.PUBLIC_ENV;
100  const locale = publicEnv?.PUBLIC_APP_LANGUAGE;
101  return locale === null || locale === undefined ? '' : String(locale).trim();
102};
103
104const getDefaultDateFormat = (locale) => getLocaleDateFormat(getPublicAppLocale() || locale || 'en');
105
106const formatLocaleTime = (date, locale, timeZone) => {
107  try {
108    return date.toLocaleTimeString(locale || undefined, timeZone ? { timeZone } : undefined);
109  } catch {
110    return date.toLocaleTimeString();
111  }
112};
113
114const formatDate = (
115  inputDate,
116  { withTime = true, format, twoDigitYear = false, locale = 'en', fallback = '', timeZone, intlOptions } = {},
117) => {
118  if (inputDate === null || inputDate === undefined || inputDate === '') return fallback;
119
120  const date = inputDate instanceof Date ? new Date(inputDate.getTime()) : new Date(inputDate);
121  if (Number.isNaN(date.getTime())) return fallback;
122
123  if (intlOptions && typeof intlOptions === 'object') {
124    const label = formatWithIntl(date, locale, timeZone ? { ...intlOptions, timeZone } : intlOptions);
125    return label || fallback;
126  }
127
128  const useUtc = String(timeZone || '').toUpperCase() === 'UTC';
129  const fullYear = useUtc ? date.getUTCFullYear() : date.getFullYear();
130  const year = twoDigitYear ? padDatePart(fullYear % 100) : padDatePart(fullYear, 4);
131  const month = padDatePart((useUtc ? date.getUTCMonth() : date.getMonth()) + 1);
132  const day = padDatePart(useUtc ? date.getUTCDate() : date.getDate());
133  const resolvedFormat = String(format || getDefaultDateFormat(locale));
134  const dayFirst = resolvedFormat.trim().toLowerCase().startsWith('d');
135  const dateLabel = dayFirst ? `${day}-${month}-${year}` : `${month}-${day}-${year}`;
136
137  if (!withTime) return dateLabel;
138
139  const timeLabel = dayFirst
140    ? `${padDatePart(useUtc ? date.getUTCHours() : date.getHours())}:${padDatePart(
141        useUtc ? date.getUTCMinutes() : date.getMinutes(),
142      )}`
143    : formatLocaleTime(date, locale, timeZone);
144  return `${dateLabel} ${timeLabel}`;
145};
146
147const DATE_CORE = {
148  DEFAULT_DATE_FORMAT,
149  formatDate,
150  getDefaultDateFormat,
151  parseApiDate,
152};
153
154if (typeof globalThis !== 'undefined' && globalThis) {
155  globalThis.DATE_CORE = DATE_CORE;
156}
157
158if (typeof module !== 'undefined' && module.exports) {
159  module.exports = DATE_CORE;
160}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.