查看源代码 Calendar 行为 (Elixir v1.16.2)
该模块定义了在 Elixir 中处理日历、日期、时间和日期时间的职责。
它定义了 Elixir 中日历行为的类型和最小实现。Elixir 中日历功能的目标是提供互操作性的基础,而不是提供完整的日期时间 API。
对于实际的日期、时间和日期时间结构体,请参阅 Date
、Time
、NaiveDateTime
和 DateTime
。
年份、月份、日期等类型是 *过度指定的*。例如,month/0
类型被指定为整数,而不是 1..12
。这是因为不同的日历可能每个月的日期数不同。
摘要
类型
一个日历实现。
任何包含日期字段的映射或结构体。
任何包含日期时间字段的映射或结构体。
在日历之间转换时使用内部时间格式。
表示 day
和 era
的元组。
在日历之间转换时使用的内部日期格式。
带有存储精度的微秒。
任何包含朴素日期时间字段的映射或结构体。
时区标准偏移量,单位为秒(通常在夏令时不为零)。
任何包含时间字段的映射或结构体。
根据 IANA tz 数据库的时区 ID(例如,Europe/Zurich
)。
指定日历操作的时区数据库。
标准时间的时区 UTC 偏移量,单位为秒。
时区缩写(例如,CET
或 CEST
或 BST
)。
回调
根据日历将日期转换为字符串。
根据日历将日期时间(带时区)转换为字符串。
根据给定的 year
、month
和 day
计算日期和纪元。
根据给定的 year
、month
和 day
计算星期几。
根据给定的 year
、month
和 day
计算一年中的第几天。
定义日历的滚动时刻。
返回给定年份中给定月份的天数。
将给定的 iso_days/0
转换为一天的第一个时刻。
将给定的 iso_days/0
转换为一天的最后一个时刻。
如果给定年份是闰年,则返回 true
。
返回给定年份中的月份数。
将 iso_days/0
转换为日历的日期时间格式。
将日期时间(无时区)转换为 iso_days/0
格式。
根据日历将朴素日期时间(无时区)转换为字符串。
将 date_to_string/3
返回的日期字符串表示形式解析为日期元组。
将 naive_datetime_to_string/7
返回的朴素日期时间字符串表示形式解析为朴素日期时间元组。
将 time_to_string/4
返回的时间字符串表示形式解析为时间元组。
将 datetime_to_string/11
返回的日期时间字符串表示形式解析为日期时间元组。
根据给定的 year
、month
和 day
计算一年中的季度。
将 day_fraction/0
转换为日历的时间格式。
根据日历将时间转换为字符串。
如果给定日期在日历中描述了一个正确的日期,则应返回 true
。
如果给定时间在日历中描述了一个正确的时间,则应返回 true
。
根据给定的 year
计算年份和纪元。
函数
如果两个日历在开始新的一天的时间相同,则返回 true
,否则返回 false
。
获取当前时区数据库。
设置当前时区数据库。
将给定的日期、时间或日期时间格式化为字符串。
返回一个微秒元组,截断到给定的精度 (:microsecond
、:millisecond
或 :second
)。
类型
@type calendar() :: module()
一个日历实现。
@type date() :: %{ optional(any()) => any(), calendar: calendar(), year: year(), month: month(), day: day() }
任何包含日期字段的映射或结构体。
@type datetime() :: %{ optional(any()) => any(), calendar: calendar(), year: year(), month: month(), day: day(), hour: hour(), minute: minute(), second: second(), microsecond: microsecond(), time_zone: time_zone(), zone_abbr: zone_abbr(), utc_offset: utc_offset(), std_offset: std_offset() }
任何包含日期时间字段的映射或结构体。
@type day() :: pos_integer()
@type day_fraction() :: {parts_in_day :: non_neg_integer(), parts_per_day :: pos_integer()}
在日历之间转换时使用内部时间格式。
它将时间表示为一天的几分之一(从午夜开始)。parts_in_day
指定一天已经过去了多少,而 parts_per_day
表示一天有多少部分。
@type day_of_era() :: {day :: non_neg_integer(), era()}
表示 day
和 era
的元组。
@type day_of_week() :: non_neg_integer()
@type era() :: non_neg_integer()
@type hour() :: non_neg_integer()
@type iso_days() :: {days :: integer(), day_fraction()}
在日历之间转换时使用的内部日期格式。
这是自 ISO 8601 表示法中 0000-01-01+00:00T00:00.000000
(也称为 *公元前 1 年 1 月 1 日午夜* 的前格里高利历)以来,包括最后一天已过部分的总天数。
@type microsecond() :: {value :: non_neg_integer(), precision :: non_neg_integer()}
带有存储精度的微秒。
精度表示在将微秒表示为外部格式时必须使用的位数。如果精度为 0
,则表示必须跳过微秒。
@type minute() :: non_neg_integer()
@type month() :: pos_integer()
@type naive_datetime() :: %{ optional(any()) => any(), calendar: calendar(), year: year(), month: month(), day: day(), hour: hour(), minute: minute(), second: second(), microsecond: microsecond() }
任何包含朴素日期时间字段的映射或结构体。
@type second() :: non_neg_integer()
@type std_offset() :: integer()
时区标准偏移量,单位为秒(通常在夏令时不为零)。
它必须添加到 utc_offset/0
,以获得用于“墙上时间”的 UTC 总偏移量。
@type time() :: %{ optional(any()) => any(), hour: hour(), minute: minute(), second: second(), microsecond: microsecond() }
任何包含时间字段的映射或结构体。
@type time_zone() :: String.t()
根据 IANA tz 数据库的时区 ID(例如,Europe/Zurich
)。
@type time_zone_database() :: module()
指定日历操作的时区数据库。
DateTime
模块中的许多函数都需要时区数据库。默认情况下,该模块使用 Calendar.get_time_zone_database/0
返回的默认时区数据库,该数据库默认为 Calendar.UTCOnlyTimeZoneDatabase
。此数据库仅处理 Etc/UTC
日期时间,对于任何其他时区都返回 {:error, :utc_only_time_zone_database}
。
其他时区数据库(包括包提供的数据库)可以通过配置进行配置
config :elixir, :time_zone_database, CustomTimeZoneDatabase
或通过调用 Calendar.put_time_zone_database/1
进行配置。
有关自定义时区数据库的更多信息,请参见 Calendar.TimeZoneDatabase
。
@type utc_offset() :: integer()
标准时间的时区 UTC 偏移量,单位为秒。
另请参阅 std_offset/0
。
@type week() :: pos_integer()
@type year() :: integer()
@type zone_abbr() :: String.t()
时区缩写(例如,CET
或 CEST
或 BST
)。
回调
根据日历将日期转换为字符串。
datetime_to_string( year, month, day, hour, minute, second, microsecond, time_zone, zone_abbr, utc_offset, std_offset )
查看源代码@callback datetime_to_string( year(), month(), day(), hour(), minute(), second(), microsecond(), time_zone(), zone_abbr(), utc_offset(), std_offset() ) :: String.t()
根据日历将日期时间(带时区)转换为字符串。
@callback day_of_era(year(), month(), day()) :: day_of_era()
根据给定的 year
、month
和 day
计算日期和纪元。
@callback day_of_week(year(), month(), day(), starting_on :: :default | atom()) :: {day_of_week(), first_day_of_week :: non_neg_integer(), last_day_of_week :: non_neg_integer()}
根据给定的 year
、month
和 day
计算星期几。
starting_on
表示一周的开始日期。所有日历至少必须支持 :default
值。它们还可以支持其他表示其星期几的值。
@callback day_of_year(year(), month(), day()) :: non_neg_integer()
根据给定的 year
、month
和 day
计算一年中的第几天。
@callback day_rollover_relative_to_midnight_utc() :: day_fraction()
定义日历的滚动时刻。
这是在你的日历中,当前一天结束和下一天开始的时刻。
此函数的结果用于检查两个日历是否在一天中的同一时间滚动。如果它们没有,我们只能在它们之间转换日期时间和时间。如果它们确实如此,这意味着我们还可以转换日期以及它们之间的朴素日期时间。
此日分数应尽可能简化,以使比较速度更快。
示例
- 如果在你的日历中,新的一天从午夜开始,则返回
{0, 1}
。 - 如果在你的日历中,新的一天从日出开始,则返回
{1, 4}
。 - 如果在你的日历中,新的一天从中午开始,则返回
{1, 2}
。 - 如果在你的日历中,新的一天从日落开始,则返回
{3, 4}
。
返回给定年份中给定月份的天数。
将给定的 iso_days/0
转换为一天的第一个时刻。
将给定的 iso_days/0
转换为一天的最后一个时刻。
如果给定年份是闰年,则返回 true
。
闰年是指比正常年份更长的年份。确切的含义取决于日历。如果日历不支持闰年的概念,则必须返回 false
。
返回给定年份中的月份数。
@callback naive_datetime_from_iso_days(iso_days()) :: {year(), month(), day(), hour(), minute(), second(), microsecond()}
将 iso_days/0
转换为日历的日期时间格式。
@callback naive_datetime_to_iso_days( year(), month(), day(), hour(), minute(), second(), microsecond() ) :: iso_days()
将日期时间(无时区)转换为 iso_days/0
格式。
@callback naive_datetime_to_string( year(), month(), day(), hour(), minute(), second(), microsecond() ) :: String.t()
根据日历将朴素日期时间(无时区)转换为字符串。
将 date_to_string/3
返回的日期字符串表示形式解析为日期元组。
@callback parse_naive_datetime(String.t()) :: {:ok, {year(), month(), day(), hour(), minute(), second(), microsecond()}} | {:error, atom()}
将 naive_datetime_to_string/7
返回的朴素日期时间字符串表示形式解析为朴素日期时间元组。
给定字符串可能包含时区偏移量,但会被忽略。
@callback parse_time(String.t()) :: {:ok, {hour(), minute(), second(), microsecond()}} | {:error, atom()}
将 time_to_string/4
返回的时间字符串表示形式解析为时间元组。
@callback parse_utc_datetime(String.t()) :: {:ok, {year(), month(), day(), hour(), minute(), second(), microsecond()}, utc_offset()} | {:error, atom()}
将 datetime_to_string/11
返回的日期时间字符串表示形式解析为日期时间元组。
返回的日期时间必须为 UTC。它所写的原始 utc_offset
必须在结果中返回。
@callback quarter_of_year(year(), month(), day()) :: non_neg_integer()
根据给定的 year
、month
和 day
计算一年中的季度。
@callback time_from_day_fraction(day_fraction()) :: {hour(), minute(), second(), microsecond()}
将 day_fraction/0
转换为日历的时间格式。
@callback time_to_day_fraction(hour(), minute(), second(), microsecond()) :: day_fraction()
将给定时间转换为 day_fraction/0
格式。
@callback time_to_string(hour(), minute(), second(), microsecond()) :: String.t()
根据日历将时间转换为字符串。
如果给定日期在日历中描述了一个正确的日期,则应返回 true
。
@callback valid_time?(hour(), minute(), second(), microsecond()) :: boolean()
如果给定时间在日历中描述了一个正确的时间,则应返回 true
。
根据给定的 year
计算年份和纪元。
函数
如果两个日历在开始新的一天的时间相同,则返回 true
,否则返回 false
。
如果两个日历不兼容,我们只能在它们之间转换日期时间和时间。如果它们兼容,这意味着我们还可以转换日期以及它们之间的原始日期时间。
@spec get_time_zone_database() :: time_zone_database()
获取当前时区数据库。
@spec put_time_zone_database(time_zone_database()) :: :ok
设置当前时区数据库。
将给定的日期、时间或日期时间格式化为字符串。
日期时间可以是任何 Calendar
类型(Time
、Date
、NaiveDateTime
和 DateTime
)或任何映射,只要它们包含所有格式化所需的相关字段即可。例如,如果您使用 %Y
格式化年份,则日期时间必须具有 :year
字段。因此,如果您传递一个 Time
或者一个没有 :year
字段的映射到一个期望 %Y
的格式,则会引发错误。
常用用法示例
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%y-%m-%d %I:%M:%S %p")
"19-08-26 01:52:06 PM"
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%a, %B %d %Y")
"Mon, August 26 2019"
用户选项
:preferred_datetime
- 用于显示日期时间的首选格式的字符串,它不能包含%c
格式,如果未接收该选项,则默认为"%Y-%m-%d %H:%M:%S"
:preferred_date
- 用于显示日期的首选格式的字符串,它不能包含%x
格式,如果未接收该选项,则默认为"%Y-%m-%d"
:preferred_time
- 用于显示时间的首选格式的字符串,它不能包含%X
格式,如果未接收该选项,则默认为"%H:%M:%S"
:am_pm_names
- 一个接收:am
或:pm
并返回一天中时间段名称的函数,如果未接收该选项,则默认为一个返回"am"
和"pm"
的函数,分别:month_names
- 一个接收数字并返回对应月份名称的函数,如果未接收该选项,则默认为一个返回英文月份名称的函数:abbreviated_month_names
- 一个接收数字并返回对应月份缩写名称的函数,如果未接收该选项,则默认为一个返回英文月份缩写名称的函数:day_of_week_names
- 一个接收数字并返回对应星期名称的函数,如果未接收该选项,则默认为一个返回英文星期名称的函数:abbreviated_day_of_week_names
- 一个接收数字并返回对应星期缩写名称的函数,如果未接收该选项,则默认为一个返回英文星期缩写名称的函数
格式化语法
string_format
参数的格式化语法是以下格式的字符序列
%<padding><width><format>
其中
%
: 表示格式化部分的开始<padding>
: 设置填充(见下文)<width>
: 表示格式化部分最小大小的数字<format>
: 格式本身(见下文)
可接受的填充选项
-
: 无填充,从格式中删除所有填充_
: 用空格填充0
: 用零填充
可接受的字符串格式
string_format
的可接受格式是
格式 | 描述 | 示例(以 ISO 格式) |
---|---|---|
a | 星期的缩写名称 | Mon |
A | 星期的完整名称 | Monday |
b | 月份的缩写名称 | Jan |
B | 月份的完整名称 | January |
c | 首选日期+时间表示 | 2018-10-17 12:34:56 |
d | 月份中的日期 | 01, 31 |
f | 微秒 (不支持宽度和填充修饰符) | 000000, 999999, 0123 |
H | 使用 24 小时制的小时 | 00, 23 |
I | 使用 12 小时制的小时 | 01, 12 |
j | 一年中的日期 | 001, 366 |
m | 月份 | 01, 12 |
M | 分钟 | 00, 59 |
p | "AM" 或 "PM"(中午为 "PM",午夜为 "AM") | AM, PM |
P | "am" 或 "pm"(中午为 "pm",午夜为 "am") | am, pm |
q | 季度 | 1, 2, 3, 4 |
s | 自纪元以来的秒数,1970-01-01 00:00:00+0000 (UTC) | 1565888877 |
S | 秒 | 00, 59, 60 |
u | 星期几 | 1 (星期一),7 (星期日) |
x | 首选日期(不含时间)表示 | 2018-10-17 |
X | 首选时间(不含日期)表示 | 12:34:56 |
y | 年份为两位数 | 01, 01, 86, 18 |
Y | 年份 | -0001, 0001, 1986 |
z | +hhmm/-hhmm 时区偏移量,相对于 UTC(如果为原始时间,则为空字符串) | +0300, -0530 |
Z | 时区缩写(如果为原始时间,则为空字符串) | CET, BRST |
% | 字面 "%" 字符 | % |
任何其他字符都将被解释为无效格式,并引发错误。
示例
无用户选项
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%y-%m-%d %I:%M:%S %p")
"19-08-26 01:52:06 PM"
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%a, %B %d %Y")
"Mon, August 26 2019"
iex> Calendar.strftime(~U[2020-04-02 13:52:06.0Z], "%B %-d, %Y")
"April 2, 2020"
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%c")
"2019-08-26 13:52:06"
有用户选项
iex> Calendar.strftime(~U[2019-08-26 13:52:06.0Z], "%c", preferred_datetime: "%H:%M:%S %d-%m-%y")
"13:52:06 26-08-19"
iex> Calendar.strftime(
...> ~U[2019-08-26 13:52:06.0Z],
...> "%A",
...> day_of_week_names: fn day_of_week ->
...> {"segunda-feira", "terça-feira", "quarta-feira", "quinta-feira",
...> "sexta-feira", "sábado", "domingo"}
...> |> elem(day_of_week - 1)
...> end
...>)
"segunda-feira"
iex> Calendar.strftime(
...> ~U[2019-08-26 13:52:06.0Z],
...> "%B",
...> month_names: fn month ->
...> {"січень", "лютий", "березень", "квітень", "травень", "червень",
...> "липень", "серпень", "вересень", "жовтень", "листопад", "грудень"}
...> |> elem(month - 1)
...> end
...>)
"серпень"
@spec truncate(microsecond(), :microsecond | :millisecond | :second) :: microsecond()
返回一个微秒元组,截断到给定的精度 (:microsecond
、:millisecond
或 :second
)。