Перейти до основного вмісту

Робота з датами та часом в Elixir

Elixir має вбудовані типи та модулі для роботи з датами, часом і часовими інтервалами. Основними модулями є Date, Time, NaiveDateTime, DateTime та Calendar.

Важливо розуміти різницю між ними. Date описує календарну дату, Time — час доби, NaiveDateTime — дату й час без інформації про часовий пояс, а DateTime — дату й час разом із часовим поясом.

У порівнянні з Java це приблизно відповідає класам LocalDate, LocalTime, LocalDateTime та ZonedDateTime з пакета java.time.

Дата за допомогою Date

Для представлення календарної дати використовується структура Date:

date = ~D[2026-08-21] date.year # 2026 date.month # 8 date.day # 21

Літерал ~D є sigil, спеціальним синтаксисом Elixir для створення дати.

Дата також може бути створена за допомогою функції Date.new/3:

{:ok, date} = Date.new(2026, 8, 21) date # ~D[2026-08-21]

Якщо передати некоректну дату, функція поверне помилку:

Date.new(2026, 2, 30) # {:error, :invalid_date}

Поточна дата

Поточну дату можна отримати за допомогою Date.utc_today/0:

date = Date.utc_today() IO.inspect(date) # ~D[2026-08-21]

Це аналогічно використанню LocalDate.now() у Java, хоча в Elixir явно вказано, що використовується UTC.

Час за допомогою Time

Тип Time використовується для представлення часу доби без дати та часового поясу:

time = ~T[14:30:00] time.hour # 14 
time.minute # 30 time.second # 0

Час можна створити через Time.new/3 або Time.new/4, якщо потрібно вказати мікросекунди:

{:ok, time} = Time.new(14, 30, 15) 
time # ~T[14:30:15]

Поточний час у UTC можна отримати за допомогою Time.utc_now/0:

time = Time.utc_now() 
IO.inspect(time) # ~T[08:42:17.123456]

NaiveDateTime

NaiveDateTime поєднує дату та час, але не містить інформації про часовий пояс. Назва Naive якраз підкреслює, що це "наївна" дата-часова величина.

datetime = ~N[2026-08-21 14:30:00] datetime.year # 2026 
datetime.month # 8 
datetime.day # 21 
datetime.hour # 14

Наприклад, значення ~N[2026-08-21 14:30:00] саме по собі не говорить, чи це 14:30 у Києві, Лондоні, Нью-Йорку чи іншому часовому поясі.

Приблизним аналогом у Java є LocalDateTime.

Коли використовувати NaiveDateTime

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

meeting = ~N[2026-09-01 10:00:00]

Однак для подій, які відбуваються в конкретний момент часу у світі, наприклад для платежів, логів або моменту створення запису, зазвичай краще використовувати DateTime та UTC.

DateTime

DateTime використовується для представлення конкретної дати та часу з урахуванням часового поясу.

datetime = DateTime.utc_now() IO.inspect(datetime)

Результат може виглядати приблизно так:

~U[2026-08-21 08:45:12.123456Z]

Символ Z означає UTC.

Для створення UTC-дати можна використовувати sigil ~U:

datetime = ~U[2026-08-21 12:30:00Z]

У Java найближчим аналогом буде Instant або ZonedDateTime, залежно від того, чи потрібно зберігати лише момент часу, чи також часову зону.

Часові пояси

Одна з важливих відмінностей між NaiveDateTime і DateTime полягає саме в часовому поясі.

Наприклад, один і той самий момент часу можна представити в UTC та в часовому поясі Europe/Kyiv:

utc = ~U[2026-08-21 09:00:00Z] 
DateTime.shift_zone(utc, "Europe/Kyiv") # {:ok, ~U[2026-08-21 12:00:00+03:00]}

Для роботи з часовими поясами Elixir використовує календарну інфраструктуру та часові зони. У стандартному середовищі доступні UTC та деякі базові можливості, а для повноцінної роботи з базою часових зон часто використовується бібліотека tzdata.

Додавання та віднімання часу

Для роботи з датами можна використовувати функції модуля Date:

date = ~D[2026-08-21] 
Date.add(date, 10) # ~D[2026-08-31] 
Date.add(date, -10) # ~D[2026-08-11]

Таким способом можна додавати або віднімати кількість днів.

Різниця між датами

Функція Date.diff/2 дозволяє отримати кількість днів між двома датами:

date1 = ~D[2026-08-21] 
date2 = ~D[2026-09-01] 
Date.diff(date2, date1) # 11

Результат може бути і від'ємним:

Date.diff(date1, date2) # -11

Порівняння дат

Дати є звичайними значеннями Elixir, тому їх можна порівнювати за допомогою операторів:

