Українська

Вичерпний посібник з використання JavaScript Temporal API для точних та інтуїтивно зрозумілих обчислень часових інтервалів, що охоплює все: від створення базової тривалості до розширеної арифметики та форматування.

JavaScript Temporal Duration: Освоєння обчислень часових інтервалів

JavaScript Temporal API представляє сучасний і потужний спосіб обробки дат, часу та часових інтервалів. Об'єкт Temporal.Duration представляє проміжок часу, надаючи чіткий та інтуїтивно зрозумілий підхід до виконання обчислень з часовими інтервалами. Ця стаття заглиблюється в деталі Temporal.Duration, демонструючи, як створювати, маніпулювати та форматувати тривалості для різних випадків використання.

Що таке Temporal.Duration?

Temporal.Duration представляє проміжок часу, виражаючи його в термінах років, місяців, днів, годин, хвилин, секунд і часток секунди (мілісекунди, мікросекунди, наносекунди). На відміну від об’єктів Date, які представляють конкретний момент часу, Temporal.Duration представляє проміжок часу. Він відповідає формату тривалості ISO 8601 (наприклад, P1Y2M10DT2H30M представляє 1 рік, 2 місяці, 10 днів, 2 години та 30 хвилин). Temporal API розроблено так, щоб бути більш інтуїтивно зрозумілим і менш схильним до помилок, ніж застарілий об’єкт Date.

Створення об’єктів Temporal.Duration

Існує кілька способів створення об’єктів Temporal.Duration:

1. Зі звичайного об’єкта

Ви можете створити тривалість, передавши об’єкт із потрібними властивостями:

const duration = new Temporal.Duration(1, 2, 10, 2, 30, 0, 0, 0);
console.log(duration.toString()); // Output: P1Y2M10DT2H30M

Це створює тривалість в 1 рік, 2 місяці, 10 днів, 2 години та 30 хвилин. Зауважте, що аргументи відповідають наступному порядку: years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds.

2. Зі строки ISO 8601

Ви також можете створити тривалість зі строки тривалості ISO 8601 за допомогою Temporal.Duration.from():

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.toString()); // Output: P1Y2M10DT2H30M

Це особливо корисно під час роботи з тривалостями, що зберігаються у форматі строки або отримані із зовнішнього джерела.

3. Використання методів 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()); // Output: PT5H

Доступ до компонентів тривалості

Ви можете отримати доступ до окремих компонентів об’єкта Temporal.Duration за допомогою його властивостей:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
console.log(duration.years);      // Output: 1
console.log(duration.months);     // Output: 2
console.log(duration.days);       // Output: 10
console.log(duration.hours);      // Output: 2
console.log(duration.minutes);     // Output: 30
console.log(duration.seconds);     // Output: 0
console.log(duration.milliseconds); // Output: 0
console.log(duration.microseconds); // Output: 0
console.log(duration.nanoseconds);  // Output: 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()); // Output: P1Y5M4D

const subtractedDuration = duration1.subtract(duration2);
console.log(subtractedDuration.toString()); // Output: P10M26D

Ви також можете об’єднувати ці методи в ланцюжок для складніших обчислень:

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

Метод negated() повертає новий об’єкт Temporal.Duration з усіма компонентами, зміненими на протилежні:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const negatedDuration = duration.negated();
console.log(negatedDuration.toString()); // Output: -P1Y2M10DT2H30M

Метод abs() повертає новий об’єкт Temporal.Duration з усіма компонентами як додатні значення (абсолютні значення):

const duration = Temporal.Duration.from("-P1Y2M10DT2H30M");
const absoluteDuration = duration.abs();
console.log(absoluteDuration.toString()); // Output: P1Y2M10DT2H30M

Метод with() дозволяє створити новий екземпляр Temporal.Duration з деякими або всіма властивостями, зміненими на нові значення. Якщо значення не вказано в об’єкті аргументу, буде використано початкове значення тривалості. Наприклад:

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const newDuration = duration.with({ years: 2, days: 5 });
console.log(newDuration.toString()); // Output: 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()); // Output: P2M1D

У цьому прикладі тривалість P1M32D нормалізується відносно 1 січня 2024 року, що призводить до P2M1D, оскільки січень має 31 день.

Якщо ви маєте справу лише з компонентами часу (години, хвилини, секунди тощо), ви можете нормалізувати без дати посилання:

