Data i czas

Obsługa czasu w Elixirze.

Time

Elixir ma kilka modułów związanych z reprezentacją i obsługą danych na temat czasu. Zacznijmy od sprawdzenia aktualnego czasu:

iex> Time.utc_now
~T[19:39:31.056226]

Zwróć uwagę na to, że jako wynik wywołanej funkcji otrzymaliśmy sigil — możemy go również użyć do stworzenia struktury Time:

iex> ~T[19:39:31.056226]
~T[19:39:31.056226]

O sigilach możesz przeczytać więcej w lekcji na ten temat. W łatwy sposób możemy pobrać części składowe tej struktury:

iex> t = ~T[19:39:31.056226]
~T[19:39:31.056226]
iex> t.hour
19
iex> t.minute
39
iex> t.day
** (KeyError) key :day not found in: ~T[19:39:31.056226]

I tu jest haczyk: co być może nie umknęło Twojej uwadze, struktura Time zawiera wyłącznie informacje o czasie, natomiast dane na temat dnia, miesiąca ani roku nie są w niej obecne.

Date

W przeciwieństwie do Time, struktura Date zawiera informacje o dacie, jednak nie przechowuje danych na temat czasu.

iex> Date.utc_today
~D[2028-10-21]

Moduł ten zawiera kilka użytecznych funkcji do pracy z datami:

iex> {:ok, date} = Date.new(2020, 12, 12)
{:ok, ~D[2020-12-12]}
iex> Date.day_of_week date
6
iex> Date.leap_year? date
true

day_of_week/1 zwraca numer dnia tygodnia. W powyższym przykładzie jest to sobota. leap_year?/1 sprawdza, czy dany rok jest przestępny. Więcej funkcji możesz znaleźć w dokumentacji.

NaiveDateTime

W Elixirze są dwa rodzaje struktur zawierających zarówno informację o dacie, jak i o czasie. Pierwszym z nich jest NaiveDateTime. Jego wadą jest brak danych o strefie czasowej:

iex(15)> NaiveDateTime.utc_now
~N[2029-01-21 19:55:10.008965]

Zawiera jednak i czas, i datę, więc możesz na przykład dodawać czas:

iex> NaiveDateTime.add(~N[2018-10-01 00:00:14], 30)
~N[2018-10-01 00:00:44]

DateTime

Drugi moduł, jak możesz wnioskować z tytułu tej sekcji, to DateTime. Nie ma on ograniczeń występujących w NaiveDateTime — zawiera czas i datę, a także obsługuje strefy czasowe. Na strefy czasowe należy jednak uważać. Oficjalna dokumentacja stwierdza:

Wiele funkcji w tym module wymaga bazy danych o strefach czasowych. Domyślnie używana jest baza zwracana przez funkcję Calendar.get_time_zone_database/0, domyślnie zwracającą Calendar.UTCOnlyTimeZoneDatabase, która obsługuje jedynie strefę “Etc/UTC” i zwraca {:error, :utc_only_time_zone_database} dla wszystkich innych stref czasowych.

Zauważyć należy również, że można utworzyć instancję DateTime z NaiveDateTime, przekazując do odpowiedniej funkcji informację o strefie czasowej:

iex> DateTime.from_naive(~N[2016-05-24 13:26:08.003], "Etc/UTC")
{:ok, #DateTime<2016-05-24 13:26:08.003Z>}

Strefy czasowe

Jak zauważyliśmy w poprzedniej sekcji, domyślnie Elixir nie zawiera żadnych informacji o strefach czasowych. Aby rozwiązać ten problem, możemy zainstalować i skonfigurować pakiet tzdata. Po zainstalowaniu go, należy globalnie skonfigurować Elixir tak, by używał Tzdata jako bazy danych o strefach czasowych:

config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase

Spróbujmy więc teraz stworzyć czas, używając strefy paryskiej, a następnie przekonwertować go na czas nowojorski:

iex> paris_datetime = DateTime.from_naive!(~N[2019-01-01 12:00:00], "Europe/Paris")
#DateTime<2019-01-01 12:00:00+01:00 CET Europe/Paris>
iex> {:ok, ny_datetime} = DateTime.shift_zone(paris_datetime, "America/New_York")
{:ok, #DateTime<2019-01-01 06:00:00-05:00 EST America/New_York>}
iex> ny_datetime
#DateTime<2019-01-01 06:00:00-05:00 EST America/New_York>

Jak możesz zauważyć, godzina zmieniła się z 12:00 czasu paryskiego na 6:00 czasu nowojorskiego, co jest w pełni poprawne — różnica czasu między Nowym Jorkiem a Paryżem wynosi właśnie 6 godzin.

I to by było na tyle! Jeśli chcesz dowiedzieć się o zaawansowanych funkcjach związanych z czasem i datami, rozważ przeczytanie dokumentacji Time, Date, DateTime i NaiveDateTime. Warto zajrzeć również do bibliotek Timex i Calendar, które są potęznymi narzędziami do pracy z czasem w Elixirze.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!