كيفية التعامل مع المناطق الزمنية في Next.js (موجه الصفحات) الإصدار 16
عرض الأوقات في المنطقة الزمنية المحلية للمستخدم
المشكلة
عندما تعرض التطبيقات الأوقات دون مراعاة موقع المستخدم، يحدث ارتباك. فاجتماع مجدول في "الساعة 3:00 مساءً" يعني أوقاتًا مختلفة اعتمادًا على ما إذا كان المشاهد في نيويورك أو لندن أو طوكيو. إذا قام الخادم بعرض الوقت بتوقيت UTC أو المنطقة الزمنية الخاصة به، فسيرى المستخدمون في المناطق الأخرى أوقاتًا محلية غير صحيحة، مما يؤدي إلى تفويت المواعيد وأخطاء في الجدولة. يجب تفسير الطابع الزمني نفسه بشكل مختلف لكل مستخدم بناءً على منطقته الزمنية.
الحل
قم بتخزين الطوابع الزمنية بتنسيق عالمي مثل ISO 8601 أو طوابع يونكس الزمنية، ثم قم بتنسيقها للعرض في المنطقة الزمنية المحلية للمستخدم على جهاز العميل. اكتشف المنطقة الزمنية للمستخدم باستخدام واجهة برمجة التطبيقات الدولية للمتصفح ومررها إلى وظائف التنسيق في react-intl. هذا يضمن أن كل مستخدم يرى الأوقات معدلة وفقًا لمنطقته الزمنية الخاصة، مما يزيل الغموض حول وقت حدوث الأحداث.
الخطوات
1. اكتشاف المنطقة الزمنية للمستخدم على جهاز العميل
تُرجع Intl.DateTimeFormat().resolvedOptions().timeZone في المتصفح معرّف المنطقة الزمنية IANA للمستخدم، مثل America/New_York أو Europe/London. قم بإنشاء خطاف مخصص للوصول إلى هذه القيمة.
import { useState, useEffect } from "react";
export function useUserTimeZone() {
const [timeZone, setTimeZone] = useState<string>("UTC");
useEffect(() => {
const detected = Intl.DateTimeFormat().resolvedOptions().timeZone;
setTimeZone(detected);
}, []);
return timeZone;
}
يعمل هذا الخطاف فقط على جهاز العميل، مما يتجنب عدم تطابق الترطيب، ويستخدم UTC كقيمة افتراضية حتى يتم اكتشاف المنطقة الزمنية.
2. تنسيق التواريخ باستخدام المنطقة الزمنية للمستخدم باستخدام FormattedDate
قم بتمرير خيار timeZone إلى طرق التنسيق في react-intl للتحكم في المنطقة الزمنية المستخدمة للعرض. استخدم مكون <FormattedDate> مع المنطقة الزمنية المكتشفة.
import { FormattedDate } from "react-intl";
import { useUserTimeZone } from "../hooks/useUserTimeZone";
interface EventDateProps {
timestamp: string;
}
export function EventDate({ timestamp }: EventDateProps) {
const userTimeZone = useUserTimeZone();
return (
<FormattedDate
value={new Date(timestamp)}
timeZone={userTimeZone}
year="numeric"
month="long"
day="numeric"
hour="numeric"
minute="2-digit"
timeZoneName="short"
/>
);
}
تضمن خاصية timeZone أن يتم تنسيق التاريخ في المنطقة الزمنية المحلية للمستخدم بدلاً من منطقة الخادم أو UTC.
3. تنسيق الأوقات بشكل إلزامي باستخدام useIntl
للسيناريوهات التي تحتاج فيها إلى سلسلة منسقة بدلاً من مكون، استخدم الخطاف useIntl للوصول إلى واجهة برمجة التطبيقات الإلزامية للتنسيق.
import { useIntl } from "react-intl";
import { useUserTimeZone } from "../hooks/useUserTimeZone";
interface MeetingTimeProps {
startTime: string;
}
export function MeetingTime({ startTime }: MeetingTimeProps) {
const intl = useIntl();
const userTimeZone = useUserTimeZone();
const formattedTime = intl.formatDate(new Date(startTime), {
timeZone: userTimeZone,
hour: "numeric",
minute: "2-digit",
timeZoneName: "short",
});
return <span title={startTime}>{formattedTime}</span>;
}
تقبل طريقة formatDate وسيطة ثانية مع DateTimeFormatOptions، بما في ذلك timeZone، مما يتيح التحكم الكامل في كيفية عرض الطابع الزمني.
4. تمرير الطوابع الزمنية للخادم كسلاسل ISO
في getServerSideProps، قم بجلب البيانات في وقت الطلب وتمريرها إلى مكون الصفحة كخصائص. قم بتسلسل التواريخ كسلاسل ISO 8601 للحفاظ على معلومات المنطقة الزمنية.
import { GetServerSideProps } from "next";
interface Event {
id: string;
title: string;
startTime: string;
}
interface EventPageProps {
event: Event;
}
export const getServerSideProps: GetServerSideProps<
EventPageProps
> = async () => {
const event = {
id: "1",
title: "Team Meeting",
startTime: new Date("2025-02-15T15:00:00Z").toISOString(),
};
return {
props: { event },
};
};
export default function EventPage({ event }: EventPageProps) {
return (
<div>
<h1>{event.title}</h1>
<EventDate timestamp={event.startTime} />
</div>
);
}
تحافظ سلاسل ISO على اللحظة الدقيقة في الوقت، مما يسمح للتنسيق من جانب العميل بتحويلها بدقة إلى أي منطقة زمنية.