查看源代码 Calendar 行为 (Elixir v1.16.2)

该模块定义了在 Elixir 中处理日历、日期、时间和日期时间的职责。

它定义了 Elixir 中日历行为的类型和最小实现。Elixir 中日历功能的目标是提供互操作性的基础,而不是提供完整的日期时间 API。

对于实际的日期、时间和日期时间结构体,请参阅 DateTimeNaiveDateTimeDateTime

年份、月份、日期等类型是 *过度指定的*。例如,month/0 类型被指定为整数,而不是 1..12。这是因为不同的日历可能每个月的日期数不同。

摘要

类型

一个日历实现。

任何包含日期字段的映射或结构体。

任何包含日期时间字段的映射或结构体。

在日历之间转换时使用内部时间格式。

表示 dayera 的元组。

在日历之间转换时使用的内部日期格式。

带有存储精度的微秒。

任何包含朴素日期时间字段的映射或结构体。

时区标准偏移量,单位为秒(通常在夏令时不为零)。

任何包含时间字段的映射或结构体。

根据 IANA tz 数据库的时区 ID(例如,Europe/Zurich)。

指定日历操作的时区数据库。

标准时间的时区 UTC 偏移量,单位为秒。

时区缩写(例如,CETCESTBST)。

回调

根据日历将日期转换为字符串。

根据给定的 yearmonthday 计算日期和纪元。

根据给定的 yearmonthday 计算星期几。

根据给定的 yearmonthday 计算一年中的第几天。

定义日历的滚动时刻。

返回给定年份中给定月份的天数。

将给定的 iso_days/0 转换为一天的第一个时刻。

将给定的 iso_days/0 转换为一天的最后一个时刻。

如果给定年份是闰年,则返回 true

返回给定年份中的月份数。

iso_days/0 转换为日历的日期时间格式。

根据日历将朴素日期时间(无时区)转换为字符串。

date_to_string/3 返回的日期字符串表示形式解析为日期元组。

naive_datetime_to_string/7 返回的朴素日期时间字符串表示形式解析为朴素日期时间元组。

time_to_string/4 返回的时间字符串表示形式解析为时间元组。

datetime_to_string/11 返回的日期时间字符串表示形式解析为日期时间元组。

根据给定的 yearmonthday 计算一年中的季度。

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()}

表示 dayera 的元组。

@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()

时区缩写(例如,CETCESTBST)。

回调

链接到此回调

date_to_string(year, month, day)

查看源代码
@callback date_to_string(year(), month(), day()) :: String.t()

根据日历将日期转换为字符串。

链接到此回调

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()

根据日历将日期时间(带时区)转换为字符串。

链接到此回调

day_of_era(year, month, day)

查看源代码
@callback day_of_era(year(), month(), day()) :: day_of_era()

根据给定的 yearmonthday 计算日期和纪元。

链接到此回调

day_of_week(year, month, day, starting_on)

查看源代码
@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()}

根据给定的 yearmonthday 计算星期几。

starting_on 表示一周的开始日期。所有日历至少必须支持 :default 值。它们还可以支持其他表示其星期几的值。

链接到此回调

day_of_year(year, month, day)

查看源代码
@callback day_of_year(year(), month(), day()) :: non_neg_integer()

根据给定的 yearmonthday 计算一年中的第几天。

链接到此回调

day_rollover_relative_to_midnight_utc()

查看源代码
@callback day_rollover_relative_to_midnight_utc() :: day_fraction()

定义日历的滚动时刻。

这是在你的日历中,当前一天结束和下一天开始的时刻。

此函数的结果用于检查两个日历是否在一天中的同一时间滚动。如果它们没有,我们只能在它们之间转换日期时间和时间。如果它们确实如此,这意味着我们还可以转换日期以及它们之间的朴素日期时间。

此日分数应尽可能简化,以使比较速度更快。

示例

  • 如果在你的日历中,新的一天从午夜开始,则返回 {0, 1}
  • 如果在你的日历中,新的一天从日出开始,则返回 {1, 4}
  • 如果在你的日历中,新的一天从中午开始,则返回 {1, 2}
  • 如果在你的日历中,新的一天从日落开始,则返回 {3, 4}
链接到此回调

days_in_month(year, month)

查看源代码
@callback days_in_month(year(), month()) :: day()

返回给定年份中给定月份的天数。

链接到此回调

iso_days_to_beginning_of_day(iso_days)

查看源代码 (自 1.15.0 起)
@callback iso_days_to_beginning_of_day(iso_days()) :: iso_days()

将给定的 iso_days/0 转换为一天的第一个时刻。

链接到此回调

iso_days_to_end_of_day(iso_days)

查看源代码 (自 1.15.0 起)
@callback iso_days_to_end_of_day(iso_days()) :: iso_days()

将给定的 iso_days/0 转换为一天的最后一个时刻。

@callback leap_year?(year()) :: boolean()

如果给定年份是闰年,则返回 true

闰年是指比正常年份更长的年份。确切的含义取决于日历。如果日历不支持闰年的概念,则必须返回 false

@callback months_in_year(year()) :: month()

返回给定年份中的月份数。

