mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
refactor(i18n): i18n utils tools (#7251)
This commit is contained in:
399
packages/frontend/i18n/src/utils/__tests__/time.spec.ts
Normal file
399
packages/frontend/i18n/src/utils/__tests__/time.spec.ts
Normal file
@@ -0,0 +1,399 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { createI18n, getI18n } from '../../';
|
||||
import { i18nTime } from '../time';
|
||||
|
||||
// Intl api is not available in github action, skip the test
|
||||
describe.skip('humanTime', () => {
|
||||
test('absolute', async () => {
|
||||
createI18n();
|
||||
expect(i18nTime('2024-10-10 13:30:28')).toBe('Oct 10, 2024, 1:30:28 PM');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28', {
|
||||
absolute: {
|
||||
accuracy: 'minute',
|
||||
},
|
||||
})
|
||||
).toBe('Oct 10, 2024, 1:30 PM');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28', {
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('Oct 10, 2024');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28', {
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
noYear: true,
|
||||
},
|
||||
})
|
||||
).toBe('Oct 10');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28', {
|
||||
absolute: {
|
||||
accuracy: 'year',
|
||||
},
|
||||
})
|
||||
).toBe('2024');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28', {
|
||||
absolute: {
|
||||
noDate: true,
|
||||
accuracy: 'minute',
|
||||
},
|
||||
})
|
||||
).toBe('1:30 PM');
|
||||
});
|
||||
|
||||
test('relative', async () => {
|
||||
createI18n();
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28.005', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('1s ago');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:25:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('5m ago');
|
||||
expect(
|
||||
i18nTime('2024-10-10 12:59:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('31m ago');
|
||||
expect(
|
||||
i18nTime('2024-10-10 12:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('1h ago');
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('yesterday');
|
||||
expect(
|
||||
i18nTime('2024-10-9 12:30:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('yesterday');
|
||||
expect(
|
||||
i18nTime('2024-10-8 23:59:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('2d ago');
|
||||
expect(
|
||||
i18nTime('2024-10-7 23:59:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('3d ago');
|
||||
expect(
|
||||
i18nTime('2024-10-4 00:00:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('6d ago');
|
||||
expect(
|
||||
i18nTime('2024-10-3 23:59:59', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('last wk.');
|
||||
expect(
|
||||
i18nTime('2024-9-29 23:59:59', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('last wk.');
|
||||
expect(
|
||||
i18nTime('2024-9-28 23:59:59', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('2w ago');
|
||||
expect(
|
||||
i18nTime('2024-9-15 00:00:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('last mo.');
|
||||
expect(
|
||||
i18nTime('2024-9-1 00:00:00', {
|
||||
now: '2024-9-30 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('4w ago');
|
||||
expect(
|
||||
i18nTime('2024-9-10 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('last mo.');
|
||||
expect(
|
||||
i18nTime('2023-9-10 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('last yr.');
|
||||
});
|
||||
|
||||
test('relative - accuracy', async () => {
|
||||
createI18n();
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28.005', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'minute',
|
||||
},
|
||||
})
|
||||
).toBe('now');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:25:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'minute',
|
||||
},
|
||||
})
|
||||
).toBe('5m ago');
|
||||
expect(
|
||||
i18nTime('2024-10-10 12:59:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'hour',
|
||||
},
|
||||
})
|
||||
).toBe('now');
|
||||
expect(
|
||||
i18nTime('2024-10-10 12:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('today');
|
||||
expect(
|
||||
i18nTime('2024-10-4 00:00:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'week',
|
||||
},
|
||||
})
|
||||
).toBe('last wk.');
|
||||
expect(
|
||||
i18nTime('2024-10-9 00:00:00', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'week',
|
||||
},
|
||||
})
|
||||
).toBe('this week');
|
||||
expect(
|
||||
i18nTime('2024-9-1 00:00:00', {
|
||||
now: '2024-9-30 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'month',
|
||||
},
|
||||
})
|
||||
).toBe('this month');
|
||||
expect(
|
||||
i18nTime('2024-9-10 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'year',
|
||||
},
|
||||
})
|
||||
).toBe('this year');
|
||||
expect(
|
||||
i18nTime('2023-9-10 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'year',
|
||||
},
|
||||
})
|
||||
).toBe('last yr.');
|
||||
});
|
||||
|
||||
test('relative - disable yesterdayAndTomorrow', async () => {
|
||||
createI18n();
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('1d ago');
|
||||
expect(
|
||||
i18nTime('2024-10-11 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('in 1d');
|
||||
});
|
||||
|
||||
test('relative - weekday', async () => {
|
||||
createI18n();
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('Wednesday');
|
||||
expect(
|
||||
i18nTime('2024-10-4 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('Friday');
|
||||
expect(
|
||||
i18nTime('2024-10-3 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('1w ago');
|
||||
expect(
|
||||
i18nTime('2024-10-11 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('Friday');
|
||||
expect(
|
||||
i18nTime('2024-10-16 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('Wednesday');
|
||||
expect(
|
||||
i18nTime('2024-10-17 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
yesterdayAndTomorrow: false,
|
||||
},
|
||||
})
|
||||
).toBe('in 1w');
|
||||
});
|
||||
|
||||
test('mix relative and absolute', async () => {
|
||||
createI18n();
|
||||
expect(
|
||||
i18nTime('2024-10-9 14:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
max: [1, 'day'],
|
||||
},
|
||||
})
|
||||
).toBe('23h ago');
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
max: [1, 'day'],
|
||||
},
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('Oct 9, 2024');
|
||||
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
max: [2, 'day'],
|
||||
},
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('yesterday');
|
||||
|
||||
expect(
|
||||
i18nTime('2024-10-8 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
max: [2, 'day'],
|
||||
},
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('Oct 8, 2024');
|
||||
});
|
||||
|
||||
test('chinese', () => {
|
||||
createI18n();
|
||||
getI18n().changeLanguage('zh-Hans');
|
||||
expect(i18nTime('2024-10-10 13:30:28.005')).toBe('2024年10月10日 13:30:28');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28.005', {
|
||||
absolute: {
|
||||
accuracy: 'day',
|
||||
},
|
||||
})
|
||||
).toBe('2024年10月10日');
|
||||
expect(
|
||||
i18nTime('2024-10-10 13:30:28.005', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('1秒前');
|
||||
expect(
|
||||
i18nTime('2024-10-9 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: true,
|
||||
})
|
||||
).toBe('昨天');
|
||||
expect(
|
||||
i18nTime('2024-10-8 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
weekday: true,
|
||||
},
|
||||
})
|
||||
).toBe('星期二');
|
||||
expect(
|
||||
i18nTime('2024-10-8 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'week',
|
||||
},
|
||||
})
|
||||
).toBe('本周');
|
||||
expect(
|
||||
i18nTime('2024-10-8 13:30:30', {
|
||||
now: '2024-10-10 13:30:30',
|
||||
relative: {
|
||||
accuracy: 'month',
|
||||
},
|
||||
})
|
||||
).toBe('本月');
|
||||
});
|
||||
});
|
||||
1
packages/frontend/i18n/src/utils/index.ts
Normal file
1
packages/frontend/i18n/src/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { i18nTime } from './time';
|
||||
281
packages/frontend/i18n/src/utils/time.ts
Normal file
281
packages/frontend/i18n/src/utils/time.ts
Normal file
@@ -0,0 +1,281 @@
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { I18n } from '../i18n';
|
||||
|
||||
export type TimeUnit =
|
||||
| 'second'
|
||||
| 'minute'
|
||||
| 'hour'
|
||||
| 'day'
|
||||
| 'week'
|
||||
| 'month'
|
||||
| 'year';
|
||||
|
||||
const timeUnitCode = {
|
||||
second: 1,
|
||||
minute: 2,
|
||||
hour: 3,
|
||||
day: 4,
|
||||
week: 5,
|
||||
month: 6,
|
||||
year: 7,
|
||||
} satisfies Record<TimeUnit, number>;
|
||||
|
||||
/**
|
||||
* ```ts
|
||||
* // timestamp to string
|
||||
* i18nTime(1728538228000) -> 'Oct 10, 2024, 1:30:28 PM'
|
||||
*
|
||||
* // absolute time string
|
||||
* i18nTime('2024-10-10 13:30:28', { absolute: { accuracy: 'minute' } }) -> '2024-10-10 13:30 PM'
|
||||
* i18nTime('2024-10-10 13:30:28', { absolute: { accuracy: 'minute', noDate: true } }) -> '13:30 PM'
|
||||
* i18nTime('2024-10-10 13:30:28', { absolute: { accuracy: 'minute', noYear: true } }) -> 'Oct 10, 13:30 PM'
|
||||
* i18nTime('2024-10-10 13:30:28', { absolute: { accuracy: 'day' } }) -> 'Oct 10, 2024'
|
||||
*
|
||||
* // relative time string
|
||||
* i18nTime('2024-10-10 13:30:30', { relative: true }) -> 'now'
|
||||
* i18nTime('2024-10-10 13:30:00', { relative: true }) -> '30s ago'
|
||||
* i18nTime('2024-10-10 13:30:30', { relative: { accuracy: 'minute' } }) -> '2m ago'
|
||||
*
|
||||
* // show absolute time string if time is pass 1 day
|
||||
* i18nTime('2024-10-9 14:30:30', { relative: { max: [1, 'day'] } }) -> '23h ago'
|
||||
* i18nTime('2024-10-9 13:30:30', { relative: { max: [1, 'day'] } }) -> 'Oct 9, 2024, 1:30:30 PM'
|
||||
* ```
|
||||
*/
|
||||
export function i18nTime(
|
||||
time: dayjs.ConfigType,
|
||||
options: {
|
||||
// override i18n instance, default is global I18n instance
|
||||
i18n?: I18n;
|
||||
// override now time, default is current time
|
||||
now?: dayjs.ConfigType;
|
||||
relative?:
|
||||
| {
|
||||
// max time to show relative time, if time is pass this time, show absolute time
|
||||
max?: [number, TimeUnit];
|
||||
// show time with this accuracy
|
||||
accuracy?: TimeUnit;
|
||||
// show weekday, e.g. 'Monday', 'Tuesday', etc.
|
||||
weekday?: boolean;
|
||||
// show 'yesterday' or 'tomorrow' if time is
|
||||
yesterdayAndTomorrow?: boolean;
|
||||
}
|
||||
| true; // use default relative option
|
||||
absolute?: {
|
||||
// show time with this accuracy
|
||||
accuracy?: TimeUnit;
|
||||
// hide year
|
||||
noYear?: boolean;
|
||||
// hide date (year, month, day)
|
||||
noDate?: boolean;
|
||||
};
|
||||
} = {}
|
||||
) {
|
||||
const i18n = options.i18n ?? I18n;
|
||||
time = dayjs(time);
|
||||
const now = dayjs(options.now);
|
||||
|
||||
const defaultRelativeOption = {
|
||||
max: [1000, 'year'],
|
||||
accuracy: 'second',
|
||||
weekday: false,
|
||||
yesterdayAndTomorrow: true,
|
||||
} satisfies typeof options.relative;
|
||||
|
||||
const relativeOption = options.relative
|
||||
? options.relative === true
|
||||
? defaultRelativeOption
|
||||
: {
|
||||
...defaultRelativeOption,
|
||||
...options.relative,
|
||||
}
|
||||
: null;
|
||||
|
||||
const defaultAbsoluteOption = {
|
||||
accuracy: 'second',
|
||||
noYear: false,
|
||||
noDate: false,
|
||||
} satisfies typeof options.absolute;
|
||||
|
||||
const absoluteOption = {
|
||||
...defaultAbsoluteOption,
|
||||
...options.absolute,
|
||||
};
|
||||
|
||||
if (relativeOption) {
|
||||
// show relative
|
||||
|
||||
const formatter = new Intl.RelativeTimeFormat(i18n.language, {
|
||||
style: 'narrow',
|
||||
numeric: relativeOption.yesterdayAndTomorrow ? 'auto' : 'always',
|
||||
});
|
||||
|
||||
const timeUnitProcessor = {
|
||||
second: () => {
|
||||
const diffSecond = time.diff(now) / 1000;
|
||||
if (Math.abs(diffSecond) < 1) {
|
||||
return i18n['com.affine.time.now']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'second' &&
|
||||
Math.abs(diffSecond) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(diffSecond) < 60) {
|
||||
return formatter.format(Math.trunc(diffSecond), 'second');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
minute: () => {
|
||||
const diffMinute = time.diff(now) / 1000 / 60;
|
||||
if (Math.abs(diffMinute) < 1) {
|
||||
return i18n['com.affine.time.now']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'minute' &&
|
||||
Math.abs(diffMinute) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(diffMinute) < 60) {
|
||||
return formatter.format(Math.trunc(diffMinute), 'minute');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hour: () => {
|
||||
const diffHour = time.diff(now) / 1000 / 60 / 60;
|
||||
if (Math.abs(diffHour) < 1) {
|
||||
return i18n['com.affine.time.now']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'hour' &&
|
||||
Math.abs(diffHour) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(diffHour) < 24) {
|
||||
return formatter.format(Math.trunc(diffHour), 'hour');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
day: () => {
|
||||
const diffDay = time.startOf('day').diff(now.startOf('day'), 'day');
|
||||
if (Math.abs(diffDay) < 1) {
|
||||
return i18n['com.affine.time.today']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'day' &&
|
||||
Math.abs(diffDay) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (relativeOption.yesterdayAndTomorrow && Math.abs(diffDay) < 2) {
|
||||
return formatter.format(Math.trunc(diffDay), 'day');
|
||||
} else if (relativeOption.weekday && Math.abs(diffDay) < 7) {
|
||||
return new Intl.DateTimeFormat(i18n.language, {
|
||||
weekday: 'long',
|
||||
}).format(time.startOf('day').toDate());
|
||||
} else if (Math.abs(diffDay) < 7) {
|
||||
return formatter.format(Math.trunc(diffDay), 'day');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
week: () => {
|
||||
const inSameMonth = time.startOf('month').isSame(now.startOf('month'));
|
||||
const diffWeek = time.startOf('week').diff(now.startOf('week'), 'week');
|
||||
if (Math.abs(diffWeek) < 1) {
|
||||
return i18n['com.affine.time.this-week']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'week' &&
|
||||
Math.abs(diffWeek) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (inSameMonth || Math.abs(diffWeek) < 3) {
|
||||
return formatter.format(Math.trunc(diffWeek), 'week');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
month: () => {
|
||||
const diffMonth = time
|
||||
.startOf('month')
|
||||
.diff(now.startOf('month'), 'month');
|
||||
if (Math.abs(diffMonth) < 1) {
|
||||
return i18n['com.affine.time.this-mouth']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'month' &&
|
||||
Math.abs(diffMonth) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(diffMonth) < 12) {
|
||||
return formatter.format(Math.trunc(diffMonth), 'month');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
year: () => {
|
||||
const diffYear = time.startOf('year').diff(now.startOf('year'), 'year');
|
||||
if (Math.abs(diffYear) < 1) {
|
||||
return i18n['com.affine.time.this-year']();
|
||||
}
|
||||
if (
|
||||
relativeOption.max[1] === 'year' &&
|
||||
Math.abs(diffYear) >= relativeOption.max[0]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return formatter.format(Math.trunc(diffYear), 'year');
|
||||
},
|
||||
} as Record<TimeUnit, () => string | false | null>;
|
||||
|
||||
const processors = Object.entries(timeUnitProcessor).sort(
|
||||
(a, b) => timeUnitCode[a[0] as TimeUnit] - timeUnitCode[b[0] as TimeUnit]
|
||||
) as [TimeUnit, () => string | false | null][];
|
||||
|
||||
for (const [unit, processor] of processors) {
|
||||
if (timeUnitCode[relativeOption.accuracy] > timeUnitCode[unit]) {
|
||||
continue;
|
||||
}
|
||||
const result = processor();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
if (result === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show absolute
|
||||
const formatter = new Intl.DateTimeFormat(i18n.language, {
|
||||
year:
|
||||
!absoluteOption.noYear && !absoluteOption.noDate ? 'numeric' : undefined,
|
||||
month:
|
||||
!absoluteOption.noDate &&
|
||||
timeUnitCode[absoluteOption.accuracy] <= timeUnitCode['month']
|
||||
? 'short'
|
||||
: undefined,
|
||||
day:
|
||||
!absoluteOption.noDate &&
|
||||
timeUnitCode[absoluteOption.accuracy] <= timeUnitCode['day']
|
||||
? 'numeric'
|
||||
: undefined,
|
||||
hour:
|
||||
timeUnitCode[absoluteOption.accuracy] <= timeUnitCode['hour']
|
||||
? 'numeric'
|
||||
: undefined,
|
||||
minute:
|
||||
timeUnitCode[absoluteOption.accuracy] <= timeUnitCode['minute']
|
||||
? 'numeric'
|
||||
: undefined,
|
||||
second:
|
||||
timeUnitCode[absoluteOption.accuracy] <= timeUnitCode['second']
|
||||
? 'numeric'
|
||||
: undefined,
|
||||
});
|
||||
|
||||
return formatter.format(time.toDate());
|
||||
}
|
||||
Reference in New Issue
Block a user