LoginSignup
28
21

More than 5 years have passed since last update.

[Elixir] Phoenixで日付/時間を扱う

Posted at

やりたいこと

下記のような日付と時間を扱った処理をスマートにやるにはどうすればよいか調べてみた。
- 現在のロケールの現在時刻から12時間進めた日時が欲しい
- DBに保存した日付データをn日加算したい

Elixirでの日付/時間

日時は基本的にタプルで持つ。現在時刻はErlangのCalendarモジュールから取得できる。

# UTC現在時刻
utc_now = :calendar.universal_time
{{2015, 10, 20}, {8, 12, 25}}

# ローカル現在時刻
jst_now = :calendar.local_time
{{2015, 10, 20}, {17, 11, 17}}

一般的な日時処理(時間の加算など)

Timexを使うのが一般的か。

use Timex

# 1031日の1ヶ月後
next_month = {{2015, 10, 31}, {0, 0, 0}} |> Date.from |> Date.shift(months: 1) |> DateConvert.to_erlang_datetime

# 1時間後
an_hour_later = Date.local |> Date.shift(hours: 1) |> DateConvert.to_erlang_datetime

# 2日前
two_days_ago = Date.local |> Date.shift(days: -2) |> DateConvert.to_erlang_datetime

Ecto.DateTimeでの日時処理

Using with Ectoにある方法でModelの日時関係プロパティをTimexモジュールのものにしない場合は下記のようにキャストしてから加算/減算する。

defmodule Demo.Person do
  use Demo.Web, :model

  schema "people" do
    field :name, :string
    field :born_at, Ecto.DateTime
    timestamps
  end
end

john = Repo.get!(Demo.Person, 1)

# Johnの誕生日を7日前にずらす
seven_days_ago = john.born_at
                 |> Ecto.DateTime.to_erl
                 |> Date.from
                 |> Date.shift(days: -7)
                 |> DateConvert.to_erlang_datetime
                 |> Ecto.DateTime.from_erl
Repo.update! %{john | born_at: seven_days_ago}

何故こんな面倒なことをするのか?上記ガイドに従って、Timex.Ecto.DateTimeにしても良いんじゃないか?
→日時処理を簡便化するためだけにModelを書き換え、その他モジュールで日時を扱う箇所を全部直し…って大げさすぎませんかね?(感想)

あとがき

Timexを使えば直感的に日時をコントロールできる。素敵。
でもEctoが絡むとどうもスマートになりきれていな気がする。

28
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
21