链接到此回调

naive_datetime_from_iso_days(iso_days)

查看源代码
@callback naive_datetime_from_iso_days(iso_days()) ::
  {year(), month(), day(), hour(), minute(), second(), microsecond()}

iso_days/0 转换为日历的日期时间格式。

链接到此回调

naive_datetime_to_iso_days(year, month, day, hour, minute, second, microsecond)

查看源代码
@callback naive_datetime_to_iso_days(
  year(),
  month(),
  day(),
  hour(),
  minute(),
  second(),
  microsecond()
) ::
  iso_days()

将日期时间(无时区)转换为 iso_days/0 格式。

链接到此回调

naive_datetime_to_string(year, month, day, hour, minute, second, microsecond)

查看源代码
@callback naive_datetime_to_string(
  year(),
  month(),
  day(),
  hour(),
  minute(),
  second(),
  microsecond()
) ::
  String.t()

根据日历将朴素日期时间(无时区)转换为字符串。

链接到此回调

parse_date(t)

查看源代码 (自 1.10.0 起)
@callback parse_date(String.t()) :: {:ok, {year(), month(), day()}} | {:error, atom()}

date_to_string/3 返回的日期字符串表示形式解析为日期元组。

链接到此回调

parse_naive_datetime(t)

查看源代码 (自 1.10.0 起)
@callback parse_naive_datetime(String.t()) ::
  {:ok, {year(), month(), day(), hour(), minute(), second(), microsecond()}}
  | {:error, atom()}

naive_datetime_to_string/7 返回的朴素日期时间字符串表示形式解析为朴素日期时间元组。

给定字符串可能包含时区偏移量,但会被忽略。

链接到此回调

parse_time(t)

查看源代码 (自 1.10.0 起)
@callback parse_time(String.t()) ::
  {:ok, {hour(), minute(), second(), microsecond()}} | {:error, atom()}

time_to_string/4 返回的时间字符串表示形式解析为时间元组。

链接到此回调

parse_utc_datetime(t)

查看源代码 (自 1.10.0 起)
@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 必须在结果中返回。

链接到此回调

quarter_of_year(year, month, day)

查看源代码
@callback quarter_of_year(year(), month(), day()) :: non_neg_integer()

根据给定的 yearmonthday 计算一年中的季度。

链接到此回调

time_from_day_fraction(day_fraction)

查看源代码
@callback time_from_day_fraction(day_fraction()) ::
  {hour(), minute(), second(), microsecond()}

day_fraction/0 转换为日历的时间格式。

链接到此回调

time_to_day_fraction(hour, minute, second, microsecond)

查看源代码
@callback time_to_day_fraction(hour(), minute(), second(), microsecond()) ::
  day_fraction()

将给定时间转换为 day_fraction/0 格式。

链接到此回调

time_to_string(hour, minute, second, microsecond)

查看源代码
@callback time_to_string(hour(), minute(), second(), microsecond()) :: String.t()

根据日历将时间转换为字符串。

链接到此回调

valid_date?(year, month, day)

查看源代码
@callback valid_date?(year(), month(), day()) :: boolean()

如果给定日期在日历中描述了一个正确的日期,则应返回 true

链接到此回调

valid_time?(hour, minute, second, microsecond)

查看源代码
@callback valid_time?(hour(), minute(), second(), microsecond()) :: boolean()

如果给定时间在日历中描述了一个正确的时间,则应返回 true

链接到此回调

year_of_era(year, month, day)

查看源代码
@callback year_of_era(year(), month(), day()) :: {year(), era()}

根据给定的 year 计算年份和纪元。

函数

链接到此函数

compatible_calendars?(calendar, calendar)

查看源代码 (自 1.5.0 起)
@spec compatible_calendars?(calendar(), calendar()) :: boolean()

如果两个日历在开始新的一天的时间相同,则返回 true,否则返回 false

如果两个日历不兼容,我们只能在它们之间转换日期时间和时间。如果它们兼容,这意味着我们还可以转换日期以及它们之间的原始日期时间。

链接到此函数

get_time_zone_database()

查看源代码 (自 1.8.0 起)
@spec get_time_zone_database() :: time_zone_database()

获取当前时区数据库。

链接到此函数

put_time_zone_database(database)

查看源代码 (自 1.8.0 起)
@spec put_time_zone_database(time_zone_database()) :: :ok

设置当前时区数据库。

链接到此函数

strftime(date_or_time_or_datetime, string_format, user_options \\ [])

查看源代码 (自 1.11.0 起)
@spec strftime(map(), String.t(), keyword()) :: String.t()

将给定的日期、时间或日期时间格式化为字符串。

日期时间可以是任何 Calendar 类型(TimeDateNaiveDateTimeDateTime)或任何映射,只要它们包含所有格式化所需的相关字段即可。例如,如果您使用 %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
S00, 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
...>)
"серпень"
链接到此函数

truncate(microsecond_tuple, atom)

查看源代码 (自 1.6.0 起)
@spec truncate(microsecond(), :microsecond | :millisecond | :second) :: microsecond()

返回一个微秒元组,截断到给定的精度 (:microsecond:millisecond:second)。