const duration = Temporal.Duration.from("PT25H61M");
const normalizedDuration = duration.normalized({ relativeTo: null }); //or omit relativeTo argument
console.log(normalizedDuration.toString()); // Output: P1DT2H1M

Порівняння тривалостей

Ви можете порівнювати тривалості за допомогою методу compare(). Цей метод повертає:

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

const comparisonResult = Temporal.Duration.compare(duration1, duration2);
console.log(comparisonResult); // Output: 1

Практичні приклади

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()); // Output: e.g., P262DT14H30M (залежно від поточної дати та часу)

2. Відстеження тривалості завдань проекту

В управлінні проектами ви можете використовувати Temporal.Duration для відстеження оціночної або фактичної тривалості завдань.

const task1EstimatedDuration = Temporal.Duration.from("PT8H"); // 8 hours
const task2EstimatedDuration = Temporal.Duration.from("PT16H"); // 16 hours

const totalEstimatedDuration = task1EstimatedDuration.add(task2EstimatedDuration);
console.log(`Total estimated duration: ${totalEstimatedDuration.toString()}`); // Output: Total estimated duration: P1DT

3. Обчислення віку

Хоча точне обчислення віку вимагає врахування високосних років і часових поясів, 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(`Estimated age: ${ageDuration.years} years`); // Output: Estimated age: 33 years

4. Відображення тривалості, зрозумілої для людини

Часто вам потрібно відображати тривалість у зрозумілому для людини форматі. Хоча Temporal.Duration не має вбудованих функцій форматування, ви можете створити власну логіку форматування:

function formatDuration(duration) {
  const parts = [];
  if (duration.years) parts.push(`${duration.years} year${duration.years > 1 ? 's' : ''}`);
  if (duration.months) parts.push(`${duration.months} month${duration.months > 1 ? 's' : ''}`);
  if (duration.days) parts.push(`${duration.days} day${duration.days > 1 ? 's' : ''}`);
  if (duration.hours) parts.push(`${duration.hours} hour${duration.hours > 1 ? 's' : ''}`);
  if (duration.minutes) parts.push(`${duration.minutes} minute${duration.minutes > 1 ? 's' : ''}`);
  if (duration.seconds) parts.push(`${duration.seconds} second${duration.seconds > 1 ? 's' : ''}`);

  return parts.join(', ');
}

const duration = Temporal.Duration.from("P1Y2M10DT2H30M");
const formattedDuration = formatDuration(duration);
console.log(formattedDuration); // Output: 1 year, 2 months, 10 days, 2 hours, 30 minutes

Розширене використання та міркування

1. Обробка часових поясів

Під час роботи з часовими інтервалами, які перетинають межі часових поясів або перехід на літній час, важливо використовувати Temporal.ZonedDateTime, щоб забезпечити точні обчислення. Використання Temporal.PlainDate і Temporal.PlainTime дозволить уникнути будь-яких перетворень часових поясів.

2. Найменша одиниця та заокруглення

Методи `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()); //example output PT340D

3. Високосні секунди

Temporal не враховує високосні секунди. Якщо вам потрібна надзвичайна точність, вам потрібно буде обробляти високосні секунди окремо.

4. Часові пояси IANA

Temporal API покладається на базу даних часових поясів IANA (Internet Assigned Numbers Authority). Переконайтеся, що у вашому середовищі є актуальна версія бази даних IANA для точної обробки перетворень часових поясів.

Кращі практики

Поширені помилки

Реальні випадки використання в різних культурах

Temporal API може бути особливо корисним у глобальних програмах, де різниця в часових поясах і культурні нюанси є значними. Ось кілька прикладів:

Висновок

Temporal.Duration надає надійний та інтуїтивно зрозумілий спосіб роботи з часовими інтервалами в JavaScript. Розуміючи його функції та найкращі практики, ви можете впевнено виконувати точні та надійні обчислення тривалості у своїх програмах. Використання Temporal API призводить до чистішого, більш підтримуваного коду та зменшує ризик помилок, пов’язаних із застарілою обробкою дат і часу.

Поглиблюючись у Temporal API, не забувайте звертатися до офіційної документації та експериментувати з різними сценаріями, щоб повністю зрозуміти його можливості. Завдяки сучасному дизайну та всеосяжним функціям Temporal готовий революціонізувати спосіб обробки дат, часу та тривалості в JavaScript.