A biblioteca padrão do Elixir oferece 4 módulos diferentes para trabalhar com datas e horas, cada um com o seu próprio struct.
O módulo Date. Podes criar um struct Date com o sigilo ~D.
~D[2021-01-01]
O módulo Time. Podes criar um struct Time com o sigilo ~T.
~T[12:00:00]
O módulo NaiveDateTime para datas e horas sem fuso horário. Podes criar um struct NaiveDateTime com o sigilo ~N.
~N[2021-01-01 12:00:00]
O módulo DateTime para datas e horas com fuso horário. Usar este módulo para fusos horários diferentes de UTC exige uma dependência externa, uma base de dados de fusos horários.
Para comparar datas ou horas entre si, procura uma função compare ou diff no módulo correspondente. Os operadores de comparação como ==, > e < parecem funcionar, mas não fazem uma comparação semântica correta para esses structs.
A tua amiga bibliotecária pediu-te para estenderes o software da biblioteca dela para calcular automaticamente as multas por atraso. O sistema atual dela guarda a data e a hora exatas do empréstimo de um livro como uma string de data e hora ISO8601. Ela gere uma biblioteca local numa pequena cidade do Gana, que usa o fuso horário GMT (UTC +0), não usa a hora de verão e não precisa de se preocupar com outros fusos horários.
Implementa a função LibraryFees.datetime_from_string/1. Deve receber como argumento uma string de data e hora em ISO8601 e devolver uma struct NaiveDateTime.
LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]
Se um livro for emprestado antes do meio-dia, o leitor tem 28 dias para o devolver. Se for emprestado ao meio-dia ou depois, são 29 dias.
Implementa a função LibraryFees.before_noon?/1. Deve receber uma struct NaiveDateTime e devolver um Boolean.
LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true
Com base na data e hora do empréstimo, calcula a data de devolução.
Implementa a função LibraryFees.return_date/1. Deve receber uma struct NaiveDateTime e devolver uma struct Date, 28 ou 29 dias depois.
LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]
A biblioteca tem um valor fixo para devoluções atrasadas. Para podermos calcular a multa, precisamos de saber quantos dias depois da data de devolução o livro foi realmente devolvido.
Implementa a função LibraryFees.days_late/2. Deve receber uma struct Date, a data de devolução prevista, e uma struct NaiveDateTime, a data e hora da devolução efetiva.
Se a data da devolução efetiva for igual ou anterior à data de devolução prevista, a função deve devolver 0. Caso contrário, deve devolver a diferença entre essas duas datas em dias.
A biblioteca regista a data e a hora da devolução efetiva do livro para fins estatísticos, mas não usa a hora ao calcular as multas por atraso.
LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7
A biblioteca tem uma oferta especial para devolver livros à segunda-feira.
Implementa a função LibraryFees.monday?/1. Deve receber uma struct NaiveDateTime e devolver um Boolean.
LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false
Implementa a função LibraryFees.calculate_late_fee/3. Deve receber três argumentos: duas strings de data e hora em ISO8601, a data e hora do empréstimo e a data e hora da devolução efetiva, e a multa por um dia. Deve devolver a multa total por atraso, de acordo com o atraso na devolução efetiva do livro.
Inclui a oferta especial de segunda-feira. Se devolveres o livro à segunda-feira, a multa é 50% mais baixa, arredondada por defeito.
# 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
Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.