Вопрос или проблема
Итак, в заключение, я хочу, чтобы мои даты работали в униформе. Поскольку мы имеем дело только с датами, а не с временем, как я могу этого достичь? Я уже пробовал много способов. В клиентской части я использую календарь React для пользовательского интерфейса даты и dayjs для форматирования даты. В серверной части я также использую dayjs для форматирования. Я создал веб-приложение, в котором пользователи могут создавать поездки. Эти поездки сильно зависят от дат для таких операций, как даты начала и конца поездки, сроки оплаты, даты окончания бронирования и т. д. Позвольте мне использовать даты начала и окончания поездки в качестве примера. Все, что я хочу, это чтобы, когда пользователь A создает поездку и устанавливает дату начала и окончания с 1 сентября по 10 сентября и публикует поездку, независимо от того, где находится человек, который хочет забронировать поездку, он или она должны видеть те же даты, которые установил владелец поездки для начала и окончания. То, что у меня сейчас, вызывает разочарование. Очень хороший пример: я настроил поездку с следующими датами: дата начала: 1 сентября 2025 года, дата окончания: 10 сентября 2025 года.
На странице бронирования я вижу 31 августа 2025 года.
Я читал, что мне следует рассматривать все как UTC и сохранять мои даты как UTC в базе данных. Я это сделал или, скажем так, я думаю, что сделал это. Вот коды, которые у меня есть. В клиентской части, которая построена с использованием Nextjs, я использую календарь React. Итак, я создал компонент для обработки этого.
import Calendar from "react-calendar";
import "react-calendar/dist/Calendar.css";
export function CustomDatePicker(dates, dateStateFunc){
//это тег p, который показывает дату, когда пользователь выбирает даты из календаря.
<div>
<p>
{dates === null || dates === undefined || !dates ? "Выберите дату"
: dayjs(dates).format("YYYY-MM-DD")}
</p>
</div>
}
<Calendar
value={dates === undefined || dates === null || !dates ? dayjs(new Date()).toDate()
: dayjs(dates).utc()?.format()}
onChange={(e) =>dateStateFunc(e)}
/>
В одном из компонентов, где я использовал компонент даты, я обработал это так: // компонент создания поездки
import { CustomDatePicker } from "../customDate/CustomDate.component";
//Я пытался создать дату utc из дат, которые пришли из календаря React
const createNewDate = (date: Date | string)=>{
let fullDate: Date | string;
const m = dayjs(date).utc().format();
fullDate = m;
return fullDate;
}
const handleDepositeDate = (datePara: Date | string, eventType) => {
const fullDate = createNewDate(datePara as Date);
if (eventType === "start_date") {
setTripData({ ...tripsData, startDate: fullDate });
} else if (eventType === "end_date") {
setTripData({ ...tripsData, endDate: fullDate });
}
};
export function CreateTrip(){
<CustomDatePicker
dates={tripsData?.startDate as string}
dateStateFunc={handleDepositeDate}
/>
}
С приведенными выше кодами, когда я console.log(tripData.startDate, tripData.endDate)
, я вижу UTC дату так: 2024-08-31T23:00:00Z, 2024-09-09T23:00:00Z
.
Это означает, что это на один день меньше. Это то, что отправляется на сервер, который создает ту же дату, которая на один день меньше. В моем бэкенде я просто восстановил дату, поскольку я хочу доверять только бэкенду. Я не знаю, правильно ли это или нет. В приложении большинство дат создаются пользователем. Поэтому в бэкенде я просто беру то, что они создали, и воссоздаю это перед сохранением в базу данных, чтобы убедиться, что правильный формат даты сохранен в базе данных. Мой бэкенд написан на node.js.
Мне сказали всегда использовать полночь UTC.
export const convertDate = (date: Date | string) => {
const converted = dayjs(date).utc().utcOffset(0).startOf("day").format();
return converted;
};
Приведенный выше код также генерирует эту дату, используя клиентскую часть, 1 сентября 2025 года и 10 сентября 2025 года: 2024-08-31T00:00:00Z
и 2024-09-09T00:00:00Z
;
Так почему же он не генерирует дату так, как я ожидал? Мой компьютер в данный момент настроен на UTC+01:00 западная центральная Африка. Чтобы отобразить дату обратно в клиентской части, я все еще использую dayjs для этого.
export const convertDate = (params: {
date: Date | string;
isFortmat?: boolean;
}) => {
const { date, isFortmat } = params;
let converted: string = "";
isFortmat
? (converted = dayjs(date).utc().format("MMM-DD-YYYY"))
: (converted = dayjs(date).utc().format());
return converted;
};
Сейчас это все еще на один день меньше с приведенным выше примером даты.
Ответ или решение
Информация о проблеме с датами в вашем веб-приложении
Данная проблема, связанная с неправильным отображением дат в вашем веб-приложении, вызвана сложными взаимодействиями между временными зонами, стандартами хранения времени и форматами на клиентской и серверной сторонах. Рассмотрим шаги и рекомендации для решения этой проблемы.
1. Причины проблемы
Ваше приложение управляет датами, но в текущем виде данные передаются с учетом часового пояса компьютера, что приводит к получению неправильных значений. Например, если вы выбираете дату 1 сентября 2025 года, она может интерпретироваться как 31 августа 2025 года в UTC, что создаёт несоответствие.
2. Использование UTC
Хранение дат в формате UTC является правильным подходом, так как позволяет избежать проблем с тестированием и обеспечивать совместимость при работе с пользователями из разных часовых поясов. Однако важно правильно обрабатывать и передавать эти данные на клиентской и серверной сторонах.
3. Корректная работа с dayjs
Ваши текущие функции преобразования дат используют dayjs
, что является хорошим выбором для обработки дат. Однако необходимо внести изменения, чтобы гарантировать, что даты сохраняются и отображаются корректно.
4. Рекомендации по коду
На стороне клиента
-
Измените форматирование в
CustomDatePicker
:
Убедитесь, что при отправке данных на сервер вы отправляете дату в формате UTC, установив время на полночь:const createNewDate = (date) => { return dayjs(date).utc().startOf('day').toISOString(); }
-
Убедитесь, что состояние дат правильно обновляется:
Убедитесь, что значения состояния имеют правильный формат:const handleDepositeDate = (datePara, eventType) => { const fullDate = createNewDate(datePara); setTripData(prevData => ({ ...prevData, })); };
На стороне сервера
-
Проверка обработки данных на сервере:
Убедитесь, что сервер обрабатывает получаемые данные и сохраняет их в UTC:exports.createTrip = async (data) => { const startDate = dayjs(data.startDate).utc().startOf('day').toISOString(); const endDate = dayjs(data.endDate).utc().startOf('day').toISOString(); // Сохраните начальную и конечную дату в базе данных };
5. Отображение дат на клиенте
Также обратите внимание на то, как вы отображаете даты. Если пользователь на клиентской стороне находится в другом часовом поясе, перед отображением дат следует также преобразовать их в локальное время, используя dayjs
:
const displayDate = (date) => {
return dayjs(date).local().format('MMM DD, YYYY');
};
6. Итог
Следуя вышеописанным рекомендациям и сохраняя последовательность в использовании формата UTC, вы сможете избежать проблем с неправильным отображением дат. Это позволит пользователям вашего приложения видеть одни и те же даты при создании и бронировании поездок, независимо от их часовой зоны.
Убедитесь, что вы протестировали все изменения на разных устройствах и в различных часовых поясах, чтобы гарантировать, что ваша система работает корректно.