DateTimeモジュール で遊んでみたシリーズ① -事前準備編

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はDateTimeモジュールについて学んだことをまとめます。

# 目次
1.DateTimeモジュール で遊んでみたシリーズ① -事前準備編(本記事)
2.[DateTimeモジュール で遊んでみたシリーズ② -DateTime.add ~ DateTime.compare の紹介](https://qiita.com/Alicesky2127/items/971a013f34f0f1fb7c90)
3.[DateTimeモジュール で遊んでみたシリーズ③ -DateTime.convert ~ DateTime.from_gregorian_seconds の紹介](https://qiita.com/Alicesky2127/items/74e646264c7a55ea6f81)
4.[DateTimeモジュール で遊んでみたシリーズ④ -DateTime.from_iso8601 ~ DateTime.from_naive! の紹介](https://qiita.com/Alicesky2127/items/79869efcf8bb5cee9d82)
5.[DateTimeモジュール で遊んでみたシリーズ⑤ -DateTime.from_unix ~ DateTime.new! の紹介](https://qiita.com/Alicesky2127/items/6ce1eb3071880db5dec2)
6.[DateTimeモジュール で遊んでみたシリーズ⑥ -DateTime.now ~ DateTime.shift_zone! の紹介](https://qiita.com/Alicesky2127/items/b706801a887ceb5427ee)
7.[DateTimeモジュール で遊んでみたシリーズ⑦ -DateTime.to_date ~ DateTime.to_string の紹介](https://qiita.com/Alicesky2127/items/a3fcf13bd2577d57b431)
8.[DateTimeモジュール で遊んでみたシリーズ⑧ -DateTime.to_time ~ DateTime.utc_now の紹介](https://qiita.com/Alicesky2127/items/ebd5b063c041adf2d1d0)
9.[DateTimeモジュール で遊んでみたシリーズ番外編 -Livebookでtzdata導入](https://qiita.com/Alicesky2127/items/4ad2072cbca04193a3d4)



# 目的 
DateTimeモジュールに含まれる関数を触って機能を理解したい。
そのためlocalに`tzdata`のインストールをしたい。

https://hexdocs.pm/elixir/DateTime.html

## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.17.3
Erlang v27.0
Phoenix v1.7.14

# Elixirにおける日付と時刻とは
Elixirの日付と時刻は「特定のタイムゾーンにおける日付と時刻の断面（スナップショット）」です。

# 日付と時刻の表現一覧
日付と時刻の表現は下記の表の通りです。

| シギル名 | 内容 | データ型 | 例　|
|:---------|:------:|:------:|:------:|
| ~D    | 日付     | Date型   | ~D[2015-01-13]   |
| ~T    | 時刻     | Time型   | ~T[13:00:07]   |
| ~U    | タイムゾーンあり日付と時刻 | DateTime型   | ~U[2015-01-13 13:00:07Z]   |
| ~N    | タイムゾーン無し日付と時刻 | NaiveDateTime型 | ~N[2015-01-13 13:00:07]  |

# UTC以外のタイムゾーンを扱いたい場合
ElixirはデフォルトではUTCしか扱えません。
UTC以外のタイムゾーンを扱うには`tzdata`などのライブラリを導入する必要があります。

https://hexdocs.pm/elixir/DateTime.html#module-time-zone-database

# tzdataの導入
DateTimeモジュールには、引数にタイムゾーンを指定する関数があります。
これらを扱うために`tzdata`を導入します。


## PJ作成
下記でphoenix PJを作成します
```shell:bash
mix phx.new timezone_phx
cd timezone_phx
mix ecto.create
```

## 事前確認
`tzdata`を未導入の状態で引数にタイムゾーンを指定する関数を使うとどうなるか確認しておきましょう。
```shell:bash
iex -S mix
```
```
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
```

```diff_elixir:iex
Application.get_env(:elixir, :time_zone_database)
```
```
Calendar.UTCOnlyTimeZoneDatabase
```
UTC以外のタイムゾーンを扱おうとするとエラーになります。

```diff_elixir:iex
DateTime.from_naive!(~N[2018-11-15 10:00:00], "Europe/Copenhagen", Calendar.UTCOnlyTimeZoneDatabase)
```

```
** (ArgumentError) cannot convert ~N[2018-11-15 10:00:00] to datetime, reason: :utc_only_time_zone_database
    (elixir 1.17.3) lib/calendar/datetime.ex:697: DateTime.from_naive!/3
    #cell:wmgxue6myjgaginj:1: (file)
```

## mix.exs
下記を追加します。
```diff_elixir:mix.exs
   defp deps do
     [
       {:phoenix, "~> 1.7.14"},
       {:phoenix_ecto, "~> 4.5"},
       ...
-      {:bandit, "~> 1.5"}
+      {:bandit, "~> 1.5"},
+      {:tzdata, "~> 1.1"}
     ]
   end
```

## config.exs
最終行の次に下記を追加します。
```diff_elixir:config/config.exs
+ config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase
```

## mix.deps.get
`tzdata`を取得します。
```shell:bash
mix deps.get
```

## 動作確認
`:time_zone_databaseの値`が変わったことを確認します。
```diff_elixir:iex
Application.get_env(:elixir, :time_zone_database)
```
```
Tzdata.TimeZoneDatabase
```

引数にタイムゾーンを指定する関数を使ってみます。

```diff_elixir:iex
DateTime.from_naive!(~N[2018-11-15 10:00:00], "Europe/Copenhagen", Calendar.UTCOnlyTimeZoneDatabase)
```
```
#DateTime<2018-11-15 10:00:00+01:00 CET Europe/Copenhagen>
```

無事、UTC以外のタイムゾーンが扱えるようになりました(^▽^)/


# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian


[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！