date1 = ~D[2026-08-21] 
date2 = ~D[2026-09-01] 
date1 < date2 # true

Також можна використовувати функції Date.compare/2:

Date.compare(~D[2026-08-21], ~D[2026-09-01]) # :lt 
Date.compare(~D[2026-09-01], ~D[2026-08-21]) # :gt 
Date.compare(~D[2026-08-21], ~D[2026-08-21]) # :eq

Робота з компонентами дати та часу

Окремі компоненти можна отримати безпосередньо з відповідних структур:

date = ~D[2026-08-21] date.year # 2026 date.month # 8 date.day # 21

Для DateTime аналогічно:

datetime = ~U[2026-08-21 12:30:45Z] 
datetime.year # 2026 
datetime.hour # 12 
datetime.minute # 30 
datetime.second # 45

Форматування дат

Elixir має функції для перетворення дат у рядки та навпаки. Для складнішого форматування часто використовують бібліотеку Timex або власне форматування.

Простий варіант — використати Calendar.strftime/2:

date = ~D[2026-08-21] 
Calendar.strftime(date, "%Y-%m-%d") # "2026-08-21" 
Calendar.strftime(date, "%d.%m.%Y") # "21.08.2026"

Для DateTime це працює аналогічно:

datetime = ~U[2026-08-21 12:30:45Z] 
Calendar.strftime(datetime, "%Y-%m-%d %H:%M:%S") # "2026-08-21 12:30:45"

Основні символи форматування

Формат Значення Приклад
%Y Рік 2026
%m Місяць 08
%d День 21
%H Година 14
%M Хвилина 30
%S Секунда 45
%A Повна назва дня тижня Friday
%B Повна назва місяця August

Перетворення рядка в дату

Для перетворення рядка у структуру Date можна використовувати Date.from_iso8601/1:

Date.from_iso8601("2026-08-21") # {:ok, ~D[2026-08-21]}

Для ISO 8601 datetime можна використовувати DateTime.from_iso8601/1:

DateTime.from_iso8601("2026-08-21T12:30:00Z") # {:ok, ~U[2026-08-21 12:30:00Z], 0}

Це особливо важливо при роботі з REST API, JSON та базами даних, оскільки ISO 8601 є поширеним форматом передачі дат і часу.

Робота з часовими інтервалами

У Elixir існує структура Date.Range, яка дозволяє описувати діапазон дат:

range = Date.range(~D[2026-08-21], ~D[2026-08-25]) 
Enum.to_list(range) # [ # ~D[2026-08-21], # ~D[2026-08-22], # ~D[2026-08-23], # ~D[2026-08-24], # ~D[2026-08-25] # ]

Це добре поєднується з модулем Enum:

Date.range(~D[2026-08-21], ~D[2026-08-25]) |> 
Enum.each(fn date -> IO.inspect(date) end)

Мікросекунди

Типи часу та datetime підтримують мікросекундну точність:

time = ~T[14:30:15.123456] time.microsecond # {123456, 6}

Другий елемент кортежу показує точність значення.

Unix timestamp

Для представлення моменту часу у вигляді Unix timestamp можна використовувати DateTime.to_unix/1:

datetime = ~U[2026-08-21 12:00:00Z] 
DateTime.to_unix(datetime) # 1787313600

Зворотне перетворення виконується через DateTime.from_unix/1:

DateTime.from_unix(1787313600) # {:ok, ~U[2026-08-21 12:00:00Z]}

Який тип використовувати?

Тип Для чого використовувати Приблизний аналог Java
Date Календарна дата без часу LocalDate
Time Час доби без дати LocalTime
NaiveDateTime Дата + час без часового поясу LocalDateTime
DateTime Дата + час із часовою зоною ZonedDateTime
DateTime у UTC Конкретний момент часу Instant
Date.Range Діапазон дат Окремого прямого аналога немає

На що варто звернути увагу Java-розробнику

Для Java-розробника концепція роботи з датами в Elixir багато в чому знайома завдяки сучасному API java.time. Наприклад, Date приблизно відповідає LocalDate, а NaiveDateTimeLocalDateTime.

Однак важлива відмінність полягає у функціональній природі Elixir. Значення дат і часу є іммутабельними. Функція, яка змінює дату або час, не модифікує існуюче значення, а повертає нове:

date = ~D[2026-08-21] new_date = Date.add(date, 10) 
IO.inspect(date) # ~D[2026-08-21] 
IO.inspect(new_date) # ~D[2026-08-31]

Це відповідає загальній моделі Elixir, де дані не змінюються після створення.

Коментарі

Популярні публікації

