基于vue3.0和element-plus的组件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
3.5 KiB

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,
};
}