فارسی

راهنمای جامع استفاده از Temporal API جاوا اسکریپت برای محاسبات دقیق و شهودی بازه‌های زمانی، شامل همه چیز از ایجاد مدت زمان پایه تا محاسبات و قالب‌بندی پیشرفته.

مدت زمان در جاوا اسکریپت تمپورال: تسلط بر محاسبات بازه‌های زمانی

Temporal API جاوا اسکریپت روشی مدرن و قدرتمند برای کار با تاریخ، زمان و بازه‌های زمانی معرفی می‌کند. شیء Temporal.Duration یک طول زمانی را نشان می‌دهد و رویکردی واضح و شهودی برای انجام محاسبات با بازه‌های زمانی فراهم می‌کند. این مقاله به جزئیات Temporal.Duration می‌پردازد و نشان می‌دهد چگونه می‌توان مدت زمان‌ها را برای کاربردهای مختلف ایجاد، دستکاری و قالب‌بندی کرد.

Temporal.Duration چیست؟

Temporal.Duration یک بازه زمانی را نشان می‌دهد و آن را بر حسب سال، ماه، روز، ساعت، دقیقه، ثانیه و کسری از ثانیه (میلی‌ثانیه، میکروثانیه، نانوثانیه) بیان می‌کند. برخلاف اشیاء Date که یک نقطه خاص در زمان را نشان می‌دهند، Temporal.Duration یک مقدار از زمان را نشان می‌دهد. این شیء از فرمت مدت زمان ISO 8601 پیروی می‌کند (به عنوان مثال، P1Y2M10DT2H30M نشان‌دهنده ۱ سال، ۲ ماه، ۱۰ روز، ۲ ساعت و ۳۰ دقیقه است). Temporal API طوری طراحی شده است که نسبت به شیء قدیمی Date شهودی‌تر و کمتر مستعد خطا باشد.

ایجاد اشیاء Temporal.Duration

چندین راه برای ایجاد اشیاء Temporal.Duration وجود دارد:

۱. از یک شیء ساده (Plain Object)

شما می‌توانید با پاس دادن یک شیء با ویژگی‌های مورد نظر، یک مدت زمان ایجاد کنید:

const duration = new Temporal.Duration(1, 2, 10, 2, 30, 0, 0, 0);
console.log(duration.toString()); // خروجی: P1Y2M10DT2H30M

این کد یک مدت زمان ۱ سال، ۲ ماه، ۱۰ روز، ۲ ساعت و ۳۰ دقیقه ایجاد می‌کند. توجه داشته باشید که آرگومان‌ها به ترتیب زیر هستند: years، months، weeks، days، hours، minutes، seconds، milliseconds، microseconds، nanoseconds.

۲. از یک رشته ISO 8601

شما همچنین می‌توانید با استفاده از Temporal.Duration.from() یک مدت زمان از روی یک رشته مدت زمان ISO 8601 ایجاد کنید:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.toString()); // خروجی: P1Y2M10DT2H30M

این روش به ویژه هنگام کار با مدت زمان‌هایی که به صورت رشته ذخیره شده‌اند یا از یک منبع خارجی دریافت شده‌اند، مفید است.

۳. استفاده از متدهای add() و subtract() با Temporal.Instant، Temporal.ZonedDateTime و غیره

وقتی شما Temporal.Duration را از دیگر انواع Temporal (مانند Temporal.Instant یا Temporal.ZonedDateTime) اضافه یا کم می‌کنید، و سپس آن‌ها را از هم کم می‌کنید، یک Temporal.Duration بازگردانده می‌شود که تفاوت بین دو نقطه زمانی را نشان می‌دهد. برای مثال:

const now = Temporal.Now.zonedDateTimeISO();
const later = now.add({ hours: 5 });
const duration = later.since(now);
console.log(duration.toString()); // خروجی: PT5H

دسترسی به اجزای مدت زمان

شما می‌توانید با استفاده از ویژگی‌های یک شیء Temporal.Duration به اجزای جداگانه آن دسترسی پیدا کنید:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.years);      // خروجی: 1
console.log(duration.months);     // خروجی: 2
console.log(duration.days);       // خروجی: 10
console.log(duration.hours);      // خروجی: 2
console.log(duration.minutes);     // خروجی: 30
console.log(duration.seconds);     // خروجی: 0
console.log(duration.milliseconds); // خروجی: 0
console.log(duration.microseconds); // خروجی: 0
console.log(duration.nanoseconds);  // خروجی: 0

انجام محاسبات با مدت زمان‌ها

اشیاء Temporal.Duration از جمع و تفریق با استفاده از متدهای add() و subtract() پشتیبانی می‌کنند. این متدها یک شیء Temporal.Duration جدید را که نتیجه عملیات است، بازمی‌گردانند.

const duration1 = Temporal.Duration.from("P1Y2M");
const duration2 = Temporal.Duration.from("P3M4D");

const addedDuration = duration1.add(duration2);
console.log(addedDuration.toString()); // خروجی: P1Y5M4D

