راهنمای جامع Temporal API جاوااسکریپت، راهکاری مدرن برای مدیریت مؤثر تاریخ و زمان در زمینههای مختلف بینالمللی.
Temporal API جاوااسکریپت: مدیریت مدرن تاریخ و زمان برای مخاطبان جهانی
شیء `Date` در جاوااسکریپت مدتهاست که منبع ناامیدی برای توسعهدهندگان بوده است. تغییرپذیری (mutability)، API ناهماهنگ و پشتیبانی ضعیف از مناطق زمانی، منجر به ایجاد کتابخانههای متعددی مانند Moment.js و date-fns برای پر کردن این شکافها شده است. اکنون، با Temporal API، جاوااسکریپت یک راهحل مدرن و داخلی برای مدیریت تاریخ و زمان با وضوح و دقت بهبود یافته ارائه میدهد. این مقاله یک نمای کلی جامع از Temporal API را با تمرکز بر ویژگیها، مزایا و کاربرد آن در زمینههای مختلف بینالمللی ارائه میدهد.
Temporal API چیست؟
Temporal API یک شیء سراسری جدید در جاوااسکریپت است که برای رفع کاستیهای شیء `Date` طراحی شده است. این API یک رابط برنامهنویسی تمیز و تغییرناپذیر (immutable) برای کار با تاریخ، زمان، مناطق زمانی و سیستمهای تقویم فراهم میکند. نکته مهم این است که هدف آن نمایش مفاهیم تاریخ و زمان به شیوهای است که با کاربردها و انتظارات دنیای واقعی هماهنگتر باشد و بینالمللیسازی را بسیار سادهتر کند.
ویژگیهای کلیدی:
- تغییرناپذیری (Immutability): اشیاء Temporal تغییرناپذیر هستند، به این معنی که عملیاتی مانند افزودن روز یا ماه، اشیاء جدیدی را برمیگردانند به جای اینکه شیء اصلی را تغییر دهند. این امر یک منبع رایج از باگها را حذف کرده و درک کد را آسانتر میکند.
- API واضح: Temporal یک API سازگار و شهودی برای عملیات رایج تاریخ و زمان فراهم میکند.
- پشتیبانی از منطقه زمانی: Temporal شامل پشتیبانی قوی از مناطق زمانی است که به شما امکان میدهد با تاریخ و زمان در مکانهای مختلف بدون پیچیدگیهای شیء قدیمی `Date` کار کنید. این API از پایگاه داده مناطق زمانی IANA استفاده میکند و اطلاعات دقیق و بهروز را تضمین میکند.
- سیستمهای تقویم: فراتر از تقویم میلادی، Temporal از سیستمهای تقویم جایگزین نیز پشتیبانی میکند و نیازهای فرهنگها و مناطق مختلف را برآورده میسازد.
- دقت بهبود یافته: Temporal دقت نانوثانیه را ارائه میدهد و محدودیتهای شیء `Date` مبتنی بر میلیثانیه را برطرف میکند.
اشیاء پایه Temporal
Temporal API چندین نوع شیء جدید معرفی میکند. در اینجا برخی از اصلیترین آنها آورده شده است:
- `Temporal.PlainDate`: یک تاریخ (سال، ماه، روز) را بدون منطقه زمانی نشان میدهد.
- `Temporal.PlainTime`: یک زمان (ساعت، دقیقه، ثانیه، میلیثانیه، میکروثانیه، نانوثانیه) را بدون تاریخ یا منطقه زمانی نشان میدهد.
- `Temporal.PlainDateTime`: یک تاریخ و زمان را بدون منطقه زمانی نشان میدهد.
- `Temporal.ZonedDateTime`: یک تاریخ و زمان را با یک منطقه زمانی مشخص نشان میدهد.
- `Temporal.Instant`: یک لحظه خاص در زمان را نشان میدهد که بر حسب نانوثانیه از مبدأ یونیکس (۱ ژانویه ۱۹۷۰ UTC) اندازهگیری میشود.
- `Temporal.TimeZone`: یک منطقه زمانی را نشان میدهد.
- `Temporal.Duration`: یک بازه زمانی (مثلاً ۲ ساعت و ۳۰ دقیقه) را نشان میدهد.
- `Temporal.YearMonth`: یک سال و ماه را نشان میدهد.
- `Temporal.MonthDay`: یک ماه و روز را نشان میدهد.
کار با تاریخها
ایجاد یک `Temporal.PlainDate`
برای ایجاد یک `Temporal.PlainDate`، میتوانید از سازنده (constructor) آن استفاده کنید:
const plainDate = new Temporal.PlainDate(2024, 10, 27); // سال، ماه (۱-۱۲)، روز
console.log(plainDate.toString()); // خروجی: 2024-10-27
همچنین میتوانید از متد `from` استفاده کنید که یک رشته با فرمت ISO 8601 را میپذیرد:
const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // خروجی: 2024-10-27
دریافت اجزای تاریخ
میتوانید به اجزای جداگانه تاریخ با استفاده از ویژگیهایی مانند `year`، `month` و `day` دسترسی پیدا کنید:
console.log(plainDate.year); // خروجی: 2024
console.log(plainDate.month); // خروجی: 10
console.log(plainDate.day); // خروجی: 27
محاسبات تاریخ
برای افزودن یا کم کردن روز، هفته، ماه یا سال، از متدهای `plus` و `minus` استفاده کنید. این متدها یک شیء `Temporal.PlainDate` جدید را برمیگردانند:
const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // خروجی: 2024-11-03
const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // خروجی: 2024-09-27
مقایسه تاریخها
میتوانید تاریخها را با استفاده از متد `compare` مقایسه کنید:
const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);
console.log(Temporal.PlainDate.compare(date1, date2)); // خروجی: -1 (date1 زودتر از date2 است)
کار با زمانها
ایجاد یک `Temporal.PlainTime`
برای ایجاد یک `Temporal.PlainTime`، از سازنده آن استفاده کنید:
const plainTime = new Temporal.PlainTime(10, 30, 0); // ساعت، دقیقه، ثانیه
console.log(plainTime.toString()); // خروجی: 10:30:00
یا از متد `from` با یک رشته زمان ISO 8601 استفاده کنید:
const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // خروجی: 10:30:00
دریافت اجزای زمان
console.log(plainTime.hour); // خروجی: 10
console.log(plainTime.minute); // خروجی: 30
console.log(plainTime.second); // خروجی: 0
محاسبات زمان
const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // خروجی: 10:45:00
کار با تاریخ و زمان با هم
ایجاد یک `Temporal.PlainDateTime`
میتوانید یک `Temporal.PlainDateTime` را مستقیماً یا با ترکیب یک `Temporal.PlainDate` و یک `Temporal.PlainTime` ایجاد کنید:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // خروجی: 2024-10-27T10:30:00
const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // خروجی: 2024-10-27T10:30:00
مناطق زمانی
مدیریت صحیح مناطق زمانی برای برنامههایی که با کاربران در مکانهای مختلف سروکار دارند، بسیار مهم است. Temporal API پشتیبانی قوی از مناطق زمانی را از طریق اشیاء `Temporal.ZonedDateTime` و `Temporal.TimeZone` فراهم میکند.
ایجاد یک `Temporal.ZonedDateTime`
برای ایجاد یک `Temporal.ZonedDateTime`، به یک `Temporal.PlainDateTime` و یک شناسه منطقه زمانی نیاز دارید. شناسههای منطقه زمانی بر اساس پایگاه داده مناطق زمانی IANA هستند (مثلاً `America/Los_Angeles`، `Europe/London`، `Asia/Tokyo`).
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // خروجی: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (آفست به قوانین DST بستگی دارد)
به طور جایگزین، `Temporal.ZonedDateTime` را از یک `Instant` ایجاد کنید.
const instant = Temporal.Instant.fromEpochSeconds(1666866600); // مهر زمانی نمونه
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // منطقه زمانی مانند 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());
تبدیل بین مناطق زمانی
میتوانید یک `Temporal.ZonedDateTime` را با استفاده از متد `withTimeZone` به یک منطقه زمانی دیگر تبدیل کنید:
const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // خروجی: 2024-10-27T18:30:00+01:00[Europe/London]
کار با آفستهای منطقه زمانی
متد `getOffsetStringFor` از شیء `Temporal.TimeZone` رشته آفست را برای یک `Temporal.Instant` معین فراهم میکند:
const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // خروجی: -07:00 (بسته به قوانین DST)
استفاده از شناسههای صحیح منطقه زمانی IANA برای محاسبات دقیق ضروری است. این شناسهها به طور منظم برای منعکس کردن تغییرات در ساعت تابستانی و مرزهای مناطق زمانی نگهداری و بهروزرسانی میشوند.
مدت زمانها (Durations)
شیء `Temporal.Duration` یک بازه زمانی را نشان میدهد. میتوان از آن برای افزودن یا کم کردن از تاریخ و زمان استفاده کرد.
ایجاد یک `Temporal.Duration`
میتوانید یک `Temporal.Duration` را با استفاده از سازنده آن و با مشخص کردن سال، ماه، روز، ساعت، دقیقه، ثانیه، میلیثانیه، میکروثانیه و نانوثانیه ایجاد کنید:
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // سال، ماه، روز، ساعت، دقیقه، ثانیه، میلیثانیه، میکروثانیه، نانوثانیه
console.log(duration.toString()); // خروجی: P1Y2M3DT4H5M6.007008009S
یا با استفاده از یک رشته مدت زمان ISO 8601:
const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // خروجی: P1Y2M3DT4H5M6S
افزودن مدت زمان به تاریخ و زمان
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // ۷ روز
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // خروجی: 2024-11-03
توجه داشته باشید که افزودن مدت زمانهایی که شامل ماهها یا سالها هستند به تاریخها نیازمند توجه دقیق است، زیرا تعداد روزها در یک ماه یا سال میتواند متفاوت باشد.
سیستمهای تقویم
Temporal API از سیستمهای تقویم مختلف فراتر از تقویم میلادی پشتیبانی میکند. این ویژگی برای برنامههایی که نیاز به مدیریت تاریخها در زمینههای فرهنگی مختلف دارند، بسیار مهم است. در حالی که پشتیبانی هنوز در حال تکامل است، این API پایهای برای توسعه آینده فراهم میکند.
استفاده از تقویمهای جایگزین
برای استفاده از یک تقویم خاص، میتوانید آن را هنگام ایجاد اشیاء Temporal مشخص کنید:
const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // خروجی مشخص ممکن است بسته به پیادهسازی و قالببندی متفاوت باشد. در زمان نگارش این مطلب، در بسیاری از محیطها به polyfill نیاز دارد.
مهم: پشتیبانی از تقویمهای غیر میلادی ممکن است به polyfill یا پشتیبانی مرورگر/محیط خاصی نیاز داشته باشد. برای آخرین اطلاعات، مستندات Temporal API و جداول سازگاری مرورگرها را بررسی کنید.
قالببندی تاریخ و زمان
در حالی که Temporal API بر روی دستکاری تاریخ و زمان تمرکز دارد، قالببندی معمولاً توسط شیء `Intl.DateTimeFormat` انجام میشود که بخشی از Internationalization API است. اشیاء Temporal به طور یکپارچه با `Intl.DateTimeFormat` کار میکنند.
استفاده از `Intl.DateTimeFormat`
در اینجا نحوه قالببندی یک `Temporal.PlainDate` با استفاده از `Intl.DateTimeFormat` آمده است:
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // خروجی: October 27, 2024
const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // خروجی: 27. Oktober 2024
میتوانید گزینههای قالببندی را متناسب با نیازهای خود سفارشی کنید. آرگومان اول `Intl.DateTimeFormat`، لوکال (locale) است که زبان و قراردادهای منطقهای مورد استفاده برای قالببندی را تعیین میکند. استفاده از لوکالهای مختلف (مانند 'en-US', 'de-DE', 'fr-FR', 'ja-JP') فرمتهای خروجی متفاوتی تولید میکند.
قالببندی `Temporal.ZonedDateTime`
قالببندی `Temporal.ZonedDateTime` مشابه است، اما میتوانید اطلاعات منطقه زمانی را نیز در خروجی بگنجانید:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // خروجی: October 27, 2024, 10:30 AM PDT (مخفف منطقه زمانی به قوانین DST بستگی دارد)
بهترین شیوهها برای بینالمللیسازی
هنگام کار با تاریخ و زمان در یک زمینه جهانی، بهترین شیوههای زیر را در نظر داشته باشید:
- از شناسههای منطقه زمانی IANA استفاده کنید: همیشه از شناسههای منطقه زمانی IANA (مانند `America/Los_Angeles`, `Europe/London`) برای مدیریت دقیق منطقه زمانی استفاده کنید.
- از ساعت تابستانی (DST) آگاه باشید: ساعت تابستانی (DST) میتواند بر آفستهای منطقه زمانی تأثیر بگذارد. Temporal API به طور خودکار تغییرات DST را مدیریت میکند.
- برای قالببندی از `Intl.DateTimeFormat` استفاده کنید: از شیء `Intl.DateTimeFormat` برای قالببندی تاریخ و زمان مطابق با لوکال کاربر استفاده کنید.
- سیستمهای تقویم را در نظر بگیرید: اگر برنامه شما نیاز به پشتیبانی از کاربران در زمینههای فرهنگی مختلف دارد، استفاده از سیستمهای تقویم جایگزین را در نظر بگیرید.
- تاریخ و زمان را در UTC ذخیره کنید: هنگام ذخیره تاریخ و زمان در پایگاه داده، بهترین روش ذخیره آنها در UTC (زمان هماهنگ جهانی) است تا از مشکلات منطقه زمانی جلوگیری شود. سپس، برای نمایش، به زمان محلی تبدیل کنید. Temporal متدهایی برای تبدیل به و از UTC فراهم میکند.
- به طور کامل تست کنید: برنامه خود را با مناطق زمانی، لوکالها و سیستمهای تقویم مختلف تست کنید تا اطمینان حاصل شود که برای همه کاربران به درستی کار میکند.
مقایسه Temporal API با شیء قدیمی Date
در اینجا جدولی وجود دارد که تفاوتهای کلیدی و مزایای Temporal API را در مقایسه با شیء قدیمی `Date` برجسته میکند:
ویژگی | شیء قدیمی `Date` | Temporal API |
---|---|---|
تغییرپذیری (Mutability) | تغییرپذیر (شیء اصلی را تغییر میدهد) | تغییرناپذیر (اشیاء جدید را برمیگرداند) |
پشتیبانی از منطقه زمانی | محدود و اغلب مشکلساز | قوی و دقیق، بر اساس پایگاه داده مناطق زمانی IANA |
API | ناهماهنگ و دشوار برای استفاده | واضح، سازگار و شهودی |
دقت | میلیثانیه | نانوثانیه |
سیستمهای تقویم | محدود به میلادی | پشتیبانی از سیستمهای تقویم جایگزین (با پشتیبانی در حال تکامل) |
بینالمللیسازی | برای بینالمللیسازی قوی به کتابخانههای خارجی نیاز دارد | پشتیبانی داخلی و یکپارچهسازی بینقص با `Intl.DateTimeFormat` |
پشتیبانی مرورگرها و Polyfillها
به عنوان یک API نسبتاً جدید، پشتیبانی مرورگرها از Temporal API هنوز در حال تکامل است. آخرین جداول سازگاری مرورگرها (مثلاً در MDN Web Docs) را بررسی کنید تا ببینید کدام مرورگرها و محیطها به طور بومی از آن پشتیبانی میکنند. برای مرورگرهای قدیمیتر یا محیطهایی که پشتیبانی بومی ندارند، میتوانید از polyfillها برای ارائه عملکرد Temporal API استفاده کنید. برای یافتن گزینههای مناسب، "Temporal API polyfill" را در وب جستجو کنید.
نتیجهگیری
JavaScript Temporal API یک گام مهم رو به جلو در مدیریت تاریخ و زمان در جاوااسکریپت است. تغییرناپذیری، API واضح، پشتیبانی قوی از مناطق زمانی و قابلیتهای سیستم تقویم آن، آن را به ابزاری قدرتمند برای توسعهدهندگانی تبدیل میکند که برنامههایی میسازند که نیاز به کار با تاریخ و زمان به صورت دقیق و قابل اعتماد در زمینههای مختلف بینالمللی دارند. در حالی که پشتیبانی مرورگرها هنوز در حال تکامل است، مزایای Temporal API آن را برای یادگیری و پذیرش در پروژههای جدید ارزشمند میکند. با پذیرش Temporal API و پیروی از بهترین شیوههای بینالمللیسازی، میتوانید برنامههایی ایجاد کنید که تجربه تاریخ و زمان یکپارچه و دقیقی را برای کاربران در سراسر جهان فراهم کنند.