Глибоке занурення в Temporal API JavaScript для перетворення календарів, що забезпечує точне відображення дат між різними календарними системами. Навчіться працювати з датами в ісламському, єврейському, буддійському та інших календарях.
Перетворення календарів за допомогою JavaScript Temporal: Опанування між-календарного відображення дат
Світ живе не лише за григоріанським календарем. Компанії, що розширюються на світовий ринок, повинні враховувати різноманітні культурні та релігійні традиції, кожна з яких пов'язана з певними календарними системами. Сучасний Temporal API у JavaScript надає потужні інструменти для роботи з цими складнощами, дозволяючи розробникам безперешкодно відображати дати між календарями та забезпечувати точне планування, обчислення та представлення даних. Цей вичерпний посібник досліджує можливості перетворення календарів у Temporal API, пропонуючи практичні приклади та найкращі практики для створення глобально орієнтованих застосунків.
Розуміння потреби у між-календарному відображенні дат
Традиційні об'єкти `Date` в JavaScript мають обмеження в роботі з негригоріанськими календарями. Temporal API вирішує цю проблему, надаючи стандартизований і надійний спосіб роботи з різними календарними системами. Розглянемо такі сценарії:
- Планування міжнародних зустрічей: Точне визначення еквівалентної дати в ісламському (хіджри) або єврейському календарі для події, запланованої за григоріанським календарем, є надзвичайно важливим для поваги до релігійних свят та культурних особливостей.
- Розрахунок відсотків за кредитом у різних регіонах: Деякі фінансові установи використовують специфічні календарі для розрахунку відсотків. Temporal дозволяє виконувати точні арифметичні операції з датами в цих системах.
- Відображення дат у форматах, зручних для користувача: Адаптація відображення дат до локалі та календарних уподобань користувача покращує користувацький досвід, особливо для застосунків, орієнтованих на різноманітну аудиторію.
- Аналіз історичних даних: Під час роботи з історичними наборами даних розуміння та перетворення дат, записаних у старих або менш поширених календарях, стає необхідним для їх точної інтерпретації.
Знайомство з Temporal API та календарями
Temporal API, що зараз широко підтримується в сучасних середовищах JavaScript, пропонує більш інтуїтивно зрозумілий і потужний спосіб роботи з датами, часом та часовими поясами. В його основі лежить об'єкт `Temporal.Calendar`, що представляє певну календарну систему. Temporal.PlainDate, Temporal.PlainDateTime та інші типи Temporal можуть бути пов'язані з екземпляром `Temporal.Calendar`.
На момент написання цієї статті Temporal API підтримує такі календарі:
- `iso8601` (Григоріанський - за замовчуванням)
- `gregory` (псевдонім для `iso8601`)
- `islamic`
- `islamic-umalqura`
- `islamic-tbla`
- `islamic-rgsa`
- `islamic-civil`
- `hebrew`
- `buddhist`
- `roc` (Календар Китайської Республіки)
- `japanese`
- `persian`
У майбутніх версіях можуть бути додані нові календарі або можливість реалізації власних календарів.
Базове перетворення календарів за допомогою Temporal.PlainDate
Об'єкт `Temporal.PlainDate` представляє дату без часового поясу. Ви можете створити `Temporal.PlainDate`, пов'язаний з певним календарем:
const gregorianDate = Temporal.PlainDate.from('2024-01-20');
const islamicCalendar = Temporal.Calendar.from('islamic');
const islamicDate = Temporal.PlainDate.from({ year: 1445, month: 6, day: 8, calendar: islamicCalendar });
console.log(gregorianDate.toString()); // Output: 2024-01-20
console.log(islamicDate.toString()); // Output: 1445-06-08[u-ca=islamic]
Метод `toString()` виведе дату з анотацією календаря `[u-ca=islamic]`. Це вказує, що дата пов'язана з ісламським календарем.
Перетворення між календарями
Ключ до перетворення між календарями полягає у створенні об'єктів `Temporal.PlainDate`, пов'язаних з кожним календарем, а потім вилученні відповідних компонентів дати. Ось як перетворити григоріанську дату на її еквівалент в ісламському календарі:
const gregorianDate = Temporal.PlainDate.from('2024-01-20');
const islamicCalendar = Temporal.Calendar.from('islamic');
// Вилучення компонентів дати в ісламському календарі
const islamicYear = gregorianDate.toPlainDate(islamicCalendar).year;
const islamicMonth = gregorianDate.toPlainDate(islamicCalendar).month;
const islamicDay = gregorianDate.toPlainDate(islamicCalendar).day;
console.log(`Gregorian: ${gregorianDate.toString()}`);
console.log(`Islamic: ${islamicYear}-${islamicMonth}-${islamicDay}`); // Output: Islamic: 1445-6-8
Розберемо цей приклад:
- Ми починаємо з `gregorianDate`, представленої як об'єкт `Temporal.PlainDate`.
- Ми створюємо об'єкт `islamicCalendar` за допомогою `Temporal.Calendar.from('islamic')`.
- Основне перетворення відбувається за допомогою `gregorianDate.toPlainDate(islamicCalendar)`. Це створює новий об'єкт `Temporal.PlainDate`, що представляє той самий момент часу, але тепер пов'язаний з ісламським календарем.
- Ми вилучаємо компоненти `year`, `month` та `day` з перетвореного об'єкта `Temporal.PlainDate`.
Ви можете адаптувати цей шаблон для перетворення між будь-якими двома календарями, що підтримуються Temporal API.
Розширена робота з календарями: Ісламські календарі
Ісламський календар має кілька варіацій. Temporal API підтримує наступні:
- `islamic`: Загальний ісламський календар (реалізація може відрізнятися).
- `islamic-umalqura`: Базується на календарі Умм аль-Кура в Саудівській Аравії.
- `islamic-tbla`: Базується на табличних розрахунках.
- `islamic-rgsa`: Базується на даних Головного релігійного секретаріату вакфів (Єгипет).
- `islamic-civil`: Чисто арифметична версія ісламського календаря, що використовується переважно для обчислень.
Працюючи з ісламським календарем, важливо розуміти, яка варіація підходить для вашого випадку. Наприклад, для релігійних свят у Саудівській Аравії, ви, ймовірно, захочете використовувати `islamic-umalqura`. Для фінансових розрахунків `islamic-civil` може бути більш доречним через свою передбачуваність.
const gregorianDate = Temporal.PlainDate.from('2024-03-11');
const islamicUmalquraCalendar = Temporal.Calendar.from('islamic-umalqura');
const islamicCivilCalendar = Temporal.Calendar.from('islamic-civil');
const islamicUmalquraDate = gregorianDate.toPlainDate(islamicUmalquraCalendar);
const islamicCivilDate = gregorianDate.toPlainDate(islamicCivilCalendar);
console.log(`Gregorian: ${gregorianDate.toString()}`);
console.log(`Islamic (Umm al-Qura): ${islamicUmalquraDate.year}-${islamicUmalquraDate.month}-${islamicUmalquraDate.day}`);
console.log(`Islamic (Civil): ${islamicCivilDate.year}-${islamicCivilDate.month}-${islamicCivilDate.day}`);
Важливі зауваження щодо ісламських календарів:
- Початок нового місяця в ісламському календарі базується на спостереженні за молодим місяцем. Календар `islamic-umalqura` намагається відповідати реальним спостереженням за місяцем у Саудівській Аравії, але розбіжності все ж можуть виникати.
- Календар `islamic-civil` є математичним наближенням і не відображає реальних спостережень за місяцем.
- Завжди консультуйтеся з відповідними релігійними авторитетами або надійними джерелами для отримання точних дат ісламських свят.
Робота з єврейським календарем
Єврейський календар — це місячно-сонячний календар, що використовується для єврейських релігійних обрядів та як офіційний календар в Ізраїлі. Він включає високосні місяці, щоб узгоджуватися з порами року.
const gregorianDate = Temporal.PlainDate.from('2024-03-11');
const hebrewCalendar = Temporal.Calendar.from('hebrew');
const hebrewDate = gregorianDate.toPlainDate(hebrewCalendar);
console.log(`Gregorian: ${gregorianDate.toString()}`);
console.log(`Hebrew: ${hebrewDate.year}-${hebrewDate.month}-${hebrewDate.day}`);
Ключові особливості єврейського календаря та Temporal:
- Високосні місяці автоматично обробляються Temporal API. Вам не потрібно реалізовувати власну логіку для визначення високосних років або додавання додаткових місяців.
- Нумерація років починається з традиційної єврейської епохи (створення світу).
- Назви місяців у єврейському календарі відрізняються від григоріанського. Ви можете отримати доступ до цих назв через бібліотеки інтернаціоналізації (i18n) або власні відповідності.
Робота з буддійським, китайським (ROC), японським та перським календарями
Temporal API також підтримує інші календарі, кожен зі своїми особливостями. Ось деякі з них:
- Буддійський календар: Це місячно-сонячний календар, що використовується в багатьох країнах Південно-Східної Азії. Нумерація років зазвичай починається від дати смерті Будди.
- Календар ROC (Китайська Республіка): Цей календар використовується на Тайвані, а роки нумеруються від заснування Китайської Республіки в 1912 році.
- Японський календар: Японський календар базується на григоріанському, але використовує назви японських ер (ненґо) для позначення років.
- Перський календар: Перський календар — це сонячний календар, що використовується переважно в Ірані та Афганістані.
const gregorianDate = Temporal.PlainDate.from('2024-03-11');
const buddhistCalendar = Temporal.Calendar.from('buddhist');
const rocCalendar = Temporal.Calendar.from('roc');
const japaneseCalendar = Temporal.Calendar.from('japanese');
const persianCalendar = Temporal.Calendar.from('persian');
const buddhistDate = gregorianDate.toPlainDate(buddhistCalendar);
const rocDate = gregorianDate.toPlainDate(rocCalendar);
const japaneseDate = gregorianDate.toPlainDate(japaneseCalendar);
const persianDate = gregorianDate.toPlainDate(persianCalendar);
console.log(`Gregorian: ${gregorianDate.toString()}`);
console.log(`Buddhist: ${buddhistDate.year}-${buddhistDate.month}-${buddhistDate.day}`);
console.log(`ROC: ${rocDate.year}-${rocDate.month}-${rocDate.day}`);
console.log(`Japanese: ${japaneseDate.year}-${japaneseDate.month}-${japaneseDate.day}`);
console.log(`Persian: ${persianDate.year}-${persianDate.month}-${persianDate.day}`);
Використовуючи ці календарі, пам'ятайте про їхню специфічну епоху (початковий рік) та будь-які культурні нюанси, пов'язані з представленням дати.
Temporal.Now та особливості календарів
Хоча `Temporal.Now` можна використовувати для отримання поточної дати та часу, важливо розуміти, що за замовчуванням він повертає поточну дату і час у календарі ISO 8601. Якщо вам потрібна поточна дата в іншому календарі, її потрібно буде перетворити:
const islamicCalendar = Temporal.Calendar.from('islamic');
const now = Temporal.Now.plainDateISO(); // Поточна дата в календарі ISO 8601
const islamicNow = now.toPlainDate(islamicCalendar);
console.log(`Current Gregorian Date: ${now.toString()}`);
console.log(`Current Islamic Date: ${islamicNow.year}-${islamicNow.month}-${islamicNow.day}`);
Форматування дат та інтернаціоналізація (i18n)
Перетворення дат — це лише частина рівняння. Вам також потрібно правильно їх форматувати для відображення. API `Intl.DateTimeFormat` у JavaScript надає потужні можливості інтернаціоналізації. Ви можете використовувати його разом з Temporal API для форматування дат з урахуванням локалі та пов'язаного календаря.
const gregorianDate = Temporal.PlainDate.from('2024-01-20');
const islamicCalendar = Temporal.Calendar.from('islamic');
const islamicDate = gregorianDate.toPlainDate(islamicCalendar);
const formatter = new Intl.DateTimeFormat('ar-SA-u-ca-islamic', { // Арабська (Саудівська Аравія) з ісламським календарем
year: 'numeric',
month: 'long',
day: 'numeric',
});
console.log(formatter.format(islamicDate)); // Приклад виводу: ٢٠ رجب، ١٤٤٥ هـ
Проаналізуємо код:
- `'ar-SA-u-ca-islamic'` — це рядок локалі. `ar-SA` вказує на арабську мову (Саудівська Аравія), а `u-ca-islamic` явно запитує ісламський календар.
- Опції `Intl.DateTimeFormat` контролюють спосіб форматування дати (рік, місяць, день).
- Метод `format()` приймає об'єкт `Temporal.PlainDate` (у даному випадку `islamicDate`) і повертає відформатований рядок відповідно до вказаної локалі та календаря.
Ви можете адаптувати рядок локалі та опції форматування відповідно до ваших потреб. Наприклад, для форматування дати єврейською мовою:
const gregorianDate = Temporal.PlainDate.from('2024-03-11');
const hebrewCalendar = Temporal.Calendar.from('hebrew');
const hebrewDate = gregorianDate.toPlainDate(hebrewCalendar);
const formatter = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', { // Іврит (Ізраїль) з єврейським календарем
year: 'numeric',
month: 'long',
day: 'numeric',
});
console.log(formatter.format(hebrewDate));
Поради для ефективного форматування дат:
- Використовуйте рядки локалі, які точно відображають бажану мову та регіон користувача.
- Обирайте опції форматування, які відповідають контексту (наприклад, короткі формати дат для компактного відображення, довгі — для детального представлення).
- Тестуйте форматування для різних локалей, щоб забезпечити точність та читабельність.
Виконання арифметичних операцій з датами між календарями
Temporal API чудово справляється з арифметикою дат. Ви можете додавати або віднімати дні, місяці чи роки від об'єкта `Temporal.PlainDate`, навіть працюючи з негригоріанськими календарями.
const gregorianDate = Temporal.PlainDate.from('2024-01-20');
const islamicCalendar = Temporal.Calendar.from('islamic');
const islamicDate = gregorianDate.toPlainDate(islamicCalendar);
// Додати 30 днів до ісламської дати
const futureIslamicDate = islamicDate.add({ days: 30 });
console.log(`Original Islamic Date: ${islamicDate.year}-${islamicDate.month}-${islamicDate.day}`);
console.log(`Islamic Date + 30 days: ${futureIslamicDate.year}-${futureIslamicDate.month}-${futureIslamicDate.day}`);
// Перетворити майбутню ісламську дату назад у григоріанську
const futureGregorianDate = futureIslamicDate.toPlainDate('iso8601');
console.log(`Equivalent Gregorian Date: ${futureGregorianDate.toString()}`);
Ключові аспекти арифметики дат:
- Методи `add()` та `subtract()` повертають нові об'єкти `Temporal.PlainDate`; вони не змінюють вихідний об'єкт.
- При додаванні або відніманні місяців чи років Temporal API враховує специфічні для календаря правила щодо високосних років та тривалості місяців.
- Пам'ятайте про можливі переповнення дати під час виконання арифметичних операцій. Temporal API зазвичай коригує дату до найближчої дійсної дати в межах календаря.
Обробка неоднозначних дат
У деяких випадках дата може бути неоднозначною при перетворенні між календарями. Це може статися, коли певна дата не існує в цільовому календарі або коли кілька дат у цільовому календарі можуть відповідати вихідній даті. Temporal обробляє такі ситуації коректно, зазвичай повертаючи найближчу дійсну дату.
Наприклад, розглянемо перетворення григоріанської дати наприкінці григоріанського місяця в ісламський календар, де відповідний ісламський місяць може бути коротшим. Temporal автоматично скоригує отриману ісламську дату до останнього дня цього місяця.
Обробка помилок та валідація
Хоча Temporal API є надійним, важливо реалізувати належну обробку помилок та валідацію для запобігання несподіваній поведінці. Ось деякі поширені сценарії, які варто враховувати:
- Неправильні назви календарів: Якщо ви надасте неправильну назву календаря в `Temporal.Calendar.from()`, буде згенеровано помилку `RangeError`. Перехоплюйте цю помилку та надавайте зрозуміле повідомлення користувачеві.
- Неправильні формати дат: Якщо ви спробуєте створити `Temporal.PlainDate` з недійсного рядка дати, буде згенеровано `RangeError`. Перевіряйте рядки дат перед передачею їх до `Temporal.PlainDate.from()`.
- Непідтримувані операції: Деякі специфічні для календаря операції можуть не підтримуватися Temporal API. Перевіряйте документацію для конкретного календаря, який ви використовуєте.
Найкращі практики для між-календарного відображення дат
Щоб забезпечити точність та зручність підтримки при роботі з між-календарним відображенням дат, дотримуйтесь цих найкращих практик:
- Використовуйте Temporal API: Temporal API надає стандартизований та надійний спосіб для перетворення календарів. Уникайте використання застарілих об'єктів `Date` JavaScript для цієї мети.
- Вказуйте календарі явно: Завжди явно вказуйте календар при створенні об'єктів `Temporal.PlainDate`. Це запобігає неоднозначності та гарантує застосування правильних календарних правил.
- Обирайте правильну варіацію ісламського календаря: Розумійте відмінності між різними реалізаціями ісламського календаря та обирайте ту, яка найбільше підходить для вашого випадку.
- Використовуйте інтернаціоналізацію (i18n): Використовуйте API `Intl.DateTimeFormat` для форматування дат з урахуванням локалі.
- Реалізуйте обробку помилок: Впроваджуйте надійну обробку помилок для перехоплення недійсних назв календарів, форматів дат та інших потенційних проблем.
- Ретельно тестуйте: Тестуйте свій код з різноманітними датами та локалями, щоб забезпечити точність та сумісність.
- Будьте в курсі оновлень: Temporal API все ще розвивається. Слідкуйте за останніми специфікаціями та реалізаціями в браузерах.
Висновок
Temporal API в JavaScript революціонізує спосіб роботи з датами та календарями, надаючи потужний та стандартизований метод для між-календарного відображення дат. Розуміючи нюанси різних календарних систем та ефективно використовуючи Temporal API, розробники можуть створювати глобально орієнтовані застосунки, що відповідають різноманітним культурним та релігійним потребам. Використовуйте Temporal API для створення більш інклюзивних та точних рішень для роботи з датами у ваших проєктах.
Цей посібник надав вичерпний огляд перетворення календарів за допомогою JavaScript Temporal API. Не забувайте звертатися до офіційної документації Temporal API для отримання найактуальнішої інформації та детальних специфікацій.