2022-04-12 01:43:49 +02:00
|
|
|
<template>
|
2022-04-15 23:10:47 +02:00
|
|
|
<div>
|
2023-04-12 23:01:21 +02:00
|
|
|
<n-form-item :show-label="false" v-bind="validation.attrs">
|
|
|
|
<n-input-group>
|
|
|
|
<n-input
|
|
|
|
v-model:value="inputDate"
|
|
|
|
:on-input="onDateInputChanged"
|
|
|
|
placeholder="Put you date string here..."
|
|
|
|
clearable
|
|
|
|
:input-props="{ 'data-test-id': 'date-time-converter-input' }"
|
|
|
|
/>
|
2022-04-12 01:43:49 +02:00
|
|
|
|
2023-04-12 23:01:21 +02:00
|
|
|
<n-select
|
|
|
|
v-model:value="formatIndex"
|
|
|
|
style="flex: 0 0 170px"
|
|
|
|
:options="formats.map(({ name }, i) => ({ label: name, value: i }))"
|
|
|
|
data-test-id="date-time-converter-format-select"
|
|
|
|
/>
|
|
|
|
</n-input-group>
|
|
|
|
</n-form-item>
|
|
|
|
<n-divider style="margin-top: 0" />
|
|
|
|
<div v-for="{ name, fromDate } in formats" :key="name" mt-1>
|
|
|
|
<n-input-group>
|
|
|
|
<n-input-group-label style="flex: 0 0 170px"> {{ name }}: </n-input-group-label>
|
|
|
|
<input-copyable
|
|
|
|
:value="formatDateUsingFormatter(fromDate, normalizedDate)"
|
|
|
|
placeholder="Invalid date..."
|
|
|
|
:input-props="{ 'data-test-id': name }"
|
|
|
|
/>
|
|
|
|
</n-input-group>
|
|
|
|
</div>
|
2022-04-15 23:10:47 +02:00
|
|
|
</div>
|
2022-04-12 01:43:49 +02:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2022-04-22 23:31:40 +02:00
|
|
|
import {
|
|
|
|
formatISO,
|
|
|
|
formatISO9075,
|
|
|
|
formatRFC3339,
|
|
|
|
formatRFC7231,
|
|
|
|
fromUnixTime,
|
|
|
|
getTime,
|
|
|
|
getUnixTime,
|
|
|
|
parseISO,
|
|
|
|
parseJSON,
|
2023-04-12 23:01:21 +02:00
|
|
|
isDate,
|
|
|
|
isValid,
|
2022-04-22 23:31:40 +02:00
|
|
|
} from 'date-fns';
|
2023-04-12 23:01:21 +02:00
|
|
|
import { withDefaultOnError } from '@/utils/defaults';
|
|
|
|
import { useValidation } from '@/composable/validation';
|
|
|
|
import type { DateFormat, ToDateMapper } from './date-time-converter.types';
|
|
|
|
import {
|
|
|
|
isISO8601DateTimeString,
|
|
|
|
isISO9075DateString,
|
|
|
|
isRFC3339DateString,
|
|
|
|
isRFC7231DateString,
|
|
|
|
isTimestamp,
|
|
|
|
isUTCDateString,
|
|
|
|
isUnixTimestamp,
|
|
|
|
isMongoObjectId,
|
|
|
|
} from './date-time-converter.models';
|
2022-04-12 01:43:49 +02:00
|
|
|
|
2022-04-22 23:31:40 +02:00
|
|
|
const inputDate = ref('');
|
2022-04-12 01:43:49 +02:00
|
|
|
|
2023-04-12 23:01:21 +02:00
|
|
|
const toDate: ToDateMapper = (date) => new Date(date);
|
2022-04-22 23:31:40 +02:00
|
|
|
|
2023-04-12 23:01:21 +02:00
|
|
|
function formatDateUsingFormatter(formatter: (date: Date) => string, date?: Date) {
|
|
|
|
if (!date || !validation.isValid) {
|
|
|
|
return '';
|
2022-04-22 23:31:40 +02:00
|
|
|
}
|
2022-05-11 22:06:39 +10:00
|
|
|
|
2023-04-12 23:01:21 +02:00
|
|
|
return withDefaultOnError(() => formatter(date), '');
|
|
|
|
}
|
2022-05-11 22:06:39 +10:00
|
|
|
|
2023-04-12 23:01:21 +02:00
|
|
|
const formats: DateFormat[] = [
|
2022-04-22 23:31:40 +02:00
|
|
|
{
|
|
|
|
name: 'JS locale date string',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: (date) => date.toString(),
|
|
|
|
toDate,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: () => false,
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'ISO 8601',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: formatISO,
|
|
|
|
toDate: parseISO,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isISO8601DateTimeString(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'ISO 9075',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: formatISO9075,
|
|
|
|
toDate: parseISO,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isISO9075DateString(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'RFC 3339',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: formatRFC3339,
|
|
|
|
toDate,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isRFC3339DateString(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'RFC 7231',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: formatRFC7231,
|
|
|
|
toDate,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isRFC7231DateString(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Unix timestamp',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: (date) => String(getUnixTime(date)),
|
|
|
|
toDate: (sec) => fromUnixTime(+sec),
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isUnixTimestamp(date),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Timestamp',
|
|
|
|
fromDate: (date) => String(getTime(date)),
|
|
|
|
toDate: (ms) => parseJSON(+ms),
|
|
|
|
formatMatcher: (date) => isTimestamp(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'UTC format',
|
2022-05-11 22:06:39 +10:00
|
|
|
fromDate: (date) => date.toUTCString(),
|
|
|
|
toDate,
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isUTCDateString(date),
|
2022-04-22 23:31:40 +02:00
|
|
|
},
|
2022-09-09 11:53:06 +02:00
|
|
|
{
|
|
|
|
name: 'Mongo ObjectID',
|
|
|
|
fromDate: (date) => Math.floor(date.getTime() / 1000).toString(16) + '0000000000000000',
|
|
|
|
toDate: (objectId) => new Date(parseInt(objectId.substring(0, 8), 16) * 1000),
|
2023-04-12 23:01:21 +02:00
|
|
|
formatMatcher: (date) => isMongoObjectId(date),
|
2022-09-09 11:53:06 +02:00
|
|
|
},
|
2022-04-22 23:31:40 +02:00
|
|
|
];
|
2023-04-12 23:01:21 +02:00
|
|
|
|
|
|
|
const formatIndex = ref(6);
|
|
|
|
const now = useNow();
|
|
|
|
|
|
|
|
const normalizedDate = computed(() => {
|
|
|
|
if (!inputDate.value) {
|
|
|
|
return now.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { toDate } = formats[formatIndex.value];
|
|
|
|
|
|
|
|
try {
|
|
|
|
return toDate(inputDate.value);
|
|
|
|
} catch (_ignored) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function onDateInputChanged(value: string) {
|
|
|
|
const matchingIndex = formats.findIndex(({ formatMatcher }) => formatMatcher(value));
|
|
|
|
if (matchingIndex !== -1) {
|
|
|
|
formatIndex.value = matchingIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const validation = useValidation({
|
|
|
|
source: inputDate,
|
|
|
|
watch: [formatIndex],
|
|
|
|
rules: [
|
|
|
|
{
|
|
|
|
message: 'This date is invalid for this format',
|
|
|
|
validator: (value) =>
|
|
|
|
withDefaultOnError(() => {
|
|
|
|
if (value === '') return true;
|
|
|
|
|
|
|
|
const maybeDate = formats[formatIndex.value].toDate(value);
|
|
|
|
return isDate(maybeDate) && isValid(maybeDate);
|
|
|
|
}, false),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
2022-04-12 01:43:49 +02:00
|
|
|
</script>
|