Как преобразовать диапазон дат в UTC с помощью JavaScript
Узнайте, как преобразовать локальные диапазоны дат в UTC с помощью JavaScript. Руководство с примерами конвертации часовых поясов и форматирования дат для серверной обработки.
Как преобразовать локальный диапазон дат в UTC с помощью JavaScript?
Предположим, пользователь вашего сайта вводит диапазон дат:
2009-1-1 to 2009-1-3
Нужно отправить эти даты на сервер для обработки, но сервер ожидает, что все даты и времена будут в UTC.
Если пользователь находится в Аляске (часовой пояс отличается от UTC), диапазон дат необходимо преобразовать в что‑то вроде:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
С помощью объекта Date в JavaScript, как бы вы преобразовали первый «локальный» диапазон дат в формат UTC, который понимает сервер?
Чтобы преобразовать локализованный диапазон дат в UTC в JavaScript, необходимо создать объекты Date для начала и конца диапазона, применить коррекцию смещения часового пояса и отформатировать их как UTC‑таймстампы. Ключевым моментом является использование getTimezoneOffset() для определения разницы между локальным временем и UTC, а затем корректировка дат, чтобы сервер получил корректно преобразованные значения datetime в UTC.
Содержание
- Понимание задачи
- Базовые методы преобразования дат
- Преобразование диапазонов дат в UTC
- Полный пример реализации
- Альтернативные подходы
Понимание задачи
Когда пользователи вводят диапазоны дат без указания времени, обычно необходимо преобразовать их в диапазоны datetime в UTC для обработки на сервере. Проблема состоит в:
- Отсутствие информации о времени: Пользователи часто указывают только даты (например, «2009-1-1») без значений времени.
- Преобразование часового пояса: Конверсия должна учитывать смещение локального часового пояса пользователя.
- Границы диапазона: Необходимо корректно обрабатывать начало (начало дня) и конец (конец дня) диапазона.
Согласно Mozilla Developer Network, объект Date в JavaScript представляет один момент времени, поэтому важно понимать, как смещения часового пояса влияют на расчёты дат.
Базовые методы преобразования дат
Получение смещения часового пояса
Основной метод для преобразования часового пояса — getTimezoneOffset():
const currentTime = new Date();
const timezoneOffsetMinutes = currentTime.getTimezoneOffset();
const timezoneOffsetHours = timezoneOffsetMinutes / 60;
console.log(`UTC offset: ${timezoneOffsetHours} hours`);
Как объясняет CoreUI, этот метод возвращает разницу в минутах между UTC и локальным временем, что служит фундаментом для точных операций с датами, учитывающих часовой пояс.
Методы UTC
JavaScript предоставляет встроенные методы UTC для независимой от часового пояса работы с датами:
const date = new Date();
console.log(date.getFullYear()); // Локальный год
console.log(date.getUTCFullYear()); // UTC год
console.log(date.getMonth()); // Локальный месяц (0-11)
console.log(date.getUTCMonth()); // UTC месяц (0-11)
Преобразование диапазонов дат в UTC
Шаг 1: Создание объектов Date
Сначала распарсите ввод пользователя в объекты Date. Поскольку время не указано, предположим:
- Начало диапазона: 00:00:00 (начало дня)
- Конец диапазона: 23:59:59.999 (конец дня)
function parseDateRange(startDateStr, endDateStr) {
// Парсим дату начала (начало дня)
const startDate = new Date(startDateStr);
startDate.setHours(0, 0, 0, 0);
// Парсим дату окончания (конец дня)
const endDate = new Date(endDateStr);
endDate.setHours(23, 59, 59, 999);
return { startDate, endDate };
}
Шаг 2: Коррекция смещения часового пояса
Преобразуйте локализованные даты в UTC, корректируя их на смещение часового пояса:
function convertToUTC(date) {
const timezoneOffset = date.getTimezoneOffset(); // в минутах
const utcDate = new Date(date.getTime() + timezoneOffset * 60000);
return utcDate;
}
Шаг 3: Форматирование для сервера
Преобразуйте даты UTC в ISO‑формат или другой требуемый формат:
function formatDateForServer(date) {
return date.toISOString(); // Возвращает формат вроде "2009-01-01T08:00:00.000Z"
}
Полный пример реализации
Ниже приведена полная реализация преобразования диапазона дат «2009-1-1 до 2009-1-3» в UTC:
function convertDateRangeToUTC(startDateStr, endDateStr) {
// Парсим и задаём границы времени
const startDate = new Date(startDateStr);
startDate.setHours(0, 0, 0, 0);
const endDate = new Date(endDateStr);
endDate.setHours(23, 59, 59, 999);
// Преобразуем в UTC
const startUTC = new Date(startDate.getTime() + startDate.getTimezoneOffset() * 60000);
const endUTC = new Date(endDate.getTime() + endDate.getTimezoneOffset() * 60000);
// Форматируем для сервера
return {
start: startUTC.toISOString(),
end: endUTC.toISOString()
};
}
// Пример использования для часового пояса Аляски
const dateRange = convertDateRangeToUTC("2009-1-1", "2009-1-3");
console.log(dateRange.start); // "2009-01-01T08:00:00.000Z" (для Аляски)
console.log(dateRange.end); // "2009-01-04T07:59:59.999Z" (для Аляски)
Расширенная версия с обнаружением часового пояса
Для более надёжной обработки можно определить часовой пояс пользователя:
function getUserTimezone() {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
}
function convertDateRangeWithTimezone(startDateStr, endDateStr, timezone = null) {
const userTimezone = timezone || getUserTimezone();
// Парсим даты с часовым поясом
const startDate = new Date(startDateStr + "T00:00:00");
const endDate = new Date(endDateStr + "T23:59:59");
// Преобразуем в UTC
const startUTC = new Date(startDate.getTime() + startDate.getTimezoneOffset() * 60000);
const endUTC = new Date(endDate.getTime() + endDate.getTimezoneOffset() * 60000);
return {
timezone: userTimezone,
start: startUTC.toISOString(),
end: endUTC.toISOString()
};
}
Альтернативные подходы
Использование библиотеки Date-fns
Для более надёжной работы с датами рассмотрите использование библиотеки, такой как date-fns:
import { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';
function convertWithDateFns(startDateStr, endDateStr, timeZone) {
const startDate = new Date(startDateStr + "T00:00:00");
const endDate = new Date(endDateStr + "T23:59:59");
const startUTC = zonedTimeToUtc(startDate, timeZone);
const endUTC = zonedTimeToUtc(endDate, timeZone);
return {
start: startUTC.toISOString(),
end: endUTC.toISOString()
};
}
Использование библиотеки Luxon
Luxon предоставляет всестороннюю поддержку часовых поясов:
import { DateTime } from 'luxon';
function convertWithLuxon(startDateStr, endDateStr) {
const start = DateTime.fromISO(startDateStr).set({ hour: 0, minute: 0, second: 0 });
const end = DateTime.fromISO(endDateStr).set({ hour: 23, minute: 59, second: 59 });
return {
start: start.toUTC().toISO(),
end: end.toUTC().toISO()
};
}
Учет серверной обработки
Согласно документации PostgreSQL, при выводе значения типа timestamp with time zone всегда выполняется преобразование из UTC в текущий часовой пояс. Это означает, что ваш сервер может обрабатывать окончательное преобразование часового пояса, поэтому вы можете отправлять строки UTC‑таймстампов и позволить серверу обработать их соответствующим образом.
Заключение
- Основной метод: используйте
getTimezoneOffset()для получения разницы между локальным временем и UTC, затем корректируйте объектыDateсоответственно. - Границы дат: всегда указывайте диапазон времени (начало в 00:00:00, конец в 23:59:59.999), когда пользователи вводят только даты.
- Форматирование: используйте
toISOString()для преобразования дат UTC в ISO‑формат при передаче на сервер. - Библиотеки: рассмотрите использование date-fns или Luxon для более сложных операций с часовыми поясами.
- Тестирование: всегда проверяйте работу с разными часовыми поясами, чтобы убедиться, что логика преобразования работает корректно.
Для продакшн‑приложений рекомендуется использовать проверенные библиотеки, такие как date-fns-tz или Luxon, которые обеспечивают надёжную обработку часовых поясов и избегают крайних случаев, которые могут возникнуть при ручных расчётах смещения.