From b5d883c8bbd44dcbdee6ca6f8dc5f37acbb899dc Mon Sep 17 00:00:00 2001 From: Scott Bradshaw Date: Tue, 7 Feb 2023 03:58:33 -0500 Subject: [PATCH] Add support for epoch time (%s) to Calendar strftime (#12380) --- lib/elixir/lib/calendar.ex | 29 ++++++++++++++++++++++++ lib/elixir/test/elixir/calendar_test.exs | 20 ++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/elixir/lib/calendar.ex b/lib/elixir/lib/calendar.ex index 073e05a6cc..b0e145618a 100644 --- a/lib/elixir/lib/calendar.ex +++ b/lib/elixir/lib/calendar.ex @@ -464,6 +464,7 @@ defmodule Calendar do p | "AM" or "PM" (noon is "PM", midnight as "AM") | AM, PM P | "am" or "pm" (noon is "pm", midnight as "am") | am, pm q | Quarter | 1, 2, 3, 4 + s | Number of seconds since the Epoch, 1970-01-01 00:00:00+0000 (UTC) | 1565888877 S | Second | 00, 59, 60 u | Day of the week | 1 (Monday), 7 (Sunday) x | Preferred date (without time) representation | 2018-10-17 @@ -804,6 +805,34 @@ defmodule Calendar do parse(rest, datetime, format_options, [result | acc]) end + # Epoch time for DateTime with time zones + defp format_modifiers( + "s" <> rest, + _width, + _pad, + datetime = %{utc_offset: _utc_offset, std_offset: _std_offset}, + format_options, + acc + ) do + result = + datetime + |> DateTime.shift_zone!("Etc/UTC") + |> NaiveDateTime.diff(~N[1970-01-01 00:00:00]) + |> Integer.to_string() + + parse(rest, datetime, format_options, [result | acc]) + end + + # Epoch time + defp format_modifiers("s" <> rest, _width, _pad, datetime, format_options, acc) do + result = + datetime + |> NaiveDateTime.diff(~N[1970-01-01 00:00:00]) + |> Integer.to_string() + + parse(rest, datetime, format_options, [result | acc]) + end + # +hhmm/-hhmm time zone offset from UTC (empty string if naive) defp format_modifiers( "z" <> rest, diff --git a/lib/elixir/test/elixir/calendar_test.exs b/lib/elixir/test/elixir/calendar_test.exs index 0eb98f3c5f..2d427214f0 100644 --- a/lib/elixir/test/elixir/calendar_test.exs +++ b/lib/elixir/test/elixir/calendar_test.exs @@ -336,6 +336,26 @@ defmodule CalendarTest do assert Calendar.strftime(~N[2019-08-15 17:07:57], "%010A") == "00Thursday" end + test "formats Epoch time with %s" do + assert Calendar.strftime(~N[2019-08-15 17:07:57], "%s") == "1565888877" + + datetime = %DateTime{ + year: 2019, + month: 8, + day: 15, + hour: 17, + minute: 7, + second: 57, + microsecond: {0, 0}, + time_zone: "Europe/Berlin", + zone_abbr: "CET", + utc_offset: 3600, + std_offset: 0 + } + + assert Calendar.strftime(datetime, "%s") == "1565885277" + end + test "formats datetime with all options and modifiers" do assert Calendar.strftime( ~U[2019-08-15 17:07:57.001Z],