Стандартна бібліотека Elixir пропонує чотири різні модулі для роботи з датами й часом, кожен зі своєю структурою.
Модуль Date. Структуру Date можна створити за допомогою сигілу ~D.
~D[2021-01-01]
Модуль Time. Структуру Time можна створити за допомогою сигілу ~T.
~T[12:00:00]
Модуль NaiveDateTime для дати-часу без часового поясу. Структуру NaiveDateTime можна створити за допомогою сигілу ~N.
~N[2021-01-01 12:00:00]
Модуль DateTime для дати-часу з часовим поясом. Використання цього модуля для часових поясів, відмінних від UTC, потребує зовнішньої залежності, а саме бази даних часових поясів.
Щоб порівняти дати або час між собою, знайдіть функцію compare або diff у відповідному модулі. Оператори порівняння, як-от ==, >, і <, здаються робочими, але вони не виконують правильного семантичного порівняння для цих структур.
Наша подруга-бібліотекарка попросила нас розширити її бібліотечну програму, щоб вона автоматично розраховувала плату за прострочення. Її поточна система зберігає точні дату й час видачі книги як рядок тексту (англ. string) у форматі ISO8601. Вона керує місцевою бібліотекою в маленькому містечку в Гані, де використовують часовий пояс GMT (UTC +0), не переходять на літній час і не мають клопоту з іншими часовими поясами.
Реалізуйте функцію LibraryFees.datetime_from_string/1. Вона має приймати рядок тексту з датою й часом у форматі ISO8601 як аргумент і повертати структуру NaiveDateTime.
LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]
Якщо книгу видали до полудня, читач має 28 днів, щоб її повернути. Якщо її видали опівдні або пізніше, то 29 днів.
Реалізуйте функцію LibraryFees.before_noon?/1. Вона має приймати структуру NaiveDateTime і повертати булеве значення (англ. Boolean).
LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true
На основі дати й часу видачі обчисліть дату повернення.
Реалізуйте функцію LibraryFees.return_date/1. Вона має приймати структуру NaiveDateTime і повертати структуру Date на 28 або 29 днів пізніше.
LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]
Бібліотека має фіксовану ставку за прострочене повернення. Щоб обчислити плату, нам треба знати, на скільки днів пізніше за дату повернення книгу повернули насправді.
Реалізуйте функцію LibraryFees.days_late/2. Вона має приймати структуру Date (заплановану дату повернення) і структуру NaiveDateTime (фактичні дату й час повернення).
Якщо фактична дата повернення припадає на той самий день, що й запланована, або раніше, функція має повернути 0. Інакше функція має повернути різницю між цими двома датами в днях.
Бібліотека зберігає і дату, і час фактичного повернення книги для статистики, але не використовує час, коли обчислює плату за прострочення.
LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7
Бібліотека має спеціальну пропозицію для повернення книг у понеділок.
Реалізуйте функцію LibraryFees.monday?/1. Вона має приймати структуру NaiveDateTime і повертати булеве значення.
LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false
Реалізуйте функцію LibraryFees.calculate_late_fee/3. Вона має приймати три аргументи: два рядки тексту з датою й часом у форматі ISO8601 (дату й час видачі та фактичні дату й час повернення) і плату за один день прострочення. Вона має повертати загальну плату за прострочення відповідно до того, наскільки пізно книгу повернули насправді.
Не забудьте про спеціальну пропозицію для понеділка. Якщо книгу повернути в понеділок, плата за прострочення зменшується на 50%, округлена в менший бік.
# Sunday, 7 days late
LibraryFees.calculate_late_fee("2020-11-28T15:55:33Z", "2021-01-03T13:30:45Z", 100)
# => 700
# one day later, Monday, 8 days late
LibraryFees.calculate_late_fee("2020-11-28T15:55:33Z", "2021-01-04T09:02:11Z", 100)
# => 400
Зареєструйтеся на Exercism, щоб вивчати й опановувати Elixir, а також 58 концепцій168 вправ та справжнє наставництво від людей, і все це безкоштовно.