generated from VLADIMIR/template_frontend
188 lines
7.6 KiB
TypeScript
188 lines
7.6 KiB
TypeScript
export function formatRussianDate(dateStr: string): string {
|
||
// 1. Вытаскиваем только саму дату (2026-03-24) с помощью регулярного выражения
|
||
// Это защитит нас от багов с часовыми поясами при парсинге
|
||
const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
||
if (!match) {
|
||
throw new Error("Неверный формат входной строки");
|
||
}
|
||
|
||
// 2. Преобразуем строки в числа
|
||
const year = parseInt(match[1], 10);
|
||
const month = parseInt(match[2], 10);
|
||
const day = parseInt(match[3], 10);
|
||
|
||
// 3. Создаем объект даты (обратите внимание: в JS месяцы начинаются с 0, поэтому month - 1)
|
||
const dateObj = new Date(year, month - 1, day);
|
||
|
||
// 4. Словари для точного форматирования (родительный падеж для месяцев)
|
||
const monthsRu = [
|
||
"января", "февраля", "марта", "апреля", "мая", "июня",
|
||
"июля", "августа", "сентября", "октября", "ноября", "декабря"
|
||
];
|
||
|
||
// В JS 0 - это воскресенье, 1 - понедельник и т.д.
|
||
const weekdaysRu = [
|
||
"воскресенье", "понедельник", "вторник", "среда",
|
||
"четверг", "пятница", "суббота"
|
||
];
|
||
|
||
// 5. Получаем нужные значения
|
||
const monthName = monthsRu[dateObj.getMonth()];
|
||
const weekdayName = weekdaysRu[dateObj.getDay()];
|
||
|
||
// 6. Собираем итоговую строку
|
||
return `${weekdayName} ${day} ${monthName}`;
|
||
}
|
||
|
||
export function getRelativeDayName(dateStr: string): string {
|
||
// 1. Вытаскиваем только дату (например, 2026-03-24)
|
||
const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
||
if (!match) {
|
||
throw new Error("Неверный формат входной строки");
|
||
}
|
||
|
||
const year = parseInt(match[1], 10);
|
||
const month = parseInt(match[2], 10) - 1; // Месяцы в JS начинаются с 0
|
||
const day = parseInt(match[3], 10);
|
||
|
||
// 2. Создаем объект целевой даты и сбрасываем время в 00:00:00
|
||
const targetDate = new Date(year, month, day, 0, 0, 0, 0);
|
||
|
||
// 3. Создаем объект СЕГОДНЯШНЕЙ даты и тоже сбрасываем время в 00:00:00
|
||
const today = new Date();
|
||
today.setHours(0, 0, 0, 0);
|
||
|
||
// 4. Вычисляем разницу в миллисекундах и переводим в дни
|
||
// Используем Math.round, чтобы избежать багов при переходе на летнее/зимнее время
|
||
const diffInMs = targetDate.getTime() - today.getTime();
|
||
const diffInDays = Math.round(diffInMs / (1000 * 60 * 60 * 24));
|
||
|
||
// 5. Возвращаем результат в зависимости от разницы в днях
|
||
switch (diffInDays) {
|
||
case 0:
|
||
return "сегодня";
|
||
case 1:
|
||
return "завтра";
|
||
case 2:
|
||
return "послезавтра"; // бонус :)
|
||
case -1:
|
||
return "вчера"; // бонус :)
|
||
default:
|
||
// Если это не сегодня и не завтра, можно вернуть пустую строку,
|
||
// либо просто количество дней, либо отформатированную дату (как в прошлом ответе)
|
||
return "";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Функция для склонения слов (1 минута, 2 минуты, 5 минут)
|
||
*/
|
||
function getDeclension(number: number, titles: [string, string, string]): string {
|
||
const cases = [2, 0, 1, 1, 1, 2];
|
||
return titles[
|
||
(number % 100 > 4 && number % 100 < 20)
|
||
? 2
|
||
: cases[(number % 10 < 5) ? number % 10 : 5]
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Основная функция форматирования времени
|
||
*/
|
||
export function timeAgo(goDateStr: string): string {
|
||
// 1. Парсим строку регуляркой, чтобы вытащить дату, время и смещение пояса.
|
||
// Игнорируем "m=+..." и доли секунд, так как для "5 минут назад" они не нужны.
|
||
// Группы: 1-Дата, 2-Время, 3-Часовой пояс (например +0700)
|
||
const regex = /^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})(?:\.\d+)? ([+-]\d{4})/;
|
||
const match = goDateStr.match(regex);
|
||
|
||
if (!match) {
|
||
console.error("Неверный формат даты:", goDateStr);
|
||
return goDateStr; // Возвращаем как есть в случае ошибки
|
||
}
|
||
|
||
const datePart = match[1];
|
||
const timePart = match[2];
|
||
const timezone = match[3];
|
||
|
||
// 2. Приводим к формату ISO 8601, который понимает любой браузер:
|
||
// "2026-03-26T12:11:18+0700"
|
||
const isoString = `${datePart}T${timePart}${timezone}`;
|
||
const date = new Date(isoString);
|
||
const now = new Date();
|
||
|
||
// 3. Считаем разницу в секундах
|
||
const seconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
||
|
||
// Если дата в будущем (например, как в вашем примере 2026 год)
|
||
if (seconds < 0) {
|
||
return "в будущем";
|
||
}
|
||
|
||
// 4. Логика интервалов
|
||
const minutes = Math.floor(seconds / 60);
|
||
const hours = Math.floor(minutes / 60);
|
||
const days = Math.floor(hours / 24);
|
||
|
||
if (seconds < 60) {
|
||
return "только что";
|
||
}
|
||
|
||
if (minutes < 60) {
|
||
return `${minutes} ${getDeclension(minutes, ['минуту', 'минуты', 'минут'])} назад`;
|
||
}
|
||
|
||
if (hours < 24) {
|
||
return `${hours} ${getDeclension(hours, ['час', 'часа', 'часов'])} назад`;
|
||
}
|
||
|
||
if (days < 7) {
|
||
return `${days} ${getDeclension(days, ['день', 'дня', 'дней'])} назад`;
|
||
}
|
||
|
||
// Если прошло больше недели, возвращаем просто дату
|
||
// Можно использовать Intl.DateTimeFormat для красоты
|
||
return date.toLocaleDateString("ru-RU", {
|
||
day: "numeric",
|
||
month: "long",
|
||
year: "numeric"
|
||
});
|
||
}
|
||
|
||
export function formatTime(timeStr: string): string {
|
||
if (!timeStr) {
|
||
return "";
|
||
}
|
||
|
||
return timeStr
|
||
// 1. Убираем абсолютно все пробелы (включая табы и неразрывные пробелы)
|
||
.replace(/\s+/g, "")
|
||
// 2. Заменяем все точки на двоеточия
|
||
.replace(/\./g, ":");
|
||
}
|
||
|
||
export function formatTimeRange(text: string): string {
|
||
if (!text) {
|
||
return "";
|
||
}
|
||
|
||
return text
|
||
// 1. Меняем точку на двоеточие ТОЛЬКО в форматах времени (например, 16.00 -> 16:00)
|
||
// (^|[^\d]) - проверяем, что перед цифрой нет других цифр
|
||
// ([0-2]?\d) - часы (от 0 до 29)
|
||
// \. - сама точка
|
||
// ([0-5]\d) - минуты (от 00 до 59)
|
||
// (?!\d) - после минут не должно быть других цифр
|
||
.replace(/(^|[^\d])([0-2]?\d)\.([0-5]\d)(?!\d)/g, "$1$2:$3")
|
||
|
||
// 2. Находим любые дефисы или тире и делаем красивые пробелы вокруг них ("-" -> " - ")
|
||
.replace(/\s*([-–—])\s*/g, " - ")
|
||
|
||
// 3. На всякий случай сжимаем двойные пробелы в один (если они случайно появились)
|
||
.replace(/\s{2,}/g, " ")
|
||
|
||
// 4. Убираем пробелы в самом начале и в самом конце строки
|
||
.trim();
|
||
}
|
||
|