トラック
/
Elixir
Elixir
/
演習
/
図書館の料金
図書館の料金

図書館の料金

学習演習

はじめに

日付と時刻

Elixirの標準ライブラリには、日付や時刻を扱うための4つのモジュールがあり、それぞれが独自の構造体を持っています。

  • 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関数を探しましょう。==、>、<などの比較演算子は_動くように見えます_が、これらの構造体に対して正しい意味での比較を行ってはくれません。

説明

図書館司書をしている友人が、延滞料金を自動で計算できるように、図書館のソフトウェアを拡張してほしいと頼んできました。 現在のシステムでは、本を貸し出した正確な日時をISO8601の日時文字列として保存しています。 彼女はガーナの小さな町で地域の図書館を運営しています。そこではGMT(UTC +0)のタイムゾーンを使っていて、夏時間もなく、ほかのタイムゾーンを気にする必要もありません。

1. 保存された日時を解析する

LibraryFees.datetime_from_string/1関数を実装しましょう。この関数は、ISO8601の日時文字列を引数として受け取り、NaiveDateTime構造体を返します。

LibraryFees.datetime_from_string("2021-01-01T13:30:45Z")
# => ~N[2021-01-01 13:30:45]

2. 本が正午より前に貸し出されたかどうかを判定する

本が正午より前に貸し出された場合、利用者は28日以内に返却する必要があります。正午ちょうど、またはそれ以降に貸し出された場合は29日です。

LibraryFees.before_noon?/1関数を実装しましょう。この関数はNaiveDateTime構造体を受け取り、真偽値を返します。

LibraryFees.before_noon?(~N[2021-01-12 08:23:03])
# => true

3. 返却日を計算する

貸し出し日時をもとに、返却日を計算しましょう。

LibraryFees.return_date/1関数を実装しましょう。この関数はNaiveDateTime構造体を受け取り、28日後または29日後のDate構造体を返します。

LibraryFees.return_date(~N[2020-11-28 15:55:33])
# => ~D[2020-12-27]

4. 本の返却がどれだけ遅れたかを判定する

図書館では、延滞に対して一律の料金が設定されています。料金を計算するには、返却予定日から実際に何日後に本が返却されたかを知る必要があります。

LibraryFees.days_late/2関数を実装しましょう。この関数は、返却予定日を表すDate構造体と、実際の返却日時を表すNaiveDateTime構造体の2つを受け取ります。

実際の返却日が、返却予定日と同じ日かそれより前の場合、関数は0を返します。それ以外の場合は、2つの日付の差を日数で返します。

図書館は統計のために、本の実際の返却日時を日付と時刻の両方で記録していますが、延滞料金の計算には時刻を使いません。

LibraryFees.days_late(~D[2020-12-27], ~N[2021-01-03 09:23:36])
# => 7

5. 本が月曜日に返却されたかどうかを判定する

図書館には、月曜日に本を返却すると得られる特典があります。

LibraryFees.monday?/1関数を実装しましょう。この関数はNaiveDateTime構造体を受け取り、真偽値を返します。

LibraryFees.monday?(~N[2021-01-03 13:30:45Z])
# => false

6. 延滞料金を計算する

LibraryFees.calculate_late_fee/3関数を実装しましょう。この関数は3つの引数、つまり2つのISO8601日時文字列(貸し出し日時と実際の返却日時)と、1日あたりの延滞料金を受け取ります。そして、本の返却が実際にどれだけ遅れたかに応じた延滞料金の合計を返します。

月曜日の特典も考慮に入れましょう。月曜日に本を返却した場合、延滞料金は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
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Elixir Exercism

図書館の料金を始める準備はできましたか?

Exercismに登録すれば、58個のコンセプト168個の演習、そして本物の人間によるメンタリングとともに、Elixirを学んでマスターできます。すべて無料です。