diff --git a/config/config.exs b/config/config.exs
index c72cd990..b3f54d13 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -7,6 +7,10 @@
# General application configuration
import Config
+config :elixir, :time_zone_database, TimeZoneInfo.TimeZoneDatabase
+
+config :time_zone_info, update: :daily
+
config :music_library,
ecto_repos: [MusicLibrary.Repo, MusicLibrary.ErrorRepo],
generators: [timestamp_type: :utc_datetime, binary_id: true]
diff --git a/lib/music_library_web/live/stats_live/index.ex b/lib/music_library_web/live/stats_live/index.ex
index 24728398..6f1941b2 100644
--- a/lib/music_library_web/live/stats_live/index.ex
+++ b/lib/music_library_web/live/stats_live/index.ex
@@ -10,6 +10,8 @@ defmodule MusicLibraryWeb.StatsLive.Index do
attr :title, :string, required: true
attr :class, :string
+ @timezone "Europe/London"
+
defp album_preview(assigns) do
~H"""
+ %{
+ t
+ | scrobbled_at_label: localize_scrobbled_at(t.scrobbled_at_uts, @timezone)
+ }
+ end)
+
+ recent_release_ids = recent_release_ids(localized_recent_tracks)
collected_releases = Collection.collected_releases(recent_release_ids)
wishlisted_releases = Wishlist.wishlisted_releases(recent_release_ids)
all_artist_ids = Artists.get_all_artist_ids()
- recent_artist_ids = recent_artist_ids(recent_tracks)
+ recent_artist_ids = recent_artist_ids(localized_recent_tracks)
artist_ids = MapSet.intersection(all_artist_ids, recent_artist_ids)
recent_albums =
- recent_tracks
+ localized_recent_tracks
|> Enum.uniq_by(fn t -> t.album end)
|> Enum.map(fn t ->
%{
@@ -190,7 +200,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
end)
socket
- |> stream(:recent_tracks, recent_tracks, reset: true)
+ |> stream(:recent_tracks, localized_recent_tracks, reset: true)
|> stream(:recent_albums, recent_albums, reset: true)
|> assign(
collected_releases: collected_releases,
@@ -220,6 +230,15 @@ defmodule MusicLibraryWeb.StatsLive.Index do
end)
end
+ defp localize_scrobbled_at(uts, timezone) do
+ ldt =
+ uts
+ |> DateTime.from_unix!()
+ |> DateTime.shift_zone!(timezone)
+
+ "#{ldt.day}/#{ldt.month}/#{ldt.year} #{ldt.hour}:#{ldt.minute}"
+ end
+
# The Tailwind build step requires all needed classes to be explicitly referenced
# in the source code, and not dynamically generated. This implies that one cannot
# (for example) interpolate a number in a class name.
diff --git a/mix.exs b/mix.exs
index 6bb5ff78..2fd288b0 100644
--- a/mix.exs
+++ b/mix.exs
@@ -80,6 +80,9 @@ defmodule MusicLibrary.MixProject do
# Image manipulation
{:vix, "~> 0.33.0"},
+ # Time-zone support - requires mint and castore
+ {:time_zone_info, "~> 0.7.8"},
+
# Data validation
{:nimble_options, "~> 1.1"},
diff --git a/mix.lock b/mix.lock
index b4a46c9c..2e4f23cf 100644
--- a/mix.lock
+++ b/mix.lock
@@ -51,6 +51,7 @@
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"},
"telemetry_poller": {:hex, :telemetry_poller, "1.2.0", "ba82e333215aed9dd2096f93bd1d13ae89d249f82760fcada0850ba33bac154b", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7216e21a6c326eb9aa44328028c34e9fd348fb53667ca837be59d0aa2a0156e8"},
"thousand_island": {:hex, :thousand_island, "1.3.12", "590ff651a6d2a59ed7eabea398021749bdc664e2da33e0355e6c64e7e1a2ef93", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "55d0b1c868b513a7225892b8a8af0234d7c8981a51b0740369f3125f7c99a549"},
+ "time_zone_info": {:hex, :time_zone_info, "0.7.8", "5b0e2b6b4af7b7526ef519dfd919d9d89d493a7b5e12a07434f2760dd5fe8be0", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "307d3fab87679e80888ce39fdfcf44a8fd6189cefc2fca3a83fb5c1097efa40e"},
"vix": {:hex, :vix, "0.33.0", "cd98084529fd8fe3d2336f157db6de03b297fb096508d820068117d58eadb6f1", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "9acde72b27bdfeadeb51f790f7a6cc0d06cf555718c05cf57e43c5cf93d8471b"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},