const subtractedDuration = duration1.subtract(duration2);
console.log(subtractedDuration.toString()); // خروجی: P10M26D

شما همچنین می‌توانید این متدها را برای محاسبات پیچیده‌تر به صورت زنجیره‌ای استفاده کنید:

const duration = Temporal.Duration.from("P1D").add({ hours: 12 }).subtract({ minutes: 30 });
console.log(duration.toString()); // خروجی: P1DT11H30M

متد negated() یک شیء Temporal.Duration جدید با تمام اجزای منفی شده بازمی‌گرداند:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const negatedDuration = duration.negated();
console.log(negatedDuration.toString()); // خروجی: -P1Y2M10DT2H30M

متد abs() یک شیء Temporal.Duration جدید با تمام اجزا به صورت مقادیر مثبت (قدر مطلق) بازمی‌گرداند:

const duration = Temporal.Duration.from("-P1Y2M10DT2H30M");
const absoluteDuration = duration.abs();
console.log(absoluteDuration.toString()); // خروجی: P1Y2M10DT2H30M

متد with() به شما امکان می‌دهد یک نمونه Temporal.Duration جدید با برخی یا تمام ویژگی‌های تغییر یافته به مقادیر جدید ایجاد کنید. اگر مقداری در شیء آرگومان مشخص نشده باشد، از مقدار اصلی مدت زمان استفاده خواهد شد. برای مثال:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const newDuration = duration.with({ years: 2, days: 5 });
console.log(newDuration.toString()); // خروجی: P2Y2M5DT2H30M

نرمال‌سازی مدت زمان‌ها

مدت زمان‌ها گاهی اوقات می‌توانند به شکلی غیرنرمال بیان شوند (مثلاً P1Y12M که می‌تواند به P2Y ساده شود). متد normalized() تلاش می‌کند تا یک مدت زمان را به فشرده‌ترین شکل خود ساده کند. با این حال، برای مدیریت پیچیدگی‌های طول‌های متفاوت ماه‌ها، به یک تاریخ مرجع نیاز دارد. برای نرمال‌سازی صحیح، شما به یک نمونه Temporal.PlainDate، Temporal.ZonedDateTime یا Temporal.Instant نیاز دارید.

برای مثال، نرمال‌سازی یک مدت زمان شامل ماه‌ها و روزها به یک تاریخ مرجع نیاز دارد:

const duration = Temporal.Duration.from("P1M32D");
const referenceDate = Temporal.PlainDate.from("2024-01-01");
const normalizedDuration = duration.normalized({ relativeTo: referenceDate });
console.log(normalizedDuration.toString()); // خروجی: P2M1D

در این مثال، مدت زمان P1M32D نسبت به اول ژانویه ۲۰۲۴ نرمال‌سازی شده و به P2M1D تبدیل می‌شود، زیرا ژانویه ۳۱ روز دارد.

اگر فقط با اجزای زمانی (ساعت، دقیقه، ثانیه و غیره) کار می‌کنید، می‌توانید بدون تاریخ مرجع نرمال‌سازی کنید:

const duration = Temporal.Duration.from("PT25H61M");
const normalizedDuration = duration.normalized({ relativeTo: null }); //یا آرگومان relativeTo را حذف کنید
console.log(normalizedDuration.toString()); // خروجی: P1DT2H1M

مقایسه مدت زمان‌ها

شما می‌توانید با استفاده از متد compare() مدت زمان‌ها را مقایسه کنید. این متد بازمی‌گرداند:

const duration1 = Temporal.Duration.from("P1Y");
const duration2 = Temporal.Duration.from("P6M");

const comparisonResult = Temporal.Duration.compare(duration1, duration2);
console.log(comparisonResult); // خروجی: 1

مثال‌های کاربردی

۱. محاسبه زمان باقی‌مانده تا یک رویداد

فرض کنید می‌خواهید زمان باقی‌مانده تا یک رویداد خاص را محاسبه کنید. با استفاده از Temporal.Now.zonedDateTimeISO() برای دریافت زمان فعلی و کم کردن تاریخ رویداد. اگر تاریخ رویداد گذشته باشد، خروجی منفی خواهد بود.

const eventDate = Temporal.ZonedDateTime.from({ timeZone: 'America/Los_Angeles', year: 2024, month: 12, day: 25, hour: 9, minute: 0, second: 0 });
const now = Temporal.Now.zonedDateTimeISO('America/Los_Angeles');

const durationUntilEvent = eventDate.since(now);

console.log(durationUntilEvent.toString()); // خروجی: به عنوان مثال، P262DT14H30M (بسته به تاریخ و زمان فعلی)

۲. پیگیری مدت زمان وظایف پروژه

در مدیریت پروژه، می‌توانید از Temporal.Duration برای پیگیری مدت زمان تخمینی یا واقعی وظایف استفاده کنید.

const task1EstimatedDuration = Temporal.Duration.from("PT8H"); // ۸ ساعت
const task2EstimatedDuration = Temporal.Duration.from("PT16H"); // ۱۶ ساعت

