こんにちは!
プログラミング未経験文系出身、Elixirの国に迷い込んだ?!見習いアルケミストのaliceと申します。
今回はDateTimeモジュールについて学んだことをまとめます。
目次
1.DateTimeモジュール で遊んでみたシリーズ① -事前準備編
2.DateTimeモジュール で遊んでみたシリーズ② -DateTime.add ~ DateTime.compare の紹介
3.DateTimeモジュール で遊んでみたシリーズ③ -DateTime.convert ~ DateTime.from_gregorian_seconds の紹介(本記事)
4.DateTimeモジュール で遊んでみたシリーズ④ -DateTime.from_iso8601 ~ DateTime.from_naive! の紹介
5.DateTimeモジュール で遊んでみたシリーズ番外編 -Livebookでtzdata導入
目的
DateTimeモジュールに含まれる関数を触って機能を理解したい
実行環境
Windows 11 + WSL2 + Ubuntu 22.04
Elixir v1.17.3
Erlang v27.0
前提
本記事を手元検証するには、前提としてtzdataの導入が必要です。
まだの場合は下記1.または2.で準備をしてください。
1.local環境でtzdataの導入
2.Livebookでtzdataの導入
DateTime.convertとは
DateTime.convert(datetime, calendar)
はdatetime
をcalendar
基準に変換したものを返します。
カレンダー間で明確に変換できない場合は{:error, :incompatible_calendars}
を返します。
例
※前提としてcalendar
の実装が必要です。
下記の例では現在のグレゴリオ暦に10000年を追加するカレンダーを実装しているとします。
dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
hour: 23, minute: 0, second: 7, microsecond: {0, 0},
utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
DateTime.convert(dt1, Calendar.Holocene)
{:ok, %DateTime{calendar: Calendar.Holocene, day: 29, hour: 23,
microsecond: {0, 0}, minute: 0, month: 2, second: 7, std_offset: 0,
time_zone: "America/Manaus", utc_offset: -14400, year: 12000,
zone_abbr: "AMT"}}
DateTime.convert!とは
DateTime.convert(datetime, calendar)
はdatetime
をcalendar
基準に変換したものを返します。
カレンダー間で明確に変換できない場合はArgumentError
を返します。
例
※前提としてcalendar
の実装が必要です。
下記の例では現在のグレゴリオ暦に10000年を追加するカレンダーを実装しているとします。
dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
hour: 23, minute: 0, second: 7, microsecond: {0, 0},
utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
DateTime.convert!(dt1, Calendar.Holocene)
変換に成功した場合DateTime.convert
は {:ok, Datetime構造体}
のタプル が返されるが、DateTime.convert!
は Datetime構造体 が返されるので注意。
%DateTime{calendar: Calendar.Holocene, day: 29, hour: 23,
microsecond: {0, 0}, minute: 0, month: 2, second: 7, std_offset: 0,
time_zone: "America/Manaus", utc_offset: -14400, year: 12000,
zone_abbr: "AMT"}
DateTime.diffとは
DateTime.diff(datetime1, datetime2, unit \\ :second)
はdatetime1
からdatetime2
を減算します。
結果はunit
単位で返されます。
例
DateTime.diff(~U[2024-01-15 10:00:10Z], ~U[2024-01-15 10:00:00Z])
10
datetime1
よりもdatetime2
が大きい場合
DateTime.diff(~U[2024-01-15 10:00:00Z], ~U[2024-01-15 10:00:10Z])
-10
unit
を変更した場合
小数の結果はサポートされておらず、切り捨てられます。
例
unit
変更前。2つのDatetime構造体には「1日(=86400秒) + 10秒」の差分があります。
DateTime.diff(~U[2024-01-16 10:00:10Z], ~U[2024-01-15 10:00:00Z])
86410
unit
変更後。10秒の差分が切り捨てられました。
DateTime.diff(~U[2024-01-16 10:00:10Z], ~U[2024-01-15 10:00:00Z], :day)
1
DateTime.from_gregorian_secondsとは
DateTime.from_gregorian_seconds(seconds, arg \\ {0, 0}, calendar \\ Calendar.ISO)
は現在のグレゴリオ暦基準で、seconds
をDatetime構造体に変換します。
seconds
特定の日付と時刻を秒数で示し、arg
で1秒以下の時刻を示します。
タイムゾーンはUTCで返されます。
UTC以外のタイムゾーンが必要な場合は、この関数の結果に対してDateTime.shift_zone/3
を使用してタイムゾーンを変換してください。
この関数の逆はDateTime.to_gregorian_seconds(datetime)
です。
例
DateTime.from_gregorian_seconds(1)
~U[0000-01-01 00:00:01Z]
DateTime.from_gregorian_seconds(63_872_532_000)
~U[2024-01-15 10:00:00Z]
余談
ISO 8601形式で0000年は現実の紀元前1年を指します。
現実には紀元1年の前は紀元前1年ですが、コンピュータにとって算術のしやすさを優先しています1
~Elixirの国のご案内~
↓Elixirって何ぞや?と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます
↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ!私もエンジニア未経験から学習中です。
↓We Are The Alchemists, my friends!2
Elixirコミュニティは本当に優しくて温かい人たちばかり!
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。3
-
https://ja.wikipedia.org/wiki/0%E5%B9%B4#%E8%A5%BF%E6%9A%A60%E5%B9%B4 ↩
-
@torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。 ↩