forked from mengyxu/noob-components
7 changed files with 213 additions and 119 deletions
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
import dayjs, { type Dayjs } from "dayjs"; |
||||
import customParseFormat from "dayjs/plugin/customParseFormat"; |
||||
import timezone from "dayjs/plugin/timezone"; |
||||
import utc from "dayjs/plugin/utc"; |
||||
import { match, P } from "ts-pattern"; |
||||
import { computed, toValue, type MaybeRefOrGetter } from "vue"; |
||||
|
||||
dayjs.extend(customParseFormat); |
||||
dayjs.extend(utc); |
||||
dayjs.extend(timezone); |
||||
|
||||
export type TimestampDisplayType = "iso8601" | "unix" | "unixMillis"; |
||||
|
||||
export interface TimestampDisplayConfig { |
||||
valueFormat?: string; |
||||
valueTz?: string; |
||||
displayFormat?: string; |
||||
locale?: string; |
||||
type?: TimestampDisplayType; |
||||
} |
||||
|
||||
export interface TimestampDisplayInput extends TimestampDisplayConfig { |
||||
value: string | number; |
||||
} |
||||
|
||||
export type TimestampSimpleConfig = undefined | boolean | string | TimestampDisplayConfig; |
||||
|
||||
export const DEFAULT_TIMESTAMP_DISPLAY_FORMAT = "YYYY-MM-DD HH:mm:ss"; |
||||
|
||||
function withDefaultDisplayFormat( |
||||
config: TimestampDisplayConfig, |
||||
defaultDisplayFormat?: string |
||||
): TimestampDisplayConfig { |
||||
if (!defaultDisplayFormat || config.displayFormat) { |
||||
return config; |
||||
} |
||||
|
||||
return { |
||||
...config, |
||||
displayFormat: defaultDisplayFormat, |
||||
}; |
||||
} |
||||
|
||||
export function normalizeTimestampValue( |
||||
timestamp: TimestampSimpleConfig, |
||||
defaultDisplayFormat?: string |
||||
): TimestampDisplayConfig | null { |
||||
return match(timestamp) |
||||
.with(P.nullish, () => null) |
||||
.with(true, () => withDefaultDisplayFormat({ type: "unixMillis" }, defaultDisplayFormat)) |
||||
.with(P.union("iso8601", "unix", "unixMillis"), (type) => withDefaultDisplayFormat({ type }, defaultDisplayFormat)) |
||||
.with(P.string, (valueFormat) => withDefaultDisplayFormat({ valueFormat }, defaultDisplayFormat)) |
||||
.otherwise((config) => withDefaultDisplayFormat({ ...config }, defaultDisplayFormat)); |
||||
} |
||||
|
||||
export function parseTimestampValue(value: string | number, config: TimestampDisplayConfig): Dayjs { |
||||
const numericValue = match(value) |
||||
.with(P.string, parseFloat) |
||||
.otherwise((n) => n); |
||||
|
||||
if (!isNaN(numericValue)) { |
||||
if (config.type == "unix") return dayjs.unix(numericValue); |
||||
if (config.type == "unixMillis") return dayjs(numericValue); |
||||
} |
||||
|
||||
if (config.valueFormat && config.valueTz) { |
||||
return dayjs.tz(value, config.valueFormat, config.valueTz); |
||||
} |
||||
|
||||
if (config.valueTz) { |
||||
return dayjs.tz(value, config.valueTz); |
||||
} |
||||
|
||||
if (config.valueFormat) { |
||||
return dayjs(value, config.valueFormat); |
||||
} |
||||
|
||||
return dayjs(value); |
||||
} |
||||
|
||||
export function formatTimestampDisplay(value: string | number, config: TimestampDisplayConfig): string { |
||||
let parsed = parseTimestampValue(value, config); |
||||
|
||||
if (!parsed.isValid()) { |
||||
return String(value); |
||||
} |
||||
|
||||
if (config.locale) { |
||||
parsed = parsed.locale(config.locale); |
||||
} |
||||
|
||||
return config.displayFormat ? parsed.format(config.displayFormat) : parsed.format(); |
||||
} |
||||
|
||||
export function formatTimestampFromValue( |
||||
value: string | number, |
||||
timestamp: TimestampSimpleConfig, |
||||
defaultDisplayFormat = DEFAULT_TIMESTAMP_DISPLAY_FORMAT |
||||
): string { |
||||
const config = normalizeTimestampValue(timestamp, defaultDisplayFormat); |
||||
if (!config) { |
||||
return String(value); |
||||
} |
||||
|
||||
return formatTimestampDisplay(value, config); |
||||
} |
||||
|
||||
export function useTimestampDisplay(input: MaybeRefOrGetter<TimestampDisplayInput>) { |
||||
const parsed = computed(() => { |
||||
const resolved = toValue(input); |
||||
return parseTimestampValue(resolved.value, resolved); |
||||
}); |
||||
|
||||
const display = computed(() => { |
||||
const resolved = toValue(input); |
||||
return formatTimestampDisplay(resolved.value, resolved); |
||||
}); |
||||
|
||||
return { |
||||
parsed, |
||||
display, |
||||
}; |
||||
} |
||||
Loading…
Reference in new issue