UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

338 lines 11.9 kB
import { LOCALE as defaultLocale } from "../../shared/defaults.js"; import { convertStringToDate } from "../date-picker/DatePickerCalc.js"; function isUTCDateString(dateValue) { if (dateValue.endsWith('Z')) { return true; } const timezonePattern = /[+-]\d{2}:?\d{2}$/; if (timezonePattern.test(dateValue)) { const offsetMatch = dateValue.match(/([+-]\d{2}:?\d{2})$/)?.[1]; if (offsetMatch) { const normalizedOffset = offsetMatch.replace(':', ''); return normalizedOffset === '+0000' || normalizedOffset === '-0000'; } } return false; } export function getDateTimeSeparator(locale, dateStyle, timeStyle) { try { const formatter = new Intl.DateTimeFormat(locale, { dateStyle, timeStyle }); const parts = formatter.formatToParts(new Date()); const datePartTypes = ['day', 'month', 'year', 'weekday']; const timePartTypes = ['hour', 'minute', 'second', 'dayPeriod']; for (let i = 0; i < parts.length; i++) { if (parts[i].type === 'literal') { const prevType = parts[i - 1]?.type; const nextType = parts[i + 1]?.type; if (datePartTypes.includes(prevType) && timePartTypes.includes(nextType)) { return parts[i].value; } } } return ', '; } catch { return ', '; } } export function formatDate(dateValue, { locale = defaultLocale, options = { dateStyle: 'short' }, timeZone, hideCurrentYear, hideYear } = {}) { const originalString = typeof dateValue === 'string' ? dateValue : typeof dateValue === 'number' ? String(dateValue) : null; const dateInput = typeof dateValue === 'number' ? String(dateValue) : dateValue; const date = convertStringToDate(dateInput); const finalOptions = { ...options }; if (timeZone) { finalOptions.timeZone = timeZone; } else if (options.timeStyle && originalString && isUTCDateString(originalString)) { finalOptions.timeZone = 'UTC'; } const dateStyle = finalOptions.dateStyle; const shouldHideYear = dateStyle && (hideYear || hideCurrentYear && date.getFullYear() === new Date().getFullYear()); if (typeof Intl === 'undefined') { return date.toLocaleString(locale, finalOptions); } if (shouldHideYear) { const dateOnlyOptionsByStyle = { full: { weekday: 'long', month: 'long', day: 'numeric' }, long: { month: 'long', day: 'numeric' }, medium: { month: 'short', day: 'numeric' }, short: { month: 'numeric', day: 'numeric' } }; const dateOnlyOptions = { ...dateOnlyOptionsByStyle[dateStyle], ...(finalOptions.timeZone ? { timeZone: finalOptions.timeZone } : {}) }; const datePart = new Intl.DateTimeFormat(locale, dateOnlyOptions).format(date); if (finalOptions.timeStyle) { const timeOnlyOptions = { timeStyle: finalOptions.timeStyle, ...(finalOptions.timeZone ? { timeZone: finalOptions.timeZone } : {}) }; const timePart = new Intl.DateTimeFormat(locale, timeOnlyOptions).format(date); const separator = getDateTimeSeparator(locale, dateStyle, finalOptions.timeStyle); return `${datePart}${separator}${timePart}`; } return datePart; } return new Intl.DateTimeFormat(locale, finalOptions).format(date); } export function formatDateRange(dates, { locale = defaultLocale, options = { dateStyle: 'long' } } = {}) { const startDate = convertStringToDate(dates.startDate); const endDate = convertStringToDate(dates.endDate); if (typeof Intl !== 'undefined') { return new Intl.DateTimeFormat(locale, options).formatRange(startDate, endDate); } const startDateString = startDate.toLocaleString(locale, options); const endDateString = endDate.toLocaleString(locale, options); return `${startDateString}-${endDateString}`; } const timeUnitsInMs = { seconds: 1000, minutes: 60_000, hours: 3_600_000, days: 86_400_000, weeks: 604_800_000, months: 30.4375 * 86_400_000, years: 365.25 * 86_400_000 }; export function getRelativeTime(date, locale = defaultLocale, options = { numeric: 'always', style: 'long' }, dateStyle, relativeTimeReference) { const relativeTimeOptions = { ...options, style: dateStyle === 'short' ? 'narrow' : dateStyle === 'medium' ? 'short' : 'long' }; try { const relativeTimeFormatter = new Intl.RelativeTimeFormat(locale, relativeTimeOptions); const nowDate = relativeTimeReference instanceof Date ? relativeTimeReference : typeof relativeTimeReference === 'function' ? relativeTimeReference() : new Date(); const msDateDifference = date.getTime() - nowDate.getTime(); const timeUnit = getTimeUnit(msDateDifference); const timeUnitDifference = Math.round(msDateDifference / timeUnitsInMs[timeUnit]); return relativeTimeFormatter.format(timeUnitDifference, timeUnit); } catch (error) { return formatDate(date, { locale, options: dateStyle ? { dateStyle } : undefined }); } } export function getRelativeTimeNextUpdateMs(date, relativeTimeReference = new Date()) { const nowDate = relativeTimeReference instanceof Date ? relativeTimeReference : typeof relativeTimeReference === 'function' ? relativeTimeReference() : new Date(); const diff = date.getTime() - nowDate.getTime(); if (!Number.isFinite(diff)) { return 1000; } const unit = getTimeUnit(diff); const unitMs = timeUnitsInMs[unit]; const v = diff / unitMs; const msUntilFlip = (v - (Math.round(v) - 0.5)) * unitMs; const min = unit === 'seconds' ? 500 : 1000; return Math.max(min, Math.floor(msUntilFlip) + 50); } const UNIT_THRESHOLDS = [[timeUnitsInMs.minutes, 'seconds'], [timeUnitsInMs.hours, 'minutes'], [timeUnitsInMs.days, 'hours'], [timeUnitsInMs.weeks, 'days'], [timeUnitsInMs.months, 'weeks'], [timeUnitsInMs.years, 'months']]; function getTimeUnit(msDifference) { var _UNIT_THRESHOLDS$find; const abs = Math.abs(msDifference); return (_UNIT_THRESHOLDS$find = UNIT_THRESHOLDS.find(([limit]) => abs < limit)?.[1]) !== null && _UNIT_THRESHOLDS$find !== void 0 ? _UNIT_THRESHOLDS$find : 'years'; } const DURATION_PATTERN = /^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/; export function parseDuration(durationString) { if (!durationString || typeof durationString !== 'string') { return 0; } const match = durationString.match(DURATION_PATTERN); if (!match) { return 0; } const [, years = '0', months = '0', weeks = '0', days = '0', hours = '0', minutes = '0', seconds = '0'] = match; return parseInt(years) * timeUnitsInMs.years + parseInt(months) * timeUnitsInMs.months + parseInt(weeks) * timeUnitsInMs.weeks + parseInt(days) * timeUnitsInMs.days + parseInt(hours) * timeUnitsInMs.hours + parseInt(minutes) * timeUnitsInMs.minutes + parseInt(seconds) * timeUnitsInMs.seconds; } function buildDurationObject(durationMs, originalDurationString) { if (originalDurationString) { const match = originalDurationString.match(DURATION_PATTERN); if (match) { const [, years, months, weeks, days, hours, minutes, seconds] = match; const result = {}; if (years !== undefined && years !== '0') { result.years = parseInt(years); } if (months !== undefined && months !== '0') { result.months = parseInt(months); } if (weeks !== undefined && weeks !== '0') { result.weeks = parseInt(weeks); } if (days !== undefined && days !== '0') { result.days = parseInt(days); } if (hours !== undefined && hours !== '0') { result.hours = parseInt(hours); } if (minutes !== undefined && minutes !== '0') { result.minutes = parseInt(minutes); } if (seconds !== undefined && seconds !== '0') { result.seconds = parseInt(seconds); } return result; } } const absDuration = Math.abs(durationMs); const units = { years: Math.floor(absDuration / timeUnitsInMs.years), months: Math.floor(absDuration % timeUnitsInMs.years / timeUnitsInMs.months), weeks: Math.floor(absDuration % timeUnitsInMs.months / timeUnitsInMs.weeks), days: Math.floor(absDuration % timeUnitsInMs.weeks / timeUnitsInMs.days), hours: Math.floor(absDuration % timeUnitsInMs.days / timeUnitsInMs.hours), minutes: Math.floor(absDuration % timeUnitsInMs.hours / timeUnitsInMs.minutes), seconds: Math.floor(absDuration % timeUnitsInMs.minutes / timeUnitsInMs.seconds) }; if (durationMs === 0 && originalDurationString) { const match = originalDurationString.match(DURATION_PATTERN); if (match) { const [, years, months, weeks, days, hours, minutes, seconds] = match; const result = {}; if (years !== undefined) { result.years = 0; } if (months !== undefined) { result.months = 0; } if (weeks !== undefined) { result.weeks = 0; } if (days !== undefined) { result.days = 0; } if (hours !== undefined) { result.hours = 0; } if (minutes !== undefined) { result.minutes = 0; } if (seconds !== undefined) { result.seconds = 0; } return Object.keys(result).length > 0 ? result : { seconds: 0 }; } return { seconds: 0 }; } return Object.fromEntries(Object.entries(units).filter(([, value]) => value > 0)); } function createDurationFormatter(locale, dateStyle) { try { const DurationFormat = Intl.DurationFormat; return new DurationFormat(locale, { style: dateStyle === 'short' ? 'narrow' : dateStyle === 'medium' ? 'short' : 'long' }); } catch { return null; } } export function formatDuration(durationMs, locale = defaultLocale, dateStyle, originalDurationString) { if (!Number.isFinite(durationMs)) { return '0 seconds'; } const durationObject = buildDurationObject(durationMs, originalDurationString); let formatter = createDurationFormatter(locale, dateStyle); if (formatter) { try { const result = formatter.format(durationObject); if (result && result.trim() !== '') { return result; } } catch {} } formatter = createDurationFormatter('en', dateStyle); if (formatter) { try { const result = formatter.format(durationObject); if (result && result.trim() !== '') { return result; } } catch {} } if (durationMs === 0) { return '0'; } const parts = []; const unitLabels = { years: 'year', months: 'month', weeks: 'week', days: 'day', hours: 'hour', minutes: 'minute', seconds: 'second' }; Object.entries(durationObject).forEach(([unit, value]) => { if (value > 0) { const label = unitLabels[unit]; parts.push(`${value} ${label}${value === 1 ? '' : 's'}`); } }); return parts.length > 0 ? parts.join(' ') : '0 seconds'; } export function isValidDuration(durationString) { if (!durationString || typeof durationString !== 'string') { return false; } const match = durationString.match(DURATION_PATTERN); if (!match) { return false; } const [, years, months, weeks, days, hours, minutes, seconds] = match; return !!(years !== undefined || months !== undefined || weeks !== undefined || days !== undefined || hours !== undefined || minutes !== undefined || seconds !== undefined); } export function getOsloDate(date = new Date()) { const OSLO_TIMEZONE = 'Europe/Oslo'; const osloDateFormatter = new Intl.DateTimeFormat('en-CA', { timeZone: OSLO_TIMEZONE, year: 'numeric', month: '2-digit', day: '2-digit' }); const osloDateString = osloDateFormatter.format(date); return new Date(osloDateString + 'T00:00:00.000Z'); } //# sourceMappingURL=DateFormatUtils.js.map