كيفية التعامل مع المناطق الزمنية في React Router v7

عرض الأوقات بالمنطقة الزمنية المحلية للمستخدم

المشكلة

عندما تعرض التطبيقات الأوقات دون مراعاة موقع المستخدم، يحدث الارتباك والأخطاء. قد يخزن الخادم وقت حدث ما بصيغة "2024-03-15T20:00:00Z" ويعرض "8:00 مساءً" مباشرة من قيمة التوقيت العالمي المنسق (UTC). يرى المستخدمون في مناطق زمنية مختلفة نفس وقت الساعة لكنهم يفسرونه على أنه محلي بالنسبة لهم، مما يؤدي إلى تفويت المواعيد وتعارضات في الجدولة. المشكلة الأساسية هي أن اللحظة الواحدة لها تمثيلات مختلفة حسب الموقع الجغرافي، وعرض الأوقات في المنطقة الزمنية الخاطئة يجعلها بلا معنى أو مضللة.

تتفاقم هذه المشكلة عندما يتعاون المستخدمون عبر المناطق المختلفة. حدث مجدول في الساعة 3:00 مساءً على الخادم يظهر كـ 3:00 مساءً في كل مكان في واجهة المستخدم، على الرغم من أنه يجب أن يظهر كـ 6:00 صباحًا في طوكيو، و 2:00 ظهرًا في لندن، و 9:00 صباحًا في نيويورك لنفس اللحظة الفعلية.

الحل

قم بتخزين جميع الطوابع الزمنية بتنسيق عالمي مثل سلاسل ISO 8601 مع مؤشرات التوقيت العالمي المنسق (UTC) أو طوابع يونكس الزمنية. عند عرض هذه الأوقات للمستخدمين، قم بتحويلها إلى كائنات تاريخ JavaScript وتنسيقها باستخدام واجهات برمجة التطبيقات الدولية التي تحترم المنطقة الزمنية للمتصفح. تكتشف المتصفحات الحديثة تلقائيًا المنطقة الزمنية المحلية للمستخدم، وتستفيد مكتبات التنسيق من ذلك لتحويل الطوابع الزمنية UTC إلى التمثيل المحلي الصحيح دون حسابات يدوية للفروق الزمنية.

يفصل هذا النهج التخزين عن العرض. يرسل الخادم طابعًا زمنيًا قانونيًا واحدًا، ويقوم كل عميل بعرضه وفقًا لمنطقته الزمنية الخاصة، مما يضمن أن يرى الجميع الوقت المحلي الصحيح لنفس اللحظة العالمية.

الخطوات

1. إرسال الطوابع الزمنية بتنسيق ISO 8601 من مصدر البيانات الخاص بك

تأكد من أن واجهة برمجة التطبيقات (API) أو محمل البيانات الخاص بك يعيد الطوابع الزمنية كسلاسل ISO 8601 مع مؤشرات التوقيت العالمي المنسق (UTC) أو كطوابع زمنية يونكس بالميلي ثانية.

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. عندما يتم تحليل هذه السلسلة إلى كائن تاريخ جافا سكريبت، سيقوم المتصفح بتخزينها داخليًا كطابع زمني UTC.

2. إنشاء مكون يقوم بتنسيق الأوقات باستخدام react-intl

قم باستيراد مكونات التنسيق من react-intl وتمرير كائنات التاريخ التي تم إنشاؤها من سلاسل 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"
        />
        {" في "}
        <FormattedTime value={startTime} />
        {" إلى "}
        <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} في {formattedTime}
      </time>
    </div>
  );
}

تعيد طرق formatDate و formatTime سلاسل منسقة وفقًا للغة المستخدم والمنطقة الزمنية. تحافظ سمة dateTime على سلسلة ISO الأصلية لقابلية القراءة الآلية بينما يعرض النص المعروض الوقت المحلي سهل الاستخدام للمستخدم.