自分の場合は現在時刻を引数で渡すようにしました。
モジュールやコンテキスを表すデータ型みたいなものを渡してもいいんですが仰々しいので。
コードはここに置いてあります。
Design-for-testability - OCaml version · GitHub
実装として、ファンクタに表示するメッセージのリストを渡して、挨拶用のモジュールを定義できるようにしてあります。
モジュールは下記の4つのモジュールです。
- Time - 時刻を扱うデータ型モジュール
- Time_range - 時刻の範囲を扱うデータ型モジュール
- Greeter_message - 挨拶のデータ型モジュール
- Greeter - 時刻によって挨拶を返すモジュール
open Greeter module Greeter = Greeter.Make(struct (* 05:00:00以上 12:00:00未満 *) let morning = Time_range.create ~stime:(Time.create ~hour:5 ~min:0 ~sec:0) ~etime:(Time.create ~hour:12 ~min:0 ~sec:0) (* 12:00:00以上 18:00:00未満 *) let noon = Time_range.create ~stime:(Time.create ~hour:12 ~min:0 ~sec:0) ~etime:(Time.create ~hour:18 ~min:0 ~sec:0) (* 18:00:00以上 05:00:00未満 *) let night1 = Time_range.create ~stime:(Time.create ~hour:18 ~min:0 ~sec:0) ~etime:(Time.create ~hour:23 ~min:59 ~sec:60) let night2 = Time_range.create ~stime:(Time.create ~hour:0 ~min:0 ~sec:0) ~etime:(Time.create ~hour:5 ~min:0 ~sec:0) let messages = [ (Greeter_message.create ~range:morning ~msg: "おはようございます"); (Greeter_message.create ~range:noon ~msg: "こんにちは"); (Greeter_message.create ~range:night1 ~msg: "こんばんは"); (Greeter_message.create ~range:night2 ~msg: "こんばんは") ] end)
またテスト用のパッケージをインストールするのが面倒だったので、テストの実行部分のコードを書きました。
通常はounitやppx_inline_testとかを使用した方がいいと思います。
ビルドもduneではなくocamlfind、ocamloptを使用しています。
適当なコード書くときに*.opam、duneファイル書くの結構面倒なんですよね。
感想
OCamlで時刻を扱うコードを書くの今ままでなかったので、標準モジュールを調べたりして、またOCamlに詳しくなりました。
今回はUnixモジュールのlocaltime、time関数やtm型を使用しました。
Windowsでは動かないと思います。