const totalEstimatedDuration = task1EstimatedDuration.add(task2EstimatedDuration);
console.log(`مجموع مدت زمان تخمینی: ${totalEstimatedDuration.toString()}`); // خروجی: مجموع مدت زمان تخمینی: P1DT

۳. محاسبه سن

در حالی که محاسبه دقیق سن نیازمند در نظر گرفتن سال‌های کبیسه و مناطق زمانی است، Temporal.Duration می‌تواند تخمین معقولی ارائه دهد:

const birthDate = Temporal.PlainDate.from("1990-05-15");
const currentDate = Temporal.PlainDate.from("2024-01-20");

const ageDuration = currentDate.since(birthDate, { smallestUnit: 'years' });
console.log(`سن تخمینی: ${ageDuration.years} سال`); // خروجی: سن تخمینی: 33 سال

۴. نمایش مدت زمان‌ها به صورت خوانا برای انسان

اغلب، شما نیاز دارید مدت زمان‌ها را در یک قالب خوانا برای انسان نمایش دهید. در حالی که Temporal.Duration توابع قالب‌بندی داخلی ندارد، می‌توانید منطق قالب‌بندی سفارشی ایجاد کنید:

function formatDuration(duration) {
  const parts = [];
  if (duration.years) parts.push(`${duration.years} سال`);
  if (duration.months) parts.push(`${duration.months} ماه`);
  if (duration.days) parts.push(`${duration.days} روز`);
  if (duration.hours) parts.push(`${duration.hours} ساعت`);
  if (duration.minutes) parts.push(`${duration.minutes} دقیقه`);
  if (duration.seconds) parts.push(`${duration.seconds} ثانیه`);

  return parts.join('، ');
}

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const formattedDuration = formatDuration(duration);
console.log(formattedDuration); // خروجی: ۱ سال، ۲ ماه، ۱۰ روز، ۲ ساعت، ۳۰ دقیقه

استفاده پیشرفته و ملاحظات

۱. مدیریت منطقه زمانی

هنگام کار با بازه‌های زمانی که از مرزهای مناطق زمانی یا تغییرات ساعت تابستانی عبور می‌کنند، استفاده از Temporal.ZonedDateTime برای اطمینان از محاسبات دقیق بسیار مهم است. استفاده از Temporal.PlainDate و Temporal.PlainTime از هرگونه تبدیل منطقه زمانی جلوگیری می‌کند.

۲. کوچکترین واحد و گرد کردن

متدهای `since()` و `until()` اغلب گزینه‌هایی برای تعریف کوچکترین واحد برای مدت زمان نتیجه را می‌پذیرند. برای مثال، محاسبه زمان *تا* یک رویداد و محدود کردن نتایج به روز.

const eventDate = Temporal.PlainDate.from("2024-12-25");
const now = Temporal.PlainDate.from("2024-01-20");

const durationUntilEvent = now.until(eventDate, { smallestUnit: 'days' });

console.log(durationUntilEvent.toString()); //خروجی نمونه PT340D

۳. ثانیه‌های کبیسه

Temporal به طور ذاتی ثانیه‌های کبیسه را در نظر نمی‌گیرد. اگر به دقت بسیار بالایی نیاز دارید، باید ثانیه‌های کبیسه را به طور جداگانه مدیریت کنید.

۴. مناطق زمانی IANA

Temporal API به پایگاه داده مناطق زمانی IANA (Internet Assigned Numbers Authority) متکی است. اطمینان حاصل کنید که محیط شما نسخه به‌روزی از پایگاه داده IANA را برای مدیریت دقیق تبدیل‌های منطقه زمانی دارد.

بهترین شیوه‌ها

اشتباهات رایج

موارد استفاده واقعی در فرهنگ‌های مختلف

Temporal API می‌تواند به ویژه در برنامه‌های جهانی که تفاوت‌های منطقه زمانی و ظرافت‌های فرهنگی قابل توجه هستند، مفید باشد. در اینجا چند نمونه آورده شده است:

نتیجه‌گیری

Temporal.Duration روشی قوی و شهودی برای کار با بازه‌های زمانی در جاوا اسکریپت فراهم می‌کند. با درک ویژگی‌ها و بهترین شیوه‌های آن، می‌توانید با اطمینان محاسبات مدت زمان دقیق و قابل اعتمادی را در برنامه‌های خود انجام دهید. پذیرش Temporal API منجر به کدی تمیزتر، قابل نگهداری‌تر و کاهش خطر خطاهای مرتبط با مدیریت تاریخ و زمان قدیمی می‌شود.

همانطور که عمیق‌تر به Temporal API می‌پردازید، به یاد داشته باشید که به مستندات رسمی مراجعه کرده و با سناریوهای مختلف آزمایش کنید تا به طور کامل قابلیت‌های آن را درک کنید. با طراحی مدرن و ویژگی‌های جامع خود، Temporal قرار است روش کار ما با تاریخ‌ها، زمان‌ها و مدت زمان‌ها در جاوا اسکریپت را متحول کند.