core/panel/utils/date.ts

141 lines
4.4 KiB
TypeScript
Raw Normal View History

2025-07-02 19:30:21 +00:00
import { createMemo } from 'solid-js'
import { useI18n } from '../intl/i18n'
export type Language = 'ru' | 'en'
2025-06-30 18:25:26 +00:00
/**
2025-07-02 19:30:21 +00:00
* Форматирование даты в формате "X дней назад" с поддержкой многоязычности
2025-06-30 18:25:26 +00:00
* @param timestamp - Временная метка
2025-07-02 19:30:21 +00:00
* @param language - Язык для форматирования ('ru' | 'en')
2025-06-30 18:25:26 +00:00
* @returns Форматированная строка с относительной датой
*/
2025-07-02 19:30:21 +00:00
export function formatDateRelativeStatic(timestamp?: number, language: Language = 'ru'): string {
if (!timestamp) return ''
2025-06-30 18:25:26 +00:00
const now = Math.floor(Date.now() / 1000)
const diff = now - timestamp
// Меньше минуты
if (diff < 60) {
2025-07-02 19:30:21 +00:00
return language === 'ru' ? 'только что' : 'just now'
2025-06-30 18:25:26 +00:00
}
// Меньше часа
if (diff < 3600) {
const minutes = Math.floor(diff / 60)
2025-07-02 19:30:21 +00:00
if (language === 'ru') {
return `${minutes} ${getMinutesForm(minutes)} назад`
} else {
return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`
}
2025-06-30 18:25:26 +00:00
}
// Меньше суток
if (diff < 86400) {
const hours = Math.floor(diff / 3600)
2025-07-02 19:30:21 +00:00
if (language === 'ru') {
return `${hours} ${getHoursForm(hours)} назад`
} else {
return `${hours} hour${hours !== 1 ? 's' : ''} ago`
}
2025-06-30 18:25:26 +00:00
}
// Меньше 30 дней
if (diff < 2592000) {
const days = Math.floor(diff / 86400)
2025-07-02 19:30:21 +00:00
if (language === 'ru') {
return `${days} ${getDaysForm(days)} назад`
} else {
return `${days} day${days !== 1 ? 's' : ''} ago`
}
2025-06-30 18:25:26 +00:00
}
// Меньше года
if (diff < 31536000) {
const months = Math.floor(diff / 2592000)
2025-07-02 19:30:21 +00:00
if (language === 'ru') {
return `${months} ${getMonthsForm(months)} назад`
} else {
return `${months} month${months !== 1 ? 's' : ''} ago`
}
2025-06-30 18:25:26 +00:00
}
// Больше года
const years = Math.floor(diff / 31536000)
2025-07-02 19:30:21 +00:00
if (language === 'ru') {
return `${years} ${getYearsForm(years)} назад`
} else {
return `${years} year${years !== 1 ? 's' : ''} ago`
}
}
/**
* Реактивная версия форматирования даты, которая автоматически обновляется при смене языка
* @param timestamp - Временная метка
* @returns Реактивный сигнал с форматированной строкой
*/
export function formatDateRelative(timestamp?: number) {
const { language } = useI18n()
return createMemo(() => formatDateRelativeStatic(timestamp, language()))
2025-06-30 18:25:26 +00:00
}
/**
* Получение правильной формы слова "минута" в зависимости от числа
*/
function getMinutesForm(minutes: number): string {
if (minutes % 10 === 1 && minutes % 100 !== 11) {
return 'минуту'
} else if ([2, 3, 4].includes(minutes % 10) && ![12, 13, 14].includes(minutes % 100)) {
return 'минуты'
}
return 'минут'
}
/**
* Получение правильной формы слова "час" в зависимости от числа
*/
function getHoursForm(hours: number): string {
if (hours % 10 === 1 && hours % 100 !== 11) {
return 'час'
} else if ([2, 3, 4].includes(hours % 10) && ![12, 13, 14].includes(hours % 100)) {
return 'часа'
}
return 'часов'
}
/**
* Получение правильной формы слова "день" в зависимости от числа
*/
function getDaysForm(days: number): string {
if (days % 10 === 1 && days % 100 !== 11) {
return 'день'
} else if ([2, 3, 4].includes(days % 10) && ![12, 13, 14].includes(days % 100)) {
return 'дня'
}
return 'дней'
}
/**
* Получение правильной формы слова "месяц" в зависимости от числа
*/
function getMonthsForm(months: number): string {
if (months % 10 === 1 && months % 100 !== 11) {
return 'месяц'
} else if ([2, 3, 4].includes(months % 10) && ![12, 13, 14].includes(months % 100)) {
return 'месяца'
}
return 'месяцев'
}
/**
* Получение правильной формы слова "год" в зависимости от числа
*/
function getYearsForm(years: number): string {
if (years % 10 === 1 && years % 100 !== 11) {
return 'год'
} else if ([2, 3, 4].includes(years % 10) && ![12, 13, 14].includes(years % 100)) {
return 'года'
}
return 'лет'
}