Дамп бази даних Postgresql локально

Що потрібно встановити локально (Ubuntu) Встанови клієнтські утиліти PostgreSQL: pg_dump , psql , pg_restore . sudo apt update sudo apt install postgresql-client Кроки міграції Ідея: не зберігати дамп на серверах. Зробити дамп з віддаленого сервера на свій локальний ПК, потім передати його на новий сервер і там відновити. 1) Створення дампу з віддаленого сервера локально pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB -f dump_file.dump Пояснення ключів: -h (хост), -U (користувач), -Fc (custom format), -d (БД), -f (вихідний файл локально). 1.1) Варіант з розбиттям на частини (якщо треба) pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB | split -b 10G - dump_file.dump.part_ Це створить локально файли типу dump_file.dump.part_aa , dump_file.dump.part_ab тощо. 2) Передача дампу на новий сервер Один файл: scp dump_file.dump NEW_USER@NEW_SERVER_IP:/tmp/ Або частинами: scp dump_file.dump.part_* NEW_USER@NEW_SERVER_IP:/tmp/ 3) Збирання файл...

Основи Next.js

Що таке Next.js? Next.js — це прогресивний фреймворк для розробки веб-застосунків на основі React. Він розширює можливості React, додаючи готову інфраструктуру для Server-Side Rendering (SSR), генерації статичних сторінок, маршрутизації через файлову систему, а також можливість створювати backend-ендпоінти прямо в проєкті. Чому він став популярним? Next.js швидко здобув популярність завдяки тому, що пропонує: SEO-дружні сторінки завдяки SSR / SSG; швидкий перший рендер (First Page Load); просту маршрутизацію без налаштування; розгортання в один клік через Vercel; вбудовану оптимізацію зображень та продуктивності. Чим відрізняється від класичного React У класичному React ми отримуємо лише клієнтську бібліотеку для побудови UI-компонентів. Усе інше (SSR, маршрути, API) треба налаштовувати вручну або через сторонні бібліотеки (наприклад, React Router, Redux, Express, etc.). Next.js — це уже повноцінний фреймворк. Він одразу має: серверний рендеринг...

ООП у TypeScript

Короткий вступ TypeScript додає статичну типізацію поверх JavaScript і підтримує класичні концепти ООП: класи , успадкування , інтерфейси , інкапсуляцію , поліморфізм та абстракції . Нижче — практичні приклади та пояснення. Класи — декларація, конструктор, властивості та методи class Person { public name: string; private age: number; protected email?: string; // необов’язкове static species = 'Homo sapiens'; constructor(name: string, age: number, email?: string) { this.name = name; this.age = age; this.email = email; } public greet(): string { return `Hi, I'm ${this.name}.`; } private getBirthYear(currentYear: number): number { return currentYear - this.age; } } const p = new Person('Ivan', 30, 'ivan@example.com'); console.log(p.greet()); // console.log(p.age); // помилка: 'age' приватне console.log(Person.species); Успадкування і перевизначення (extends, super) class Employee extends Person { ...

Створення проєкту на TypeScript, модулі

Крок 1. Ініціалізація проєкту Спочатку створимо нову теку та ініціалізуємо Node.js-проєкт за допомогою npm : mkdir my-typescript-app cd my-typescript-app npm init -y Крок 2. Встановлення TypeScript Додаємо TypeScript як dev-залежність: npm install --save-dev typescript ts-node @types/node - typescript — компілятор TypeScript - ts-node — дозволяє запускати TS-файли без попередньої компіляції - @types/node — типи для стандартних Node.js API Крок 3. Створення файлу tsconfig.json Ініціалізуємо конфігурацію TypeScript: npx tsc --init Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020", // Версія JS у вихідному коді "module": "CommonJS", // Система модулів (для Node.js) "rootDir": "src", // Вхідна папка з TypeScript-кодом "outDir": "dist", // Куди компілюється код JS "str...

Інструменти для роботи з Node.js

Що таке npm? npm (Node Package Manager) — це офіційний пакетний менеджер для Node.js . Він дозволяє: Встановлювати сторонні бібліотеки та фреймворки Керувати залежностями проєкту Запускати скрипти (команди) через package.json Приклад ініціалізації проєкту з npm npm init -y Файл package.json (скорочений приклад) { "name": "my-project", "version": "1.0.0", "scripts": { "start": "ts-node src/index.ts", "build": "tsc" }, "dependencies": { "express": "^4.18.0" }, "devDependencies": { "typescript": "^5.0.0", "ts-node": "^10.0.0" } } Що таке tsconfig.json? tsconfig.json — це файл конфігурації для компілятора TypeScript, який визначає, як слід компілювати код. Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020...