La libreria standard di Elixir offre 4 moduli diversi per lavorare con date e orari, ognuno con la propria struct.
Il modulo Date. Una struct Date si può creare con il sigil ~D.
~D[2021-01-01]
Il modulo Time. Una struct Time si può creare con il sigil ~T.
~T[12:00:00]
Il modulo NaiveDateTime per date e orari senza fuso orario. Una struct NaiveDateTime si può creare con il sigil ~N.
~N[2021-01-01 12:00:00]
Il modulo DateTime per date e orari con un fuso orario. Usare questo modulo per fusi orari diversi da UTC richiede una dipendenza esterna, un database di fusi orari.
Per confrontare tra loro date o orari, cerca una funzione compare o diff nel modulo corrispondente. Gli operatori di confronto come ==, > e < sembrano funzionare, ma non fanno un confronto semantico corretto per quelle struct.
La tua amica bibliotecaria ti ha chiesto di estendere il software della sua biblioteca per calcolare automaticamente le penali per il ritardo. Il suo sistema attuale memorizza la data e l'ora esatte del prestito di un libro come stringa di data e ora ISO8601. Gestisce una biblioteca locale in una piccola città del Ghana, che usa il fuso orario GMT (UTC +0), non usa l'ora legale e non deve preoccuparsi di altri fusi orari.
Implementa la funzione LibraryFees.datetime_from_string/1. Deve prendere come argomento una stringa di data e ora ISO8601 e restituire uno struct NaiveDateTime.
LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]
Se un libro viene preso in prestito prima di mezzogiorno, il lettore ha 28 giorni per restituirlo. Se viene preso in prestito a mezzogiorno o dopo, sono 29 giorni.
Implementa la funzione LibraryFees.before_noon?/1. Deve prendere uno struct NaiveDateTime e restituire un valore booleano.
LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true
In base alla data e ora del prestito, calcola la data di restituzione.
Implementa la funzione LibraryFees.return_date/1. Deve prendere uno struct NaiveDateTime e restituire uno struct Date, 28 o 29 giorni dopo.
LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]
La biblioteca applica una tariffa fissa per le restituzioni in ritardo. Per poter calcolare la penale, dobbiamo sapere quanti giorni dopo la data di restituzione il libro è stato effettivamente restituito.
Implementa la funzione LibraryFees.days_late/2. Deve prendere uno struct Date, la data di restituzione prevista, e uno struct NaiveDateTime, la data e ora della restituzione effettiva.
Se la data di restituzione effettiva cade in un giorno precedente o nello stesso giorno della data e ora di restituzione prevista, la funzione deve restituire 0. Altrimenti, deve restituire la differenza tra queste due date in giorni.
La biblioteca registra sia la data sia l'ora della restituzione effettiva del libro per fini statistici, ma non usa l'ora quando calcola le penali per il ritardo.
LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7
La biblioteca ha un'offerta speciale per la restituzione dei libri di lunedì.
Implementa la funzione LibraryFees.monday?/1. Deve prendere uno struct NaiveDateTime e restituire un valore booleano.
LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false
Implementa la funzione LibraryFees.calculate_late_fee/3. Deve prendere tre argomenti: due stringhe di data e ora ISO8601, la data e ora del prestito e la data e ora della restituzione effettiva, e la penale per un giorno di ritardo. Deve restituire la penale totale in base a quanto in ritardo è avvenuta la restituzione effettiva del libro.
Includi l'offerta speciale del lunedì. Se restituisci il libro di lunedì, la penale è scontata del 50%, arrotondata per difetto.
# 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
Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.