Български

Изчерпателно ръководство за използване на Temporal API на JavaScript за точни и интуитивни изчисления на времеви интервали, обхващащо всичко от основно създаване на продължителност до разширена аритметика и форматиране.

JavaScript Temporal Duration: Овладяване на изчисленията на времеви интервали

Temporal API на JavaScript въвежда модерен и мощен начин за работа с дати, часове и времеви интервали. Обектът 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.