Вичерпний посібник з використання 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()
. Цей метод повертає:
- -1, якщо перша тривалість коротша за другу тривалість.
- 0, якщо тривалості рівні.
- 1, якщо перша тривалість довша за другу тривалість.
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 для точної обробки перетворень часових поясів.
Кращі практики
- Використовуйте формат ISO 8601 для строк тривалості: це забезпечує узгодженість і сумісність.
- Виберіть відповідний тип Temporal: використовуйте
Temporal.PlainDate
,Temporal.PlainTime
,Temporal.ZonedDateTime
абоTemporal.Instant
залежно від того, чи потрібна вам підтримка часових поясів чи ні. - Нормалізуйте тривалість, коли це необхідно: нормалізація спрощує тривалість і полегшує їх порівняння.
- Обережно обробляйте часові пояси: перетворення часових поясів можуть бути складними, тому використовуйте
Temporal.ZonedDateTime
і пам’ятайте про перехід на літній час. - Враховуйте найменшу одиницю: під час обчислення тривалості вкажіть найменшу одиницю, щоб отримати бажаний рівень точності.
- Пишіть юніт-тести: ретельно перевіряйте свій код, щоб переконатися, що обчислення тривалості є точними.
Поширені помилки
- Ігнорування часових поясів: неврахування часових поясів може призвести до неправильних обчислень тривалості, особливо під час роботи з подіями в різних місцях.
- Використання застарілого об’єкта Date: застарілий об’єкт
Date
відомий своїми дивацтвами та непослідовностями. Віддавайте перевагу Temporal API для більш надійної обробки дат і часу. - Не нормалізація тривалості: не нормалізація тривалості може ускладнити порівняння та обчислення.
- Неправильний формат ISO 8601: використання недійсної строки тривалості ISO 8601 може спричинити помилки.
Реальні випадки використання в різних культурах
Temporal API може бути особливо корисним у глобальних програмах, де різниця в часових поясах і культурні нюанси є значними. Ось кілька прикладів:
- Глобальне планування подій: точне планування подій у кількох часових поясах з урахуванням переходу на літній час. Наприклад, планування вебінару, який починається о 9:00 ранку за тихоокеанським часом, і відображення відповідного часу початку в різних часових поясах, таких як CET, JST і AEDT.
- Планування міжнародних подорожей: обчислення тривалості подорожей, включаючи пересадки та зміни часових поясів. Це корисно для створення маршрутів і керування розкладом рейсів. Наприклад, обчислення загального часу подорожі з Нью-Йорка до Токіо, включаючи пересадку в Лондоні та коригування різниці в часових поясах.
- Глобальна електронна комерція: відображення орієнтовного часу доставки в місцевому часовому поясі користувача. Це вимагає врахування часового поясу походження, тривалості доставки та часового поясу призначення. Наприклад, товар, відправлений зі складу в Німеччині клієнту в Австралії, з орієнтовним часом доставки 7 днів, відображається в місцевому часі клієнта.
- Транскордонні фінансові операції: точний розрахунок нарахування відсотків або термінів сплати в різних регіонах. Це часто передбачає врахування різних робочих днів і свят у кожній країні. Наприклад, обчислення відсотків, нарахованих за кредитом у Сінгапурі, з урахуванням державних свят Сінгапуру.
- Мультикультурні календарні програми: підтримка різних календарних систем, таких як ісламський або єврейський календар, і точний розрахунок тривалості подій і нагадувань на основі цих календарів.
- Глобальне управління проектами: відстеження тривалості завдань проекту та термінів виконання розподіленими командами з урахуванням різних графіків роботи та часових поясів.
Висновок
Temporal.Duration
надає надійний та інтуїтивно зрозумілий спосіб роботи з часовими інтервалами в JavaScript. Розуміючи його функції та найкращі практики, ви можете впевнено виконувати точні та надійні обчислення тривалості у своїх програмах. Використання Temporal API призводить до чистішого, більш підтримуваного коду та зменшує ризик помилок, пов’язаних із застарілою обробкою дат і часу.
Поглиблюючись у Temporal API, не забувайте звертатися до офіційної документації та експериментувати з різними сценаріями, щоб повністю зрозуміти його можливості. Завдяки сучасному дизайну та всеосяжним функціям Temporal готовий революціонізувати спосіб обробки дат, часу та тривалості в JavaScript.