DateTimeモジュール で遊んでみたシリーズ⑦ -DateTime.to_date ~ DateTime.to_string の紹介

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

# 目次
1.[DateTimeモジュール で遊んでみたシリーズ① -事前準備編](https://qiita.com/Alicesky2127/items/71d6905684f6f0f936c2)
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 の紹介(本記事)
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モジュールに含まれる関数を触って機能を理解したい

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

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

# 前提
本記事を手元検証するには、前提としてtzdataの導入が必要です。
まだの場合は下記1.または2.で準備をしてください。

1.local環境でtzdataの導入

https://qiita.com/Alicesky2127/items/71d6905684f6f0f936c2

2.Livebookでtzdataの導入

https://qiita.com/Alicesky2127/items/4ad2072cbca04193a3d4
# DateTime.to_dateとは
`DateTime.to_date(datetime)`は`datetime`をDate構造体に変換します。
日付以外の情報は失われます。

## 例
```diff_elixir:iex
DateTime.to_date(~U[2015-01-23 23:50:07Z])
```
```
~D[2015-01-23]
```

タイムゾーンがUTC以外の時も同様
```diff_elixir:iex
dt = DateTime.now!("Asia/Tokyo")
```
```
#DateTime<2024-12-22 16:09:52.716011+09:00 JST Asia/Tokyo>
```

```diff_elixir:iex
DateTime.to_date(dt)
```
```
~D[2024-12-22]
```


# DateTime.to_gregorian_secondsとは
`DateTime.to_gregorian_seconds(datetime)`は現在のグレゴリオ暦基準で、`datetime`を秒とマイクロ秒に変換します。

タイムゾーンはUTCで返されます。
UTC以外のタイムゾーンが必要な場合は、この関数の結果に対して`DateTime.shift_zone/3`を使用してタイムゾーンを変換してください。

この関数の逆は`DateTime.from_gregorian_seconds(seconds, arg \\ {0, 0}, calendar \\ Calendar.ISO)`です。

## 例
```diff_elixir:iex
dt = %DateTime{year: 0000, month: 1, day: 1, zone_abbr: "UTC",
               hour: 0, minute: 0, second: 1, microsecond: {0, 0},
               utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}

DateTime.to_gregorian_seconds(dt)
```
```
{1, 0}
```

```diff_elixir:iex
dt = %DateTime{year: 2020, month: 5, day: 1, zone_abbr: "CET",
               hour: 1, minute: 26, second: 31, microsecond: {5000, 0},
               utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}

DateTime.to_gregorian_seconds(dt)
```
```
{63755511991, 5000}
```



# DateTime.to_iso8601とは
`DateTime.to_iso8601(datetime, format \\ :extended, offset \\ nil)`はDatetime構造体をISO 8601の拡張形式に変換します。
タイムゾーン情報は失われます。

この関数の逆は`DateTime.from_iso8601(string, format_or_calendar \\ Calendar.ISO)`です。


## 例
### 時差無しの場合
```diff_elixir:iex
DateTime.to_iso8601(~U[2015-01-23 23:50:07Z])
```
```
"2015-01-23T23:50:07Z"
```

### 時差ありの場合
```diff_elixir:iex
DateTime.to_iso8601(~U[2015-01-23 14:50:07Z], :extended, 32400)
```
```
"2015-01-23T23:50:07+09:00"
```


### ISO8601基本形式への対応
`format_or_calendar`に`:basic`を渡すことでISO8601基本形式へ対応できます。
```diff_elixir:iex
DateTime.to_iso8601(~U[2015-01-24 04:50:07.123Z], :basic, -18000)
```
```
"20150123T235007.123-0500"
```

# DateTime.to_naiveとは
`DateTime.to_naive(datetime)`はDatetime構造体をNaiveDatetime構造体に変換します。
タイムゾーン情報は失われます。

この関数の逆は`DateTime.from_naive(naive_datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())`です。

## 例
```diff_elixir:iex
dt = ~U[2016-05-24 13:26:08.003Z]]
DateTime.to_naive(dt)
```
```
~N[2016-05-24 13:26:08.003]
```

```diff_elixir:iex
dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
               hour: 23, minute: 0, second: 7, microsecond: {0, 1},
               utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}

DateTime.to_naive(dt)
```
```
~N[2000-02-29 23:00:07.0]
```

# DateTime.to_stringとは
`DateTime.to_string(datetime)`は`datetime`を文字列に変換します。

## 例
```diff_elixir:iex
dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
               hour: 23, minute: 0, second: 7, microsecond: {0, 0},
               utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
```
```
#DateTime<2000-02-29 23:00:07+01:00 CET Europe/Warsaw>
```

```diff_elixir:iex
DateTime.to_string(dt)
```
```
"2000-02-29 23:00:07+01:00 CET Europe/Warsaw"
```

紀元前の場合
```diff_elixir:iex
dt = %DateTime{year: -100, month: 12, day: 19, zone_abbr: "CET",
               hour: 3, minute: 20, second: 31, microsecond: {0, 0},
               utc_offset: 3600, std_offset: 0, time_zone: "Europe/Stockholm"}
```
```
#DateTime<-0100-12-19 03:20:31+01:00 CET Europe/Stockholm>
```

```diff_elixir:iex
DateTime.to_string(dt)
```
```
"-0100-12-19 03:20:31+01:00 CET Europe/Stockholm"
```




# ～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

[^1]:ユーザーが文字として認識する単位のことを書記素(grapheme)と呼びます。

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


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