Haskellで時間を扱うためのライブラリといえばtime
がデファクトスタンダードでしょう。しかし時間に関係する概念はとても多く(そもそも時間という概念が複雑なのでいたしたかないところはあるかも知れませんが)、初見だとライブラリをどのように扱ったら良いかわからないかも知れません。この記事では time-1.8.0.4
が提供する型とその間の関係を簡単にまとめていきます。
time
が提供する型
※空白○から伸びる関数は引数を取らない関数(つまり値)
※先端が◇の矢印はIOを伴う関数
ロケーションに依存しない時間を表す型
UTCTime
協定世界時(UTC)を表す型です。定義は
data UTCTime = UTCTime
{ utctDay :: Day
, utctDayTime :: DiffTime
}
となっており、経過日数utctDay
(詳細は後述のDay
を参照)と一日の中での経過秒utctDayTime
を保持しています。DiffTime
型は閏秒まで考慮した時間の長さを表す型で、$10^{-12}$秒の精度があります。
getCurrentTime :: IO UTCTime
getCurrentTime
を使うと現在時刻を表すUTCTime
の値が簡単に手に入ります。ただしUTCなので日本時間ではありません。タイムゾーンの情報も含んだ時間を取得したい場合は後述するgetZonedTime
を使用してください。
NominalDiffTime
UTCで測った時間の長さです。$10^{-12}$秒の精度があり、DiffTime
と違って閏秒は無視されます。diffUTCTime
を使ってUTCTime
を引き算した結果の型だったり、addUTCTime
を使ってUTCTime
に足すことでUTCTime
を変化させることができたりします。
DiffTime
やNominalDiffTime
の値を生成する時はduration
というライブラリが便利です。これはTemplate Haskellを使って直感的な形で時間を記述できるライブラリで、例えば[µs| 1s |]
と書けば1秒をマイクロ秒に換算した時の値を表すことができます。詳細は以下の記事を参照してみてください。
Template Haskell でいい感じに時間の長さを書けるライブラリ duration を作った - ryota-ka's blog
時間と期間に関連する型
Day
修正ユリウス通日を表す型で、1858年11月17日からの経過日数が保持されています。
newtype Day = ModifiedJulianDay { toModifiedJulianDay :: Integer }
TimeOfDay
一日の中の経過時間(時間・分・秒)を表す型です。
data TimeOfDay = TimeOfDay
{ todHour :: Int -- range 0 - 23
, todMin :: Int -- range 0 - 59
, todSec :: Pico -- 0 <= 'todSec' < 61
}
Pico
は$10^{-12}$精度の数を表す型で、todSec
が60を超える可能性があるのは閏秒の存在があるからです。
LocalTime
現地時間を表す型です。場所によって変わる時間なのでUTCTime
とも違いますがタイムゾーンの情報は持っていません。
data LocalTime = LocalTime
{ localDay :: Day
, localTimeOfDay :: TimeOfDay
}
日付localDay
とその日における時間localTimeOfDay
の情報を持っています。
TimeZone
タイムゾーンを表す型でUTCからのズレを保持しています。
data TimeZone = TimeZone
{ timeZoneMinutes :: Int
, timeZoneSummerOnly :: Bool
, timeZoneName :: String
}
getCurrentTimeZone
という関数を使用することで現在のシステムに設定されているタイムゾーンを取得することができます。
getCurrentTimeZone :: IO TimeZone
ZonedTime
タイムゾーンの情報を持った現地時間を表す型です。
data ZonedTime = ZonedTime
{ zonedTimeToLocalTime :: LocalTime
, zonedTimeZone :: TimeZone
}
getZonedTime
という関数を使用することで現在時刻を表すZonedTime
の値を取得することができます。
getZonedTime :: IO ZonedTime
おわりに
timeに含まれる型について非常に簡単に説明してみました。より詳細な使い方に関しては次の記事が分かりやすいと思います。time パッケージの使い方
timeを使うハードルが少しでも低くなれば幸いです