Haskell

Haskellの時間系ライブラリ time が提供する型

Haskellで時間を扱うためのライブラリといえばtimeがデファクトスタンダードでしょう。しかし時間に関係する概念はとても多く(そもそも時間という概念が複雑なのでいたしたかないところはあるかも知れませんが)、初見だとライブラリをどのように扱ったら良いかわからないかも知れません。この記事では time-1.8.0.4 が提供する型とその間の関係を簡単にまとめていきます。


timeが提供する型

relations.png

※空白○から伸びる関数は引数を取らない関数(つまり値)

※先端が◇の矢印は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を変化させることができたりします。

DiffTimeNominalDiffTimeの値を生成する時は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を使うハードルが少しでも低くなれば幸いです :relaxed: