如果能将其包含在标准 Elixir 库中就好了,但我们没有。
Date.add(date, n, :month) # where n could be +/-
您将如何实施这个?
这看起来是一个很好的起点:https://stackoverflow.com/a/53407676/44080
Date.utc_today() |> Timex.shift(months: -1)
您可以使用 Timex 实现:
defp shift_by(%NaiveDateTime{:year => year, :month => month} = datetime, value, :months) do
m = month + value
shifted =
cond do
m > 0 ->
years = div(m - 1, 12)
month = rem(m - 1, 12) + 1
%{datetime | :year => year + years, :month => month}
m <= 0 ->
years = div(m, 12) - 1
month = 12 + rem(m, 12)
%{datetime | :year => year + years, :month => month}
end
# If the shift fails, it's because it's a high day number, and the month
# shifted to does not have that many days. This will be handled by always
# shifting to the last day of the month shifted to.
case :calendar.valid_date({shifted.year,shifted.month,shifted.day}) do
false ->
last_day = :calendar.last_day_of_the_month(shifted.year, shifted.month)
cond do
shifted.day <= last_day ->
shifted
:else ->
%{shifted | :day => last_day}
end
true ->
shifted
end
end
Timex 使用 MIT 许可证,因此您应该能够将其合并到几乎任何项目中。
ex_cldr_calendars 还可以对实现
Calendar
行为的任何日历进行基本日期数学运算,添加和减去年、季度、月、周和日。
iex> Cldr.Calendar.plus ~D[2019-03-31], :months, -1
~D[2019-02-28]
# The :coerce option determines whether to force an end
# of month date when the result of the operation is an invalid date
iex> Cldr.Calendar.plus ~D[2019-03-31], :months, -1, coerce: false
{:error, :invalid_date}
在不添加像 Timex 这样的依赖项的情况下,以下方法可以轻松添加/减去公历月份 - 假设您只需要每个月的第一天。考虑到有多少日历谬误,直接转换到一个月中的某一天可能最好通过图书馆来实现。
defmodule DateUtils
@doc """
Shift a given date forward or back n months
"""
def shift_n_months(date, n) when n < 0, do: subtract_n_months(date, -1 * n)
def shift_n_months(date, n), do: add_n_months(date, n)
def add_n_months(date, 0), do: Date.beginning_of_month(date)
def add_n_months(date, n) do
date
|> Date.end_of_month()
|> Date.add(1)
|> add_n_months(n - 1)
end
def subtract_n_months(date, 0), do: Date.beginning_of_month(date)
def subtract_n_months(date, n) do
date
|> Date.beginning_of_month()
|> Date.add(-1)
|> subtract_n_months(n - 1)
end
end
从 Elixir 1.17 开始,您可以使用 Elixir 的 Date.shift/2 函数来添加或减去持续时间
Date.shift/2 期望一个日期作为它的第一个参数,一个持续时间作为它的第二个参数。
以下是取自文档
的几个示例iex> Date.shift(~D[2016-01-03], month: 2)
~D[2016-03-03]
Date.shift(~D[2016-01-31], year: 4, day: 1).
~D[2020-02-01]
请注意,您可以使用正整数或负整数,具体取决于您要添加还是减去日期的持续时间。
Date.add/2
。给它任何日期,它会为您添加日期。
iex>Date.add(~D[2000-01-03], -2)
~D[2000-01-01]
Date.new/4
iex>{:ok, date} = Date.new(year, month, day)
iex>date |> Date.add(n)