haskell

Haskellで日付を扱う

以下で紹介している関数は全て、Haskellのtimeパッケージをインストールして、

import Data.Time

-- 一部はこれも
import Data.Time.Clock.POSIX

とすれば使えます。

日時を扱う

現在のタイムスタンプを取得する関数はgetCurrentTimeです。戻り値はUTCTime型です。

getCurrentTime
--> 2019-09-16 06:59:38.751786 UTC

文字列 –> UTCTime

文字列からUTCTimeデータを作成するには2つ方法があり、一つはreadを使って

read "2019-09-16 14:00:00.012345" :: UTCTime
--> 2019-09-16 14:00:00.012345 UTC

これはそのままUTCTime型で取得できるので便利ですが、元の文字列が正しい形式でなかった場合に例外を出すので危険です。

もう一つは、文字列をパースする方法で、parseTimeMという関数がData.Time.Formatにあります。型は

parseTimeM
  :: (Monad m, ParseTime t) =>
     Bool -> TimeLocale -> String -> String -> m t

少し複雑なので使い方から入りましょう。

parseTimeM True defaultTimeLocale "%Y-%m-%d %H:%M:%S.%q" "2019-10-30 09:12:59.000000000001" :: Maybe UTCTime
--> Just 2019-10-30 09:12:59.000000000001 UTC

ドキュメントによれば第一引数は、文字列の先頭・末尾に空白がある場合に自動でトリムするかどうかを指定します。Falseにした場合は、先頭・末尾に空白があった場合にフォーマット違反とみなされNothingが返ってきます。
(実際に試してみると、Falseにしていても先頭の空白は自動でトリムされてJustで返ってきました。)
第二引数はタイムゾーン、第三引数にフォーマット、第四引数にパースしたい文字列を指定します。
ちなみに%qはピコ秒のことで、12桁の数字列を要求します。ミリ秒とマイクロ秒は無さそうでした。

POSIXTime –> UTCTime

POSIXTimeからHaskellのUTCTime型に変換するにはData.Time.Clock.POSIXにあるposixSecondsToUTCTimeという関数が使えます。

import Data.Time.Clock.POSIX

posixSecondsToUTCTime 0
--> 1970-01-01 00:00:00 UTC

posixSecondsToUTCTime 1570775400
--> 2019-10-11 06:30:00 UTC

UTCTime –> POSIXTime

同モジュール内には、これとは逆にUTCTimeからPOSIXTimeに変換するutcTimeToPOSIXSecondsという関数もあります。

-- UTCTime
utcNow <- getCurrentTime

utcNow
--> 2020-01-22 23:39:23.039432 UTC

utcTimeToPOSIXSeconds utcNow
--> 1579736363.039432s

任意のDayデータを作成する方法

Haskellで日時ではなく日付までを扱いたい場合、Data.Time.Calendarというモジュール内にDayという型があり、これを使います。

fromGregorian 2019 9 16
--> 2019-09-16

整数型で年、月、日を引数で渡すと、Day型データを返してくれます。文字列からの場合は、UTCTimeの時と同様、parseTimeMが使えるようです。

現在の日付を取得する

こちらは、まず現在のタイムスタンプを取得して(UTCTime型)、そこからutctDayという関数を使ってDayを取得します。utctDayData.Time.Clockで提供されています。

now <- getCurrentTime
utctDay now
--> 2019-09-16

年、月、日、をそれぞれ整数値として別個に取得したい場合は、toGregorianが使えます。最初に紹介した関数の逆関数ですね。以下に書いた例のように、年月日をタプルで返してきます。

today <- return . utctDay =<< getCurrentTime
toGregorian today
--> (2019, 09, 16)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です