Retrieving the first and last day of previous month to build a query with a range date?

Hi,

I try to retrieve the first and last day of previous month to build a query with a range date.

Right now I’m doing this:

def foo(%DateTime{month: month, year: year} = current_date) do

  # eg. 2019-01-01 00:00:00
  start_date = %{current_date | month: month - 1, day: 1, hour: 00, minute: 00, second: 00}

  days_of_month = DateTime.to_date(start_date) |> Date.days_in_month()

  # eg. 2019-01-31 23:59:59
  end_date = DateTime.add(start_date, (days_of_month - 1) * 86_400 + 86_399, :seconds)

  ...
end

For the moment I don’t handle the year change :smile: , but before continuing I wanted to know if you had another way of doing it.

Thanks

Please don’t do such calculations on your own you’re bound to get into trouble with things like daylight-savings time switches or leap-seconds and things like that. Use a library like timex or calendar for calculations on datetimes.

7 Likes

Oh yes, my bad, timex has everything I need.

Thanks

2 Likes

And when timex is not an option, one could use the API that comes with elixir to handle date a safer way too. Like DateTime.add or DateTime.diff for example.

To get the last day of previous month with bare Elixir for example:

datetime = DateTime.utc_now()
date = DateTime.to_date(datetime)
last_day_of_previous_month = Date.add(date, date.day * -1)
end_of_last_day_on_original_timezone = last_day_of_previous_month |> NaiveDateTime.new(~T[23:59:59]) |> DateTime.from_naive(datetime.time_zone)

Just in case someone stumbles across this, there are built-in functions to help with these calculations.

iex> Date.beginning_of_month(~D[2000-01-31])
~D[2000-01-01]
iex> Date.end_of_month(~D[2000-01-01])
~D[2000-01-31]

https://hexdocs.pm/elixir/Date.html#beginning_of_month/1

4 Likes