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();
|
|
}
|
|
|