A biblioteca padrão do Elixir oferece 4 módulos diferentes para trabalhar com datas e horas, cada um com seu próprio struct.
O módulo Date. Um struct Date pode ser criado com o sigilo ~D.
~D[2021-01-01]
O módulo Time. Um struct Time pode ser criado com o sigilo ~T.
~T[12:00:00]
O módulo NaiveDateTime para datas e horas sem fuso horário. Um struct NaiveDateTime pode ser criado com o sigilo ~N.
~N[2021-01-01 12:00:00]
O módulo DateTime para datas e horas com fuso horário. Usar esse módulo para fusos horários diferentes de UTC exige uma dependência externa, um banco de dados de fusos horários.
Para comparar datas ou horas entre si, procure uma função compare ou diff no módulo correspondente. Operadores de comparação como ==, > e < parecem funcionar, mas não fazem uma comparação semântica correta para esses structs.
Sua amiga bibliotecária pediu que você estendesse o software da biblioteca dela para calcular automaticamente as taxas de atraso. O sistema atual dela armazena a data e a hora exatas da retirada de um livro como uma string de data e hora ISO8601. Ela administra uma biblioteca local em uma cidade pequena de Gana, que usa o fuso horário GMT (UTC +0), não adota horário de verão e não precisa se preocupar com outros fusos horários.
Implemente a função LibraryFees.datetime_from_string/1. Ela deve receber uma string de data e hora ISO8601 como argumento e retornar uma struct NaiveDateTime.
LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]
Se um livro foi retirado antes do meio-dia, o leitor tem 28 dias para devolvê-lo. Se foi retirado ao meio-dia ou depois, são 29 dias.
Implemente a função LibraryFees.before_noon?/1. Ela deve receber uma struct NaiveDateTime e retornar um valor booleano.
LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true
Com base na data e hora da retirada, calcule a data de devolução.
Implemente a função LibraryFees.return_date/1. Ela deve receber uma struct NaiveDateTime e retornar uma struct Date, 28 ou 29 dias depois.
LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]
A biblioteca cobra uma taxa fixa por devoluções atrasadas. Para calcular a taxa, precisamos saber quantos dias após a data de devolução o livro foi realmente devolvido.
Implemente a função LibraryFees.days_late/2. Ela deve receber uma struct Date (a data de devolução planejada) e uma struct NaiveDateTime (a data e hora da devolução real).
Se a data de devolução real for em um dia anterior ou no mesmo dia que a data e hora da devolução planejada, a função deve retornar 0. Caso contrário, ela deve retornar a diferença entre essas duas datas em dias.
A biblioteca registra tanto a data quanto a hora da devolução real do livro para fins estatísticos, mas não usa a hora no cálculo da taxa de atraso.
LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7
A biblioteca tem uma oferta especial para devoluções de livros às segundas-feiras.
Implemente a função LibraryFees.monday?/1. Ela deve receber uma struct NaiveDateTime e retornar um valor booleano.
LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false
Implemente a função LibraryFees.calculate_late_fee/3. Ela deve receber três argumentos: duas strings de data e hora ISO8601 (a data e hora da retirada e a data e hora da devolução real) e a taxa de atraso de um dia. Ela deve retornar a taxa de atraso total de acordo com o atraso da devolução real do livro.
Inclua a oferta especial de segunda-feira. Se você devolver o livro em uma segunda-feira, sua taxa de atraso tem 50% de desconto, arredondado para baixo.
# 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
Crie sua conta no Exercism para aprender e dominar Elixir com 58 conceitos168 exercícios e mentoria humana de verdade, tudo de graça.