festivals 模块

模块: borax.calendars.festivals

日期模式类(DateSchema)

在 Borax.Calendars 中,使用 DateSchema 表示和定义一个节假日、生日等日期,称之为 日期模式 。日期模式是与年份无关的,在给定的年份中,可以计算推导出一个或多个具体的日期。

由于节日的表示各不相同,有的是农历日期,有的是公历日期,也有的是按星期确定具体的日期,每个表示形式(模式)使用 DateSchema 的一个子类表示。

DateSchema 仅提供了一些简单的接口,无法被实例化。

  • year等于0表示一个模糊日期模式,可匹配任何一年的日期。
  • name表示名称、标签,传入任何字符串即可。

SolarSchema

  • `SolarSchema(month, day, year=YEAR_ANY, reverse=0, kwargs)`**

公历日期,比如元旦(1月1日)、劳动节(5月1日)、国庆节(10月1日)等。

当 reverse 等于0时,day 表示具体的“日”;当 reverse 等于1时,day 表示倒数的序数。

比如 reverse=1和day=1表示该月的最后一天,即1月31日、3月31日、4月30日…12月31日等。

节日编码表示如下:

字段(长度) schema(1) year(4) month(2) day(2) reverse(1)
描述 模式序号 年份 月份 日期或序号 是否倒序
取值范围 0 0000,1900 - 2101 01 - 12 01 - 31 0,1

WeekSchema

  • `WeekSchema(month, index, week, year=YEAR_ANY, kwargs)`**

依赖于星期的公历日期,比如母亲节(5月的第2个星期日)、父亲节、感恩节等。

星期的数值表示参考 calendar 模块的定义,即0表示星期一,6表示星期日。

比如 WeekSchema(month=5, index=2, week=6) 表示母亲节。

节日编码表示如下:

字段(长度) schema(1) year(4) month(2) index(2) week(1)
描述 模式序号 年份 月份 序号 星期
取值范围 2 0000,1900 - 2101 01 - 12 01 - 05 0 - 6

TermSchema

  • `TermSchema(index, year=YEAR_ANY, kwargs)`**

依赖于节气的公历日期,比如清明、冬至。节气按照公历一年先后排序,即0为小寒、1为大寒、6为清明、23为冬至。

节日编码表示如下:

字段(长度) schema(1) year(4) - (2) index(2) - (1)
描述 模式序号 年份 - 节气序号 -
取值范围 4 0000,1900 - 2101 00 01 - 23 0

LunarSchema

  • `LunarSchema(month, day, year=YEAR_ANY, leap=0, ignore_leap=1, kwargs)`**

农历日期,比如七夕(七月初七)、腊八节 (腊月初八)等。

ignore_leap表示是否忽略闰月进行匹配。比如:

(1) LunarSchema(month=6, day=1) 可以匹配 LunarDate(2017, 6, 1, 0)LunarDate(2017, 6, 1, 1) 两个日期。

(2) LunarSchema(month=6, day=1, ignore_leap=0) 只匹配 LunarDate(2017, 6, 1, 0) 一个日期。

(3) LunarSchema(month=6, day=1, leap=1, ignore_leap=1) 只匹配 LunarDate(2017, 6, 1, 1) 一个日期。

节日编码表示如下:

字段(长度) schema(1) year(4) month(2) day(2) leap(1)
描述 模式序号 年份 月份 日期 是否闰月
取值范围 1 0000,1900 - 2100 01 - 12 01 - 30 0,1

DayLunarSchema

  • `DayLunarSchema(month, day, year=YEAR_ANY, reverse=0, kwargs)`**

依赖具体日的农历日期,比如除夕(农历十二月的最后一天)。

当 reverse 等于0时,day 表示具体的“日”;当 reverse 等于1时,day 表示倒数的序数。

节日编码表示如下:

字段(长度) schema(1) year(4) month(2) day(2) reverse(1)
描述 模式序号 年份 月份 日期或序号 是否倒序
取值范围 3 0000,1900 - 2100 01 - 12 01 - 30 0,1

