كيفية التعامل مع المناطق الزمنية في React Router v7
عرض الأوقات بالمنطقة الزمنية المحلية للمستخدم
المشكلة
عندما تعرض التطبيقات الأوقات دون مراعاة موقع المستخدم، يتبع ذلك ارتباك وأخطاء. قد يخزن الخادم وقت حدث كـ "2024-03-15T20:00:00Z" ويعرض "8:00 PM" مباشرة من قيمة UTC تلك. يرى المستخدمون في مناطق زمنية مختلفة نفس الوقت على الساعة لكنهم يفسرونه على أنه محلي بالنسبة لهم، مما يؤدي إلى تفويت المواعيد وتعارضات الجدولة. المشكلة الأساسية هي أن لحظة واحدة في الوقت لها تمثيلات مختلفة اعتماداً على الموقع الجغرافي، وعرض الأوقات في المنطقة الخاطئة يجعلها بلا معنى أو مضللة.
تتفاقم هذه المشكلة عندما يتعاون المستخدمون عبر المناطق. يصبح حدث مجدول للساعة 3:00 PM على الخادم 3:00 PM في كل مكان في واجهة المستخدم، على الرغم من أنه يجب أن يظهر كـ 6:00 AM في طوكيو، و2:00 PM في لندن، و9:00 AM في نيويورك لنفس اللحظة الفعلية.
الحل
قم بتخزين جميع الطوابع الزمنية بتنسيق عالمي مثل سلاسل ISO 8601 مع مؤشرات UTC أو طوابع زمنية Unix. عند عرض هذه الأوقات للمستخدمين، قم بتحويلها إلى كائنات Date في JavaScript وتنسيقها باستخدام واجهات برمجة التطبيقات الدولية التي تحترم المنطقة الزمنية للمتصفح. تكتشف المتصفحات الحديثة تلقائياً المنطقة الزمنية المحلية للمستخدم، وتستفيد مكتبات التنسيق من ذلك لتحويل الطوابع الزمنية UTC إلى التمثيل المحلي الصحيح دون حسابات إزاحة يدوية.
يفصل هذا النهج التخزين عن العرض. يرسل الخادم طابعاً زمنياً قانونياً واحداً، ويعرضه كل عميل وفقاً لمنطقته الزمنية الخاصة، مما يضمن أن يرى الجميع الوقت المحلي الصحيح لنفس اللحظة العالمية.
الخطوات
1. إرسال الطوابع الزمنية بتنسيق ISO 8601 من مصدر البيانات الخاص بك
تأكد من أن واجهة برمجة التطبيقات أو محمل البيانات الخاص بك يُرجع الطوابع الزمنية كسلاسل نصية بتنسيق ISO 8601 مع مؤشرات UTC أو كطوابع زمنية Unix بالميلي ثانية.
export async function loader() {
const event = await fetchEvent();
return {
title: event.title,
startTime: "2024-03-15T20:00:00Z",
endTime: "2024-03-15T22:00:00Z",
};
}
تشير اللاحقة Z إلى توقيت UTC. عند تحليل هذه السلسلة النصية إلى كائن Date في JavaScript، سيقوم المتصفح بتخزينها كطابع زمني UTC داخلياً.
2. إنشاء مكون يقوم بتنسيق الأوقات باستخدام react-intl
استورد مكونات التنسيق من react-intl ومرر كائنات Date التي تم إنشاؤها من سلاسل ISO النصية الخاصة بك.
import { FormattedDate, FormattedTime } from "react-intl";
import type { Route } from "./+types/event";
export default function EventDetails({ loaderData }: Route.ComponentProps) {
const startTime = new Date(loaderData.startTime);
const endTime = new Date(loaderData.endTime);
return (
<div>
<h1>{loaderData.title}</h1>
<p>
<FormattedDate
value={startTime}
year="numeric"
month="long"
day="numeric"
/>
{" at "}
<FormattedTime value={startTime} />
{" to "}
<FormattedTime value={endTime} />
</p>
</div>
);
}
يستخدم مكونا FormattedDate وFormattedTime تلقائياً المنطقة الزمنية المكتشفة للمتصفح لعرض الوقت المحلي الصحيح. يرى المستخدم في نيويورك "15 مارس 2024 الساعة 3:00 مساءً" بينما يرى المستخدم في طوكيو "16 مارس 2024 الساعة 5:00 صباحاً" لنفس الطابع الزمني UTC.
3. استخدام الواجهة البرمجية الحتمية لاحتياجات التنسيق الديناميكية
عندما تحتاج إلى أوقات منسقة في السمات أو القيم المحسوبة أو السياقات غير JSX، استخدم خطاف useIntl.
import { useIntl } from "react-intl";
import type { Route } from "./+types/event";
export default function EventCard({ loaderData }: Route.ComponentProps) {
const intl = useIntl();
const startTime = new Date(loaderData.startTime);
const formattedDate = intl.formatDate(startTime, {
year: "numeric",
month: "short",
day: "numeric",
});
const formattedTime = intl.formatTime(startTime, {
hour: "numeric",
minute: "2-digit",
});
return (
<div>
<h2>{loaderData.title}</h2>
<time dateTime={loaderData.startTime}>
{formattedDate} at {formattedTime}
</time>
</div>
);
}
تُرجع طريقتا formatDate وformatTime سلاسل نصية منسقة وفقاً للغة المستخدم والمنطقة الزمنية الخاصة به. تحافظ سمة dateTime على سلسلة ISO النصية الأصلية لقابلية القراءة الآلية بينما يعرض النص المرئي الوقت المحلي سهل الاستخدام.