查看源代码 Date (Elixir v1.16.2)
日期结构体和函数。
日期结构体包含年、月、日和日历字段。可以使用 new/3
函数或 ~D
(参见 sigil_D/2
)符号创建新的日期
iex> ~D[2000-01-01]
~D[2000-01-01]
new/3
函数和符号都会返回一个结构体,其中可以访问日期字段。
iex> date = ~D[2000-01-01]
iex> date.year
2000
iex> date.month
1
此模块中的函数适用于 Date
结构体,以及任何包含与 Date
结构体相同字段的结构体,例如 NaiveDateTime
和 DateTime
。这些函数在类型说明中使用 Calendar.date/0
(而不是 t/0
)。
开发者应该避免直接创建日期结构体,而是应该依赖此模块提供的函数以及第三方日历库提供的函数。
比较日期
Elixir 中使用 ==/2
、>/2
、</2
和类似的比较是结构性的,基于 Date
结构体的字段。要正确比较日期,请使用 compare/2
函数。此模块中 compare/2
函数的存在也允许使用 Enum.min/2
和 Enum.max/2
函数来获取 Enum
中的最小和最大日期。例如
iex> Enum.min([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-03-31]
使用纪元
add/2
和 diff/2
函数可用于计算日期或检索时间间隔之间的天数。例如,如果想计算从 Unix 纪元(1970-01-01)起的天数
iex> Date.diff(~D[2010-04-17], ~D[1970-01-01])
14716
iex> Date.add(~D[1970-01-01], 14716)
~D[2010-04-17]
这些函数经过优化,可以处理常见的纪元,例如上面的 Unix 纪元或公历纪元(0000-01-01)。
摘要
函数
将天数添加到给定的 date
。
如果第一个日期严格晚于第二个日期,则返回 true
。
如果第一个日期严格早于第二个日期,则返回 true
。
计算给定 date
的月份第一天对应的日期。
计算给定 date
的星期第一天对应的日期。
比较两个日期结构体。
将给定的 date
从其日历转换为给定的 calendar
。
类似于 Date.convert/2
,但如果两个日历之间的转换不可行,则会引发 ArgumentError
。
计算给定日历 date
的纪元日和纪元。
计算给定 date
的星期几。
计算给定 date
的一年中的第几天。
返回给定 date
月份的天数。
计算两个日期之间的差值,以完整的天数表示。
计算给定 date
的月份最后一天对应的日期。
计算给定 date
的星期最后一天对应的日期。
将 Erlang 日期元组转换为 Date
结构体。
将 Erlang 日期元组转换为,但对于无效日期会引发异常。
将公历天数转换为 Date
结构体。
解析 ISO 8601:2019 中描述的扩展“日期”格式。
解析 ISO 8601:2019 中描述的扩展“日期”格式。
如果给定 date
的年份是闰年,则返回 true
。
返回给定 date
年份的月份数。
构建一个新的 ISO 日期。
构建一个新的 ISO 日期。
计算给定 date
的一年中的季度。
返回一个日期范围。
返回具有步长的日期范围。
将给定的 date
转换为 Erlang 日期元组。
将 date
结构体转换为公历天数。
将给定的 date
转换为 ISO 8601:2019。
根据其日历将给定的日期转换为字符串。
返回当前的 UTC 日期。
计算给定日历年份的纪元年和纪元。
类型
@type t() :: %Date{ calendar: Calendar.calendar(), day: Calendar.day(), month: Calendar.month(), year: Calendar.year() }
函数
@spec add(Calendar.date(), integer()) :: t()
将天数添加到给定的 date
。
天数按公历天数计算。返回的日期与输入的日期使用相同的日历。
示例
iex> Date.add(~D[2000-01-03], -2)
~D[2000-01-01]
iex> Date.add(~D[2000-01-01], 2)
~D[2000-01-03]
iex> Date.add(~N[2000-01-01 09:00:00], 2)
~D[2000-01-03]
iex> Date.add(~D[-0010-01-01], -2)
~D[-0011-12-30]
@spec after?(Calendar.date(), Calendar.date()) :: boolean()
如果第一个日期严格晚于第二个日期,则返回 true
。
示例
iex> Date.after?(~D[2022-02-02], ~D[2021-01-01])
true
iex> Date.after?(~D[2021-01-01], ~D[2021-01-01])
false
iex> Date.after?(~D[2021-01-01], ~D[2022-02-02])
false
@spec before?(Calendar.date(), Calendar.date()) :: boolean()
如果第一个日期严格早于第二个日期,则返回 true
。
示例
iex> Date.before?(~D[2021-01-01], ~D[2022-02-02])
true
iex> Date.before?(~D[2021-01-01], ~D[2021-01-01])
false
iex> Date.before?(~D[2022-02-02], ~D[2021-01-01])
false
@spec beginning_of_month(Calendar.date()) :: t()
计算给定 date
的月份第一天对应的日期。
示例
iex> Date.beginning_of_month(~D[2000-01-31])
~D[2000-01-01]
iex> Date.beginning_of_month(~D[2000-01-01])
~D[2000-01-01]
iex> Date.beginning_of_month(~N[2000-01-31 01:23:45])
~D[2000-01-01]
@spec beginning_of_week(Calendar.date(), starting_on :: :default | atom()) :: t()
计算给定 date
的星期第一天对应的日期。
如果日期已经是星期第一天,则返回该日期本身。对于内置的 ISO 日历,星期从周一算起。可以将星期几而不是 :default
作为 starting_on
参数。
示例
iex> Date.beginning_of_week(~D[2020-07-11])
~D[2020-07-06]
iex> Date.beginning_of_week(~D[2020-07-06])
~D[2020-07-06]
iex> Date.beginning_of_week(~D[2020-07-11], :sunday)
~D[2020-07-05]
iex> Date.beginning_of_week(~D[2020-07-11], :saturday)
~D[2020-07-11]
iex> Date.beginning_of_week(~N[2020-07-11 01:23:45])
~D[2020-07-06]
@spec compare(Calendar.date(), Calendar.date()) :: :lt | :eq | :gt
比较两个日期结构体。
如果第一个日期晚于第二个日期,则返回 :gt
;反之则返回 :lt
。如果两个日期相等,则返回 :eq
。
示例
iex> Date.compare(~D[2016-04-16], ~D[2016-04-28])
:lt
此函数还可以用于比较更复杂的日历类型,方法是只考虑日期字段
iex> Date.compare(~D[2016-04-16], ~N[2016-04-28 01:23:45])
:lt
iex> Date.compare(~D[2016-04-16], ~N[2016-04-16 01:23:45])
:eq
iex> Date.compare(~N[2016-04-16 12:34:56], ~N[2016-04-16 01:23:45])
:eq
@spec convert(Calendar.date(), Calendar.calendar()) :: {:ok, t()} | {:error, :incompatible_calendars}
将给定的 date
从其日历转换为给定的 calendar
。
如果日历兼容,则返回 {:ok, date}
;如果不兼容,则返回 {:error, :incompatible_calendars}
。
另请参见 Calendar.compatible_calendars?/2
。
示例
假设有人实现了 Calendar.Holocene
,这是一个基于公历的日历,它将当前公历年份增加 10,000 年
iex> Date.convert(~D[2000-01-01], Calendar.Holocene)
{:ok, %Date{calendar: Calendar.Holocene, year: 12000, month: 1, day: 1}}
@spec convert!(Calendar.date(), Calendar.calendar()) :: t()
类似于 Date.convert/2
,但如果两个日历之间的转换不可行,则会引发 ArgumentError
。
示例
假设有人实现了 Calendar.Holocene
,这是一个基于公历的日历,它将当前公历年份增加 10,000 年
iex> Date.convert!(~D[2000-01-01], Calendar.Holocene)
%Date{calendar: Calendar.Holocene, year: 12000, month: 1, day: 1}
@spec day_of_era(Calendar.date()) :: {Calendar.day(), non_neg_integer()}
计算给定日历 date
的纪元日和纪元。
返回一个元组 {day, era}
,它表示纪元中的日期和纪元编号。
示例
iex> Date.day_of_era(~D[0001-01-01])
{1, 1}
iex> Date.day_of_era(~D[0000-12-31])
{1, 0}
@spec day_of_week(Calendar.date(), starting_on :: :default | atom()) :: Calendar.day_of_week()
计算给定 date
的星期几。
将星期几作为整数返回。对于 ISO 8601 日历(默认),它是一个从 1 到 7 的整数,其中 1 是周一,7 是周日。
可以提供一个可选的 starting_on
值,它配置星期开始的星期几。它的默认值为 :default
,对于内置的 ISO 日历,它对应于 :monday
。可以提供任何其他星期几。
示例
iex> Date.day_of_week(~D[2016-10-31])
1
iex> Date.day_of_week(~D[2016-11-01])
2
iex> Date.day_of_week(~N[2016-11-01 01:23:45])
2
iex> Date.day_of_week(~D[-0015-10-30])
3
iex> Date.day_of_week(~D[2016-10-31], :sunday)
2
iex> Date.day_of_week(~D[2016-11-01], :sunday)
3
iex> Date.day_of_week(~N[2016-11-01 01:23:45], :sunday)
3
iex> Date.day_of_week(~D[-0015-10-30], :sunday)
4
@spec day_of_year(Calendar.date()) :: Calendar.day()
计算给定 date
的一年中的第几天。
将一年中的第几天作为整数返回。对于 ISO 8601 日历(默认),它是一个从 1 到 366 的整数。
示例
iex> Date.day_of_year(~D[2016-01-01])
1
iex> Date.day_of_year(~D[2016-11-01])
306
iex> Date.day_of_year(~D[-0015-10-30])
303
iex> Date.day_of_year(~D[2004-12-31])
366
@spec days_in_month(Calendar.date()) :: Calendar.day()
返回给定 date
月份的天数。
示例
iex> Date.days_in_month(~D[1900-01-13])
31
iex> Date.days_in_month(~D[1900-02-09])
28
iex> Date.days_in_month(~N[2000-02-20 01:23:45])
29
@spec diff(Calendar.date(), Calendar.date()) :: integer()
计算两个日期之间的差值,以完整的天数表示。
它返回两个日期之间的格里高利日数。仅当两个 Date
结构遵循相同或兼容的日历时,才能以这种方式进行比较。如果两个日历不兼容,它将引发错误。
示例
iex> Date.diff(~D[2000-01-03], ~D[2000-01-01])
2
iex> Date.diff(~D[2000-01-01], ~D[2000-01-03])
-2
iex> Date.diff(~D[0000-01-02], ~D[-0001-12-30])
3
iex> Date.diff(~D[2000-01-01], ~N[2000-01-03 09:00:00])
-2
@spec end_of_month(Calendar.date()) :: t()
计算给定 date
的月份最后一天对应的日期。
示例
iex> Date.end_of_month(~D[2000-01-01])
~D[2000-01-31]
iex> Date.end_of_month(~D[2000-01-31])
~D[2000-01-31]
iex> Date.end_of_month(~N[2000-01-01 01:23:45])
~D[2000-01-31]
@spec end_of_week(Calendar.date(), starting_on :: :default | atom()) :: t()
计算给定 date
的星期最后一天对应的日期。
如果该日已经是该周的最后一天,则返回该日本身。对于内置的 ISO 日历,一周以周日结束。可以给出工作日而不是 :default
作为 starting_on
。
示例
iex> Date.end_of_week(~D[2020-07-11])
~D[2020-07-12]
iex> Date.end_of_week(~D[2020-07-05])
~D[2020-07-05]
iex> Date.end_of_week(~D[2020-07-06], :sunday)
~D[2020-07-11]
iex> Date.end_of_week(~D[2020-07-06], :saturday)
~D[2020-07-10]
iex> Date.end_of_week(~N[2020-07-11 01:23:45])
~D[2020-07-12]
@spec from_erl(:calendar.date(), Calendar.calendar()) :: {:ok, t()} | {:error, atom()}
将 Erlang 日期元组转换为 Date
结构体。
仅支持转换处于 ISO 日历中的日期,或其他日历,其中日期也从午夜开始。尝试转换来自其他日历的日期将返回一个错误元组。
示例
iex> Date.from_erl({2000, 1, 1})
{:ok, ~D[2000-01-01]}
iex> Date.from_erl({2000, 13, 1})
{:error, :invalid_date}
@spec from_erl!(:calendar.date(), Calendar.calendar()) :: t()
将 Erlang 日期元组转换为,但对于无效日期会引发异常。
示例
iex> Date.from_erl!({2000, 1, 1})
~D[2000-01-01]
iex> Date.from_erl!({2000, 13, 1})
** (ArgumentError) cannot convert {2000, 13, 1} to date, reason: :invalid_date
@spec from_gregorian_days(integer(), Calendar.calendar()) :: t()
将公历天数转换为 Date
结构体。
示例
iex> Date.from_gregorian_days(1)
~D[0000-01-02]
iex> Date.from_gregorian_days(730_485)
~D[2000-01-01]
iex> Date.from_gregorian_days(-1)
~D[-0001-12-31]
@spec from_iso8601(String.t(), Calendar.calendar()) :: {:ok, t()} | {:error, atom()}
解析 ISO 8601:2019 中描述的扩展“日期”格式。
此函数解析的年份限制为四位数字。
示例
iex> Date.from_iso8601("2015-01-23")
{:ok, ~D[2015-01-23]}
iex> Date.from_iso8601("2015:01:23")
{:error, :invalid_format}
iex> Date.from_iso8601("2015-01-32")
{:error, :invalid_date}
@spec from_iso8601!(String.t(), Calendar.calendar()) :: t()
解析 ISO 8601:2019 中描述的扩展“日期”格式。
如果格式无效,则会引发错误。
示例
iex> Date.from_iso8601!("2015-01-23")
~D[2015-01-23]
iex> Date.from_iso8601!("2015:01:23")
** (ArgumentError) cannot parse "2015:01:23" as date, reason: :invalid_format
@spec leap_year?(Calendar.date()) :: boolean()
如果给定 date
的年份是闰年,则返回 true
。
示例
iex> Date.leap_year?(~D[2000-01-01])
true
iex> Date.leap_year?(~D[2001-01-01])
false
iex> Date.leap_year?(~D[2004-01-01])
true
iex> Date.leap_year?(~D[1900-01-01])
false
iex> Date.leap_year?(~N[2004-01-01 01:23:45])
true
@spec months_in_year(Calendar.date()) :: Calendar.month()
返回给定 date
年份的月份数。
示例
iex> Date.months_in_year(~D[1900-01-13])
12
@spec new(Calendar.year(), Calendar.month(), Calendar.day(), Calendar.calendar()) :: {:ok, t()} | {:error, atom()}
构建一个新的 ISO 日期。
期望所有值都是整数。如果每个条目都符合其适当的范围,则返回 {:ok, date}
,否则返回 {:error, reason}
。
示例
iex> Date.new(2000, 1, 1)
{:ok, ~D[2000-01-01]}
iex> Date.new(2000, 13, 1)
{:error, :invalid_date}
iex> Date.new(2000, 2, 29)
{:ok, ~D[2000-02-29]}
iex> Date.new(2000, 2, 30)
{:error, :invalid_date}
iex> Date.new(2001, 2, 29)
{:error, :invalid_date}
@spec new!(Calendar.year(), Calendar.month(), Calendar.day(), Calendar.calendar()) :: t()
构建一个新的 ISO 日期。
期望所有值都是整数。如果每个条目都符合其适当的范围,则返回 date
,如果日期无效,则会引发错误。
示例
iex> Date.new!(2000, 1, 1)
~D[2000-01-01]
iex> Date.new!(2000, 13, 1)
** (ArgumentError) cannot build date, reason: :invalid_date
iex> Date.new!(2000, 2, 29)
~D[2000-02-29]
@spec quarter_of_year(Calendar.date()) :: non_neg_integer()
计算给定 date
的一年中的季度。
返回一年中的第几天作为整数。对于 ISO 8601 日历(默认值),它是 1 到 4 之间的整数。
示例
iex> Date.quarter_of_year(~D[2016-10-31])
4
iex> Date.quarter_of_year(~D[2016-01-01])
1
iex> Date.quarter_of_year(~N[2016-04-01 01:23:45])
2
iex> Date.quarter_of_year(~D[-0015-09-30])
3
@spec range(Calendar.date(), Calendar.date()) :: Date.Range.t()
返回一个日期范围。
日期范围表示一组离散的日期,其中第一个和最后一个值是具有匹配日历的日期。
日期范围可以是递增的 (first <= last
) 并且总是包含边界。对于递减范围,请使用 range/3
,并将 -1 作为步长作为第一个参数。
示例
iex> Date.range(~D[1999-01-01], ~D[2000-01-01])
Date.range(~D[1999-01-01], ~D[2000-01-01])
日期范围实现了 Enumerable
协议,这意味着 Enum
模块中的函数可以用于处理范围
iex> range = Date.range(~D[2001-01-01], ~D[2002-01-01])
iex> range
Date.range(~D[2001-01-01], ~D[2002-01-01])
iex> Enum.count(range)
366
iex> ~D[2001-02-01] in range
true
iex> Enum.take(range, 3)
[~D[2001-01-01], ~D[2001-01-02], ~D[2001-01-03]]
@spec range(Calendar.date(), Calendar.date(), step :: pos_integer() | neg_integer()) :: Date.Range.t()
返回具有步长的日期范围。
示例
iex> range = Date.range(~D[2001-01-01], ~D[2002-01-01], 2)
iex> range
Date.range(~D[2001-01-01], ~D[2002-01-01], 2)
iex> Enum.count(range)
183
iex> ~D[2001-01-03] in range
true
iex> Enum.take(range, 3)
[~D[2001-01-01], ~D[2001-01-03], ~D[2001-01-05]]
@spec to_erl(Calendar.date()) :: :calendar.date()
将给定的 date
转换为 Erlang 日期元组。
仅支持转换处于 ISO 日历中的日期,或其他日历,其中日期也从午夜开始。尝试转换来自其他日历的日期将引发错误。
示例
iex> Date.to_erl(~D[2000-01-01])
{2000, 1, 1}
iex> Date.to_erl(~N[2000-01-01 00:00:00])
{2000, 1, 1}
@spec to_gregorian_days(Calendar.date()) :: integer()
将 date
结构体转换为公历天数。
示例
iex> Date.to_gregorian_days(~D[0000-01-02])
1
iex> Date.to_gregorian_days(~D[2000-01-01])
730_485
iex> Date.to_gregorian_days(~N[2000-01-01 00:00:00])
730_485
@spec to_iso8601(Calendar.date(), :extended | :basic) :: String.t()
将给定的 date
转换为 ISO 8601:2019。
默认情况下,Date.to_iso8601/2
以“扩展”格式返回日期,以便于人类阅读。它还支持通过传递 :basic
选项的“基本”格式。
仅支持转换处于 ISO 日历中的日期,或其他日历,其中日期也从午夜开始。尝试转换来自其他日历的日期将引发一个 ArgumentError
错误。
示例
iex> Date.to_iso8601(~D[2000-02-28])
"2000-02-28"
iex> Date.to_iso8601(~D[2000-02-28], :basic)
"20000228"
iex> Date.to_iso8601(~N[2000-02-28 00:00:00])
"2000-02-28"
@spec to_string(Calendar.date()) :: String.t()
根据其日历将给定的日期转换为字符串。
示例
iex> Date.to_string(~D[2000-02-28])
"2000-02-28"
iex> Date.to_string(~N[2000-02-28 01:23:45])
"2000-02-28"
iex> Date.to_string(~D[-0100-12-15])
"-0100-12-15"
@spec utc_today(Calendar.calendar()) :: t()
返回当前的 UTC 日期。
示例
iex> date = Date.utc_today()
iex> date.year >= 2016
true
@spec year_of_era(Calendar.date()) :: {Calendar.year(), non_neg_integer()}
计算给定日历年份的纪元年和纪元。
返回一个元组 {year, era}
,表示纪元中的年份和纪元号。
示例
iex> Date.year_of_era(~D[0001-01-01])
{1, 1}
iex> Date.year_of_era(~D[0000-12-31])
{1, 0}
iex> Date.year_of_era(~D[-0001-01-01])
{2, 0}