方法

以下函数的 date_obj 参数可以传入 datetime.date 或者 LunarDate 对象。

  • DateSchema.match(data_obj:Union[date, LunarDate]) -> bool

返回 date_obj 的日期和 所代表节日的是否是同一天。

  1. >>> from datetime import date
  2. >>>from borax.calendars.festivals import SolarSchema
  3. >>>md = SolarSchema(year=0, month=2, day=14)
  4. >>>md.match(date(2020, 2, 14))
  5. True
  • DateSchema.countdown(data_obj:Union[date, LunarDate]) -> int

返回 data_obj 的日期和本节日下一次日期的距离天数。

  1. >>>from borax.calendars.lunar import LunarDate
  2. >>>from borax.calendars.festivals import LunarSchema
  3. >>>ls = LunarSchema(year=0, month=4, day=2)
  4. >>>ls.countdown(LunarDate(2019, 4, 1))
  5. 1
  • DateSchema.resolve(year:int) -> Union[date, LunarDate]

获取某年该日期模式对应的日期对象,具体类型由 DateSchema.data_class 确定。

  1. >>>from borax.calendars.festivals import LunarSchema
  2. >>>ls = LunarSchema(year=0, month=4, day=2)
  3. >>>ls.resolve(2019)
  4. LunarDate(2019, 4, 2)
  • DateSchema.delta(date_obj:Union[date, LunarDate]) -> int

    获取和 date_obj 距离的天数,要求 DateSchema.year 不为0。

  1. >>>from borax.calendars.festivals import LunarSchema
  2. >>>ls = LunarSchema(year=0, month=4, day=2)
  3. >>>ls.delta()
  4. -6550

序列化和存储

DateSchema 实现了 Encoder 的接口,可以在 DateSchema 和字符串之间进行转换, 支持不同形式节日的混合存储。

节日编码字符串有长短两种形式。长编码字符串的长度为10,包含了年份字段;短编码字符串长度为6,不包含年份字段。

  1. DateSchema ====(encode)====> RawString
  2. RawString ====(decode)====> DateSchema
  • DateSchema.encode(short: bool = True) -> str

转化为编码字符串,这是一个实例方法。

  • classmethod DateSchema.decode(raw) -> DateSchema

根据编码字符串创建模式对象,这是一个类方法。

例子:

  1. from datetime import date
  2. from borax.calendars.festivals import SolarSchema
  3. ss = SolarSchema.decode('0000012310')
  4. print(ss.match(date(2018, 12, 31))) # True

节日计算工具(FestivalFactory)

FestivalFactory类支持从特定的外部文件读取一系列的节日信息。

  1. class FestivalFactory(lang=None, file_path=None)

festivals 也内置了一些国家地区常见的节假日,可以通过 lang 读取这些信息。

  1. from datetime import date
  2. from borax.calendars.festivals import FestivalFactory
  3. factory = FestivalFactory(lang='zh-Hans')
  4. festival = factory.get_festival('元旦')
  5. print(festival.match(date(2018, 1, 1))) # True

FestivalFactory 提供了一系列函数。

  • iter_festival_countdown(countdown:Optional[int]=None, today:Union[date, LunarDate], lang: str = 'zh-Hans') -> Iterator[int, List]

计算节日距离某一日期还有多少天,结果按倒计天数分组。

  1. list(factory.iter_festival_countdown(30)) # [(7, ['春节']), (16, ['情人节']), (21, ['元宵节'])]
  • get_festival(name:str, lang: str = 'zh-Hans') -> DateSchema

获取一个节日的所代表日期对象(DateSchema)。

  1. festival = factory.get_festival('春节')
  2. festival.countdown() # 7

快捷访问工具

为了保持之前的兼容性,festivals 提供了几个快捷函数。调用这些函数无需创建相应的 FestivalFactory 实例 。

  • iter_festival_countdown(countdown:Optional[int]=None, today:Union[date, LunarDate]) -> Iterator[int, List]
  • get_festival(name:str) -> DateSchema