公众授权版:normal · 1000 次 · 有效期至 2026-12-31

副本编号 LY-20261007-AC63(水印指纹已嵌入)
含 README、.gitignore;排除 .DS_Store / __pycache__ / .pytest_cache
This commit is contained in:
2026-10-07 17:29:52 +08:00
commit d9da4301cd
772 changed files with 48534 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# vendor/ —— 随包内置的依赖(免安装)
用户拿到 skill 后**无需 pip install**:运行期依赖的源码直接放在这里,
`scripts/cast_chart.py` 启动时把本目录插入 `sys.path` 最前(优先于环境已安装的包)。
## 内容
| 目录/文件 | 包 | 版本 | 来源 | 许可证 |
|---|---|---|---|---|
| `tyme4py/` | tyme4py | 1.5.0(==锁定) | PyPI / 工作区 `tyme4py-1.5.0/` | MIT(`tyme4py.LICENSE`) |
| `tzdata/` | tzdata | 2026.5 | PyPI | Apache-2.0(`tzdata.LICENSE`) |
两个包均为纯 Python / 纯数据,无编译产物,跨平台(macOS / Linux / Windows)、
跨架构可用。运行时唯一要求是 **Python ≥ 3.10**(`zoneinfo` 与类型标注语法需要)。
## 为什么 vendor 而不是打包 .venv
虚拟环境不可移植:`pyvenv.cfg` 与 activate 脚本硬编码创建时的绝对路径,
`bin/python` 是指向本机解释器的符号链接,且按 OS/架构绑定。
vendor 纯源码没有这些问题,同时把 `tyme4py==1.5.0` 的版本锁定做到了字节级。
## 如何升级
1. 用新版本源码替换对应目录(保持目录名不变);
2. 同步更新本表的版本号与 `pyproject.toml` / `requirements.txt` 的锁定;
3. 跑 `tests/` 黄金样本与规则库 `rules/tests/` 确认无回归
(历法库升级可能改变节气时刻,必须全量回归)。
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 6tail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+179
View File
@@ -0,0 +1,179 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Union, List
__version__ = '1.5.0'
class Culture(ABC):
"""传统文化(民俗)"""
@abstractmethod
def get_name(self) -> str:
"""
名称
:return: 名称
"""
pass
class Tyme(Culture):
@abstractmethod
def next(self, n: int) -> Union[Tyme, None]:
"""
推移
:param n: 推移步数
:return: 推移后的Tyme或None
"""
pass
class AbstractCulture(Culture):
"""传统文化抽象"""
@abstractmethod
def get_name(self) -> str:
pass
def __str__(self) -> str:
return self.get_name()
def __eq__(self, other: Culture) -> bool:
return other and other.__str__() == self.__str__()
@staticmethod
def index_of(index: int, size: int) -> int:
"""
转换为不超范围的索引
:param index: 索引
:param size: 长度大小
:return: 索引,从0开始
"""
i: int = index % size
return i + size if i < 0 else i
class AbstractTyme(AbstractCulture, Tyme):
"""抽象Tyme"""
@abstractmethod
def get_name(self) -> str:
pass
@abstractmethod
def next(self, n: int) -> Union[Tyme, None]:
pass
class AbstractCultureDay(AbstractCulture):
"""带天索引的传统文化抽象"""
def __init__(self, culture: AbstractCulture, day_index: int):
"""
初始化
:param culture: 传统文化抽象
:param day_index: 天索引
"""
self._culture = culture
self._day_index = day_index
def get_day_index(self) -> int:
"""
天索引
:return: 索引
"""
return self._day_index
def get_culture(self) -> AbstractCulture:
return self._culture
def get_name(self) -> str:
return self._culture.get_name()
def __str__(self) -> str:
return f'{self.get_name()}第{self.get_day_index() + 1}天'
class LoopTyme(AbstractTyme):
"""可轮回的Tyme"""
def __init__(self, names: List[str], index_or_name: Union[int, str]):
"""
初始化
:param names: 名称列表
:param index_or_name: 索引,支持负数,自动轮转; 名称
"""
self._names = names
self._index = self._index_of_by(index_or_name)
def _index_of_by(self, index_or_name: Union[int, str]) -> int:
"""
:param index_or_name: 索引或名称
:return: 索引
"""
if isinstance(index_or_name, int):
return self.index_of(index_or_name, self.get_size())
else:
for i in range(0, self.get_size()):
if index_or_name == self._names[i]:
return i
raise ValueError(f"illegal name: {index_or_name}")
def get_name(self) -> str:
return self._names[self._index]
def get_index(self) -> int:
"""
索引
:return: 索引,从0开始
"""
return self._index
def get_size(self) -> int:
"""
数量
:return: 数量
"""
return self._names.__len__()
def next_index(self, n: int) -> int:
"""
推移后的索引
:param n: 推移步数
:return: 索引,从0开始
"""
return self._index_of_by(self._index + n)
def steps_to(self, target_index: int) -> int:
"""
到目标索引的步数(从左往右顺序)
:param target_index: 目标索引
:return: 步数(>=0)
"""
return self.index_of(target_index - self._index, self.get_size())
def steps_back_to(self, target_index: int) -> int:
"""
到目标索引的步数(从右往左逆序)
:param target_index: 目标索引
:return: 步数(<=0)
"""
n = self.get_size()
return -((self._index - target_index + n) % n)
def steps_close_to(self, target_index: int) -> int:
"""
到目标索引的最少步数
:param target_index: 目标索引
:return: 步数(从左往右顺序>=0,从右往左逆序<=0)
"""
d1 = self.steps_to(target_index)
d2 = self.steps_back_to(target_index)
if d1 <= abs(d2):
return d1
return d2
@abstractmethod
def next(self, n: int) -> Union[LoopTyme, None]:
pass
+743
View File
@@ -0,0 +1,743 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
import re
from math import floor
from typing import TYPE_CHECKING, List, Union
from tyme4py import LoopTyme, AbstractCulture, AbstractCultureDay
from tyme4py.util import ShouXingUtil
if TYPE_CHECKING:
from tyme4py.culture.star.seven import SevenStar
from tyme4py.culture.star.twentyeight import TwentyEightStar
from tyme4py.lunar import LunarDay, LunarMonth
from tyme4py.sixtycycle import SixtyCycle, EarthBranch
from tyme4py.jd import JulianDay
from tyme4py.solar import SolarTime, SolarDay
class Animal(LoopTyme):
"""动物"""
NAMES: List[str] = ['蛟', '龙', '貉', '兔', '狐', '虎', '豹', '獬', '牛', '蝠', '鼠', '燕', '猪', '獝', '狼', '狗', '彘', '鸡', '乌', '猴', '猿', '犴', '羊', '獐', '马', '鹿', '蛇', '蚓']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Animal:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Animal:
return cls(index)
def next(self, n: int) -> Animal:
return Animal(self.next_index(n))
def get_twenty_eight_star(self) -> TwentyEightStar:
"""
二十八宿
:return: 二十八宿
"""
from tyme4py.culture.star.twentyeight import TwentyEightStar
return TwentyEightStar(self.get_index())
class Beast(LoopTyme):
"""神兽"""
NAMES: List[str] = ['青龙', '玄武', '白虎', '朱雀']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Beast:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Beast:
return cls(index)
def next(self, n: int) -> Beast:
return Beast(self.next_index(n))
def get_zone(self) -> Zone:
"""
:return: 宫
"""
return Zone(self.get_index())
class Constellation(LoopTyme):
"""星座"""
NAMES: List[str] = ['白羊', '金牛', '双子', '巨蟹', '狮子', '处女', '天秤', '天蝎', '射手', '摩羯', '水瓶', '双鱼']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Constellation:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Constellation:
return cls(index)
def next(self, n: int) -> Constellation:
return Constellation(self.next_index(n))
class Direction(LoopTyme):
"""方位"""
NAMES: List[str] = ['北', '西南', '东', '东南', '中', '西北', '西', '东北', '南']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Direction:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Direction:
return cls(index)
def next(self, n: int) -> Direction:
return Direction(self.next_index(n))
def get_land(self) -> Land:
"""
:return: 九野
"""
return Land(self.get_index())
def get_element(self) -> Element:
"""
:return: 五行
"""
return Element([4, 2, 0, 0, 2, 3, 3, 2, 1][self.get_index()])
class Duty(LoopTyme):
"""建除十二值神"""
NAMES: List[str] = ['建', '除', '满', '平', '定', '执', '破', '危', '成', '收', '开', '闭']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Duty:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Duty:
return cls(index)
def next(self, n: int) -> Duty:
return Duty(self.next_index(n))
class Element(LoopTyme):
"""五行"""
NAMES: List[str] = ['木', '火', '土', '金', '水']
"""名称"""
def __init__(self, index_or_name: Union[int, str], names: Union[List[str], None] = None):
super().__init__(self.NAMES if names is None else names, index_or_name)
@classmethod
def from_name(cls, name: str) -> Element:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Element:
return cls(index)
def next(self, n: int) -> Element:
return Element(self.next_index(n))
def get_reinforce(self) -> Element:
"""
我生者
:return: 五行
"""
return self.next(1)
def get_restrain(self) -> Element:
"""
我克者
:return: 五行
"""
return self.next(2)
def get_reinforced(self) -> Element:
"""
生我者
:return: 五行
"""
return self.next(-1)
def get_restrained(self) -> Element:
"""
克我者(耗)
:return: 五行
"""
return self.next(-2)
def get_direction(self) -> Direction:
"""
方位
:return: 方位
"""
return Direction([2, 8, 4, 6, 0][self.get_index()])
class God(LoopTyme):
"""神煞"""
NAMES: List[str] = ['天恩', '鸣吠', '母仓', '不将', '四相', '鸣吠对', '五合', '三合', '除神', '月德', '月空', '月德合', '月恩', '时阴', '五富', '生气', '金匮', '相日', '阴德', '六合', '益后', '青龙', '续世', '明堂', '王日', '要安', '官日', '吉期', '福德', '六仪', '金堂', '宝光', '民日', '临日', '天马', '敬安', '普护', '驿马', '天后', '阳德', '天喜', '天医', '司命', '圣心', '玉宇', '守日', '时德', '解神', '时阳', '天仓', '天巫', '玉堂', '福生', '天德', '天德合', '天愿', '天赦', '天符', '阴神', '解除', '五虚', '五离', '重日', '复日', '血支', '天贼', '土符', '游祸', '白虎', '小耗', '致死', '河魁', '劫煞', '月煞', '月建', '往亡', '大时', '大败', '咸池', '厌对', '招摇', '九坎', '九焦', '天罡', '死神', '月害', '死气', '月破', '大耗', '天牢', '元武', '月厌', '月虚', '归忌', '小时', '天刑', '朱雀', '九空', '天吏', '地火', '四击', '大煞', '勾陈', '八专', '灾煞', '天火', '血忌', '土府', '月刑', '触水龙', '地囊', '八风', '四废', '四忌', '四穷', '五墓', '阴错', '四耗', '阳错', '孤辰', '小会',
'大会', '八龙', '七鸟', '九虎', '六蛇', '天狗', '行狠', '了戾', '岁薄', '逐阵', '三丧', '三阴', '阴道冲阳', '阴位', '阴阳交破', '阴阳俱错', '阴阳击冲', '鬼哭', '单阴', '绝阴', '纯阳', '阳错阴冲', '七符', '成日', '孤阳', '绝阳', '纯阴', '大退', '四离', '阳破阴冲']
"""名称"""
day_gods: List[str] = [
';000002300F14156869717A3F;01001617495C40413C425D6A;0209000C041831031906054A5E6B4B5F;033500041A1B032C06054C4D4E60;04002D321C1D1E104F50615152;05111F53546C55433C3E;062E200721220D01566E44;070B2333242F45;08360A2526242F080157583D59;091234080162463C3D5A;0A270728292A5B6364653F79;0B0237130E2B4748727A3E66;0C09020C04300F0314150568696D;0D3504031617495C40413C6F425D6A;0E38183119064A5E6B4B5F;0F001A1B032C064C4D4E60;10002D321C1D1E104F50615152;110B00111F53546C55433C3E;12360A002E200721220D015644;13002333456D;142526242F080157583F3D59;15001234080162463C3D5A;16090004270728292A5B636465;17350204130E032B47483E66;1802300F14156869;19031617495C40413C425D6A;1A1831031906054A5E6B4B5F;1B0B1A1B032C06054C4D4E;1C360A2D321C1D1E104F50615152;1D111F53546C55433C3E;1E2E200721220D01563F44;1F23334573;20090C042526242F080157583D;2135041234080162463C3D5A;22270728292A5B636465;2302130E032B47483E66;2402300F0314150568696E;250B031617495C40413C425D6A;26360A18311906054A5E6B4B5F;271A1B2C06054C4D4E60;282D321C1D1E104F506151523F;29111F53546C55433C3E;2A090C042E200721220D015644;2B350423334567;2C2526242F0857583D59;2D001234080162463C3D5A;2E00270728292A5B63646574;2F0B0002130E032B47483E66;30360A0002300F141505686975;31001617495C40413C425D6A676D;3218311906054A5E6B4B3F675F76;331A1B2C06054C4D4E60;34090C042D321C1D1E104F50615152;353504111F53546C55433C6F3E;362E200721220D5644;3723334567;382526242F08015758703D6759;390B123408016246703C3D5A84;3A360A270728292A5B636465;3B02130E2B47483E66;',
';00090002272A536C4C4D4E41717A;0100300F3103233C6151523F66;020004180E032406150543405D;03000C041A1D340617054A5E6B4F50;04002D1B555F;050B112526321C2B3C42654B3E60;060A2E2014100547546246;0712070D161F566A;0822192F0148453D44;092C083301575868695B633C3D;0A0937131E495C6459;0B020721282903727A3F3E5A;0C020427032A05536C4C4D4E416D;0D0C04300F03233C6F61515266;0E38180E24061543405D;0F0B001A1D3406174A5E6B4F5078;100A002D1B555F;1100112526321C2B3C42654B3E60;12002E2014100147546246;130012070D161F566A6D;140922192F080148453D44;152C083301575868695B633C3F3D44;160413031E495C6459;17020C0407212829033E5A;1802272A536C4C4D4E41;190B300F3103233C61515266;1A0A180E032406150543405D;1B1A1D340617014A5E6B4F50;1C2D1B555F;1D112526321C2B3C42654B3E60;1E092E2014100147546246;1F12070D161F56736E6A3F;200422192F080148453D44;210C042C083301575868695B633C3D;22131E495C6459;230B0207212829033E5A;240A0227032A05536C4C4D4E41;25300F31233C61515266;26180E2406150543405D;271A1D340617054A5E6B4F50;28092D1B555F;29112526321C2B3C42654B3F3E60;2A042E2014100147546246;2B0C0412070D161F566A67;2C22192F0848453D44;2D0B002C083301575868695B633C3D85;2E0A0013031E495C6459;2F0002072128293E5A;300002272A05536C4C4D4E4175;3100300F31233C6151526E676D66;3209180E2406150543405D;331A1D340617054A5E6B4F503F76;34042D1B555F;350C04112526321C2B3C6F42654B3E60;362E20141047546246;370B12070D161F566A67;380A22192F08014845703D6744;392C083301575868695B63703C3D74;3A131E495C6459;3B02072128293E5A;',
';00000207282931032B717A6E5D59;01000314473C5A;020A000427182526300F1D16062A054F506A;03360B00041A1906055562464066;04002D2C154A5E6B6C733F788B;0512111B0E1E17483C3E;060C2E20321C016869655F;0753544960;08350907210D230810015B63564B3D77;091324081F014C4D4E453C423D;0A2203342F57586461515244;0B02032C4341727A3E;0C0A020407282931032B055D6D59;0D360B040314473C6F5A;0E3827182526300F1D16062A4F506A3F;0F001A19065562464066;10000C2D2C154A5E6B6C86;110012111B0E1E17483C3E;123509002E20321C0168696E655F;13005354495C6D60;1407210D230810015B63564B3D7F;1537130324081F014C4D4E453C423D;160A042203342F57586461515244;17360B0204033343413E;1802072829312B5D3F59;190314473C5A;1A0C27182526300F1D16062A054F506A;1B1A1906055562464066;1C35092D2C154A5E6B6C;1D12111B0E1E17483C3E;1E2E20321C016869655F;1F5354495C60;200A0407210D230810015B63564B3D80;21360B04130324081F014C4D4E453C423D;2222342F5758646151523F44;2302033343413E;24020C072829312B055D59;2514473C5A;26120927182526300F1D16062A054F506A;271A1906055562464066;282D2C154A5E6B6C76;2912111B0E1E17483C3E;2A0A042E20321C016869655F;2B360B045354495C6760;2C07210D2308105B63564B3F3D77;2D00130324081F014C4D4E453C423D;2E000C22342F57586461515244;2F00023343413E;3035090002072829312B05755D59;310014473C676D5A;3227182526300F1D16062A054F506A67;331A1906055562464066;340A042D2C154A5E6B6C;35360B0412111B0E1E17483C6F3E;362E20321C6869653F5F;375354495C6760;380C07210D230810015B6356704B3D677774;391324081F014C4D4E45703C423D;3A350922342F57586461515244;3B023343413E;',
';000A00220362463C44;010B00072128291D334F50645D;02360002230605534855423F59;03000212300F24060568695A;0400042E27342A495C403C8C;050C04184A5E6B3E66788D76;06091A1B2B15014C4D4E;07352D321C14175B636151526577;0811130E16080147546C433C6A3D5F;0920070D190801563D60;0A0A032C2F104541;0B0B252631031E1F57584B3E;0C362203056246717B3C3F6D44;0D072128291D334F50645D;0E020423065348554259;0F00020C0412300F240668696E5A;1009002E12342A495C403C;113500184A5E6B3E66;12001A1B2B15014C4D4E;13002D321C14175B63615152656D77;140A11130E0316080147546C433C6F6A3D5F;150B20070D03190801563D60;1636032C2F104541733F;17252631031E1F5758727B4B3E;1804220362463C44;190C04072128291D334F50645D;1A09022306055348554259;1B3502120D0F24060568695A;1C2E27342A495C403C;1D184A5E6B3E66;1E0A381A1B2B15014C4D4E;1F0B2D321C14175B63615152657F;20363711130E0316080147546C433C6A3F3D5F;2120070D03190801563D60;2204032C2F104541;230C042526311E1F57584B3E;2409220562463C44;2535072128291D334F50645D;26022306055348554259;270212300F24060568695A;280A2E27342A495C403C6F;290B184A5E6B3E66;2A361A1B2B15014C4D4E3F81;2B2D321C14175B6361515265678074;2C0411130E03160847546C433C6A3D5F;2D000C0420070D190801566E3D60;2E09002C2F104541;2F35002526311E1F57584B3E;300022056246703C44;3100072128291D334F50645D676D;320A02230605534855426759;330B02120D0F2406056869755A;34362E27342A495C403C3F;35184A5E6B3E6676;36041A1B2B154C4D4E81;370C042D321C14175B6361515265677774;380911130E16080147546C433C6A3D675F;393520070D190801563D60;3A2C2F104541;3B2526311E1F5758704B3E87;',
';00001D2F10575868694F503C;0100122B1F495C5564;0209000207222829140605655D44;03000216063305474C4D4E51526A4B3F;04000C042E300F193C6159;0504182C43403E5A;06271A1E2A014A5E6B6C5B6342;070B2D1B1366;080A112526321C0815013C3D;0920032308170153546246413D;0A07210D310324565F;0B0E033448453E60;0C091D2F1005575868694F50717B3C6D;0D122B1F495C553F;0E020C04072228291406655D44;0F000204160633474C4D4E51526A4B;10002E300F193C6159;110B00182C43403E5A;120A00271A1E2A014A5E6B6C5B6342;13002D1B13036D66;14112526321C030815013C6F3D;1520032308170153546246413D;160907210D31032456735F;170E344845727B3F3E60;180C041D2F10575868694F503C;1904122B1F495C5564;1A0207222829140605655D44;1B0B0216063305474C4D4E51526A4B;1C0A2E300F193C6159;1D182C43403E5A;1E38271A1E2A014A5E6B6C5B6342;1F2D1B130366;2009112526321C030815013C3D;21202308170153546246413F3D;220C0407210D3103565F;23040E3448453E60;241D2F1005575868694F503C;250B122B1F495C5564;260A0207222829140605655D44;270216063305474C4D4E51526A4B;282E300F193C6F616E59;29182C43403E5A;2A09271A1E2A014A5E6B6C5B63427988;2B372D1B133F6766;2C0C04112526321C0308153C3D;2D0004202308170153546246413D;2E0007210D3124565F;2F0B000E3448453E60;300A001D2F1005575868694F50703C89;3100122B1F495C5564676D;320207222829140605655D6744;330216063305474C4D4E7551526A4B;34092E300F193C6159;35182C43403F3E5A;360904271A1E2A4A5E6B6C5B634278;37042D1B136766;38112526321C0815013C3D67;390B202308170153546246413D;3A0A07210D3124566E5F;3B0E03344845703E60;',
';003509001E2F554C4D4E453C51525D5F;010057586C646160;0200020E06100543;0300020721282923061F0565;0400042E2224533C7344;05360B04182526300F34335B633F3E74;060A1A13016246404B59;070C2D2B4A5E6B5A;0827111B0314082A0148413C3D;0920321C310316080148413C3D;0A35090319154754495C42;0B12070D1D2C174F50563E;0C1E2F05554C4D4E45717B3C51525D6D5F;0D57586C646160;0E02040E061043;0F360B0002040721282923061F653F;100A002E2224533C44;11000C182526300F34335B633E;12001A1303016246404B59;13002D032B4A5E6B6D5A;14350927111B0314082A0148413C6F3D;1520321C310316080168696A3D66;1619154754495C426E;1712070D1D2C174F5056727B3E;18041E2F554C4D4E453C51525D5F;19360B0457586C64613F60;1A0A020E06100543;1B020C0721282923061F0565;1C2E2224533C44;1D182526300F34335B633E;1E3509381A1303016246404B59;1F2D032B4A5E6B5A;2027111B14082A0148413C3D;2120321C3116080168696A3D66;22040319154754495C42;23360B0412070D1D2C174F50563F3E;240A1E2F05554C4D4E453C51525D5F;250C57586C646160;26020E06100543;27020721282923061F0565;2835092E2224533C6F44;29182526300F34335B633E;2A1A13016246404B5982;2B2D2B4A5E6B675A76;2C0427111B0314082A48413C3D;2D360B000420321C3116080168696A3F3D66;2E0A0019154754495C42;2F000C12070D1D2C174F50563E;30001E2F05554C4D4E45703C51525D5F;310057586C6461676D608E;323509020E0610054367;33020721282923061F057565;342E2224533C6E44;35182526300F34335B633E7974;3637041A13036246404B5982;37360B042D2B4A5E6B3F675A76;380A27111B14082A0148413C3D67;390C20321C3116080168696A3D66;3A0319154754495C42;3B12070D1D2C174F5056703E;',
';0000302007210D341556;01000217455D;020A0025262B2F060557586C5F;030B001406056246603C8F;0436000207282916105B6364656A;0537130E191F47483E;0622300F2C0168693F44;07021E33495C40413C;08090C04184A5E423D59;093504121A1B0308014C4D4E51524B3D5A;0A02272D321C1D232A4F507E61;0B1124535455433E66;0C0A2E2007210D341505566D;0D0B0217455D;0E3625262B2F0657586C;0F00140662463C4260;10000207282916105B6364656A3F79;1100130E191F47483E;1209350C0422300F032C01686944;1335000204031E33495C40413C6D;1418310308014A5E6B3D59;15121A1B0308014C4D4E51524B3D5A;160A02272D321C1D232A4F507E61;170B1124535455433C6F6E3E66;18362E2007210D341556;190217455D;1A25262B060557586C3F5F;1B14060562463C4260;1C09020C0407282916105B6364656A;1D3504130E03191F47483E;1E22300F032C01686944;1F02031E495C40413C;200A183108014A5E6B3D59;210B121A1B08014C4D4E51524B3D5A;223602272D321C1D232A4F507E61;231124535455433C3E66;242E2007210D34150556717C3F;25021745735D;26090C0425262B2F060557586C5F;27350414060562463C4260;280207282916105B6364656A74;29130E03191F47483E;2A0A22300F2C01686944;2B0B021E33495C40413C6F67;2C36381831034A5E6B3D59;2D00121A1B08014C4D4E51524B3D5A;2E0002272D321C1D232A4F507E613F;2F00112453545543727C3C3E66;3009000C042E2007210D34150556;313500020417455D676D;3225262B2F060557586C70675F;331406056246703C426084;340A0207282916105B6364656A;350B130E191F47486E3E;363622300F032C7544;37021E33495C40413C67;38183108014A5E6B3F3D675976;39121A1B08014C4D4E51524B3D5A;3A09020C04272D321C1D232A4F507E61;3B35041124535455433C3E66;',
';000A002E27202C2A475462464B;010B0002070D1E5666;02002F06150548456E5D;0300061705575868695B633C;040002130323495C645F;0507212829249060;0609341001534C4D4E415152;070212300F31031F3C61423F;080418220E032B080143403D44;090C041A1D14080833014A5E6B6C4F503D;0A0A022D1B16556A59;0B0B112526321C193C653E5A;0C2E27202C2A05475462464B6D;0D02070D1E5666;0E2F061548455D;0F000617575868695B633C85;10090002371323495C645F;11000721282903243F3E60;12000403341001534C4D4E415152;1300020C0412300F31031F3C61426D;140A18220E032B080143403D44;150B1A1D140833014A5E6B6C4F503D;16022D1B16556A59;17112526321C193C6F653E5A;182E27202C2A475462464B;1902070D1E5666;1A092F06150548455D;1B061705575868695B633C3F79;1C0204130323495C645F;1D0C040721282903243E60;1E0A03341001534C4D4E415152;1F0B0227300F311F3C6142;2018220E2B080143406E3D44;211A1D140833014A5E6B6C4F503D;22022D1B16556A59;23112526321C193C653E5A;24092E27202C2A0547546246717C4B;2502070D1E56733F66;26042F06150548455D;270C04061705575868695B633C;280A02130323495C645F;290B07212829243E60;2A341001534C4D4E415152;2B0212300F311F3C6F614267;2C3818220E032B0843403D44;2D001A1D140833014A5E6B5B4F503D78;2E0900022D1B16556A59;2F00112526321C19727C3C653F3E5A;3000042E27202C2A05475462464B;3100020C04070D1E56676D66;320A2F0615054845705D67;330B061705575868695B63703C74;34021323495C645F;3507212829243E60;36033410534C4D4E41755152;370212300F311F3C614267;380918220E2B080143403D6744;391A1D140833014A5E6B6C4F503F3D76;3A02042D1B16556A59;3B0C04112526321C193C653E5A;',
';00002E20391C246869655D59;010002345354495C5A;023509002707210D062A055B6356515277;0300132B06054C4D4E453C66;04000203142F1557586473614B3F;0512161743416A3E;060C072829310319015F;07360B02032C476C3C6E60;080A04182526300F1D1E0810014F503D;09041A081F01556246403D;0A022D224A5E6B4486;0B111B0E2333483C423E;0C35092E20321C24056869655D6D59;0D02345354495C5A;0E2707210D062A5B635651523F77;0F00132B064C4D4E453C66;1000020C03142F15575864614B;11360B001203161743416A3E;120A0004072829310319015F;13000204032C476C3C6D60;14182526300F1D1E0810014F503D;151A081F01556246403D;163509022D224A5E6B44;17111B0E2333483C6F423E;182E20321C246869655D3F59;1902345354495C5A;1A0C2707210D062A055B635651527F;1B360B3713032B06054C4D4E453C66;1C0A020403142F15575864614B;1D041203161743416A3E;1E0728293119015F;1F022C476C3C60;203509182526300F1D1E08104F503D;211A081F01556246403D;22022D224A5E6B3F447891;23111B0E2333483C423E;240C2E20321C24056869717C655D59;25360B021C5354495C6E5A;260A042707210D062A055B6356515280;270413032B06054C4D4E453C66;2802142F15575864614B;2912161743416A3E;2A35090728293119015F;2B022C476C3C6F6760;2C38182526300F1D1E08104F503F3D;2D001A081F01556246403D;2E0002092D224A5E6B4476;2F360B00111B0E233348727C3C423E;300A00042E20321C24056869655D59;31000204345354495C676D5A;322707210D062A055B6356705152677774;33132B06054C4D4E45703C66;34350902142F15575864614B;3512161743416A3E;36072829310319753F5F;37022C476C3C6760;380C182526300F1D1E0810014F503D67;39360B1A081F01556246403D;3A0A02042D224A5E6B44;3B04111B0E2333483C423E;',
';00090038041A221B194C4D4E44;0135000C042D321C2C335B6361655D77;02002E11130E1E06054754433C59;03001220070D0605565A;0400272F2A454142;050B252631032357583E66;06360A0324150162463C;07072128291D34174F50644B;080208015348553F3D5F;0902300F2B080168693D60;0A09041410495C403C6F;0B35090418161F4A5E6B6C5152403E;0C1A221B19054C4D4E6D44;0D2D321C2C335B6361655D77;0E2E11130E1E064754433C6E59;0F0B351220070D0306565A;10360A0027032F2A454142;1100252631032357583E66;12000324150162463C3F;1300072128291D34174F50644B6D;1409020408015348553D5F;1535020C04300F2B080168693D60;161410495C403C;1718161F4A5E6B6C51526A3E;181A221B194C4D4E4481;190B0A2E11130E031E06054754433C59;1A360A2E11130E031E06054754433C59;1B1220070D030605565A;1C27032F2A454173423F;1D252631032357583E66;1E090424150162463C;1F350C04072128291D34174F50644B;200208015348553D5F;2102300F2B080168693D60;221410495C403C92;230B18161F4A5E6B6C51526A3E7893;24360A1A221B19054C4D4E44;252D321C2C335B6361655D7F;26372E11130E031E06054754433C3F59;271220070D030605565A;280904272F2A454142;29350C042526312357583E66;2A2415016246703C;2B072128291D34174F50644B67;2C02085348556E3D5F;2D090002300F2B080168693D60;2E360A001410495C403C;2F0018161F4A5E6B6C51526A3E;30001A221B19054C4D4E717D3F4481;31002D321C2C335B6361655D676D8074;3209042E11130E1E06054754433C6F6759;33350C042720070D0605565A;34272F2A454142;35252631235758703E6687;36241562463C;370B072128291D34174F50644B67;38360A023A015348553D675F;3902300F2B08016869753D60;3A1410495C403C3F;3B18161F4A5E6B6C727D51526A3E76;',
';0000380C041A23104A5E6B5B63;010004122D1B13241F838A;020A002E11252622321C3406053C5D44;030B00200306330553544641;040007210D312B5659;050E031448453E5A;060E1D162F2A01575868694F503C6A;0719495C556466;0809020728292C081501515242653D;09021E081701474C4D4E3F3D;0A0C04300F3C6F614B5F;0B041843403E60;0C0A1A2310054A5E6B5B636D;0D0B122D1B1303241F838A94;0E2E11252622321C34063C5D44;0F002003063353546C624641;100007210D31032B5659;11000E031448453E5A;120900271D162F2A01575868694F503C6A;130019495C55643F6D66;14020C040728292C081501515242653D;1502041E081701474C4D4E3D;160A300F3C614B5F;170B1843403E60;181A23104A456B5B6378;19122D1B1303241F9583;1A2E11252622321C033406053C5D44;1B200306330553546C6246416E;1C0907210D31032B567359;1D0E1448453F3E5A;1E0C04271D163B2A01575868694F503C6A;1F0419495C556466;200A020728292C081501515242653D;210B021E081701474C4D4E3D;22300F3C614B5F;231843403E60;241A2310054A5E425B63;25122D1B1303241F;26092E11252622321C033406053C5D44;272006330553546C6246413F;280C0407210D312B5659;29040E1448453E5A;2A0A271D162F2A01575868694F50703C6A89;2B0B19495C55646766;2C020728292C0815515242653D;2D00021E081701474C4D4E3D;2E00300F3C614B5F;2F001843403E60;3009001A2310054A5E6B5B63717D7988;310037122D1B13241F3F676D;320C042E11252622321C3406053C6F5D6744;33042006330553546C624641;340A07210D312B5659;350B0E03144845703E5A;36271D162F2A575868694F503C6A;3719495C55646766;38020728292C081501515242653D67;39021E081701474C4D4E756E3D;3A09300F3C614B5F;3B184340727D3F3E60;',
';000A003837041A1316624640425D6A5F;01360B00042D194A5E6B4B60;020009111B032C06100548413C;030020321C310310061F056869;0400224754495C7344;05070D1D334F505651523F3E;063509232F01554C4D4E453C59;070C24575864615A;0802270E34082A01433D;09020721282908016E653D66;0A0A042B15536C3C6F;0B360B0412182526300F14175B633E;0C1A13031605624640425D6A6D5F;0D2D03194A5E6B4B60;0E2E111B33061048413C;0F0020321C31031E061F68693F;1035090022034754495C44;11000C070D1D334F505651523E;1200232F01554C4D4E453C59;130024575864616D5A;140A0204270E0F082A01433D;15360B0204072128290801653D66;162B15536C3C;17121825260D0F14175B633E;181A1316624640425D6A5F82;192D03194A5E6B4B3F60;1A35092E111B032C061048413C;1B0C20321C31031E061F056869;1C224754495C44;1D07121D334F505651523E;1E0A04232F01554C4D4E453C59;1F360B0424575864615A;2002270E34082A01433D;2102072128290801653D66;222B15536C3C;2312182526300F14175B633F3E;2435091A13031605624640425D6A5F;250C2D03194A5E6B4B60;262E111B2C06100548413C;2720321C311E061F056869;280A04224746495C44;29360B04070D1D334F505651523E;2A232F01554C4D4E45703C59;2B2457586461675A96;2C02270E34082A433D;2D0002072128290801653F3D66;2E3509002B15536C3C;2F000C12182526300F14175B633E;30001A1316624640717D425D6A5F82;31002D194A5E6B4B676D6076;320A042E111B2C06100548413C6F67;33360B0420321C311E061F0568696E;3422034754495C44;35070D1D334F50567051523E;36232F554C4D4E453C59;3724575864613F675A;38350902270E34082A01433D67;39020C07212829080175653D66;3A2B15536C3C;3B12182526300F14175B63727D3E7974;'
]
"""吉神宜趋,凶神宜忌数据(参考 https://www.51wnl-cq.com/ 并进行了部分数据修正)"""
def __init__(self, index_or_name: Union[int, str]) -> None:
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> God:
return cls(name)
@classmethod
def from_index(cls, index: int) -> God:
return cls(index)
def next(self, n: int) -> God:
return God(self.next_index(n))
def get_luck(self) -> Luck:
"""
吉凶
:return: 吉凶
"""
return Luck(0 if self.get_index() < 60 else 1)
@classmethod
def get_day_gods(cls, month: SixtyCycle, day: SixtyCycle) -> List[God]:
"""
日神煞列表(吉神宜趋,凶神宜忌)
:return: 神煞列表
"""
l: List[God] = []
index: str = format(day.get_index(), '02X')
pattern = re.compile(f';{index}(.[^;]*)')
matcher = pattern.search(God.day_gods[month.get_earth_branch().next(-2).get_index()])
if matcher:
data: str = matcher.group(1)
for i in range(0, data.__len__(), 2):
l.append(God(int(data[i: i + 2], 16)))
return l
class KitchenGodSteed(AbstractCulture):
NUMBERS: List[str] = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二']
"""数字"""
def __init__(self, lunar_year):
from tyme4py.lunar import LunarDay
self._first_day_sixty_cycle = LunarDay.from_ymd(lunar_year, 1, 1).get_sixty_cycle()
@classmethod
def from_lunar_year(cls, lunar_year):
return cls(lunar_year)
def _by_heaven_stem(self, n):
return self.NUMBERS[self._first_day_sixty_cycle.get_heaven_stem().steps_to(n)]
def _by_earth_branch(self, n):
return self.NUMBERS[self._first_day_sixty_cycle.get_earth_branch().steps_to(n)]
def get_mouse(self):
return f'{self._by_earth_branch(0)}鼠偷粮'
def get_grass(self):
return f'草子{self._by_earth_branch(0)}分'
def get_cattle(self):
return f'{self._by_earth_branch(1)}牛耕田'
def get_flower(self):
return f'花收{self._by_earth_branch(3)}分'
def get_dragon(self):
return f'{self._by_earth_branch(4)}龙治水'
def get_horse(self):
return f'{self._by_earth_branch(6)}马驮谷'
def get_chicken(self):
return f'{self._by_earth_branch(9)}鸡抢米'
def get_silkworm(self):
return f'{self._by_earth_branch(9)}姑看蚕'
def get_pig(self):
return f'{self._by_earth_branch(11)}屠共猪'
def get_field(self):
return f'甲田{self._by_heaven_stem(0)}分'
def get_cake(self):
return f'{self._by_heaven_stem(2)}人分饼'
def get_gold(self):
return f'{self._by_heaven_stem(7)}日得金'
def get_people_cakes(self):
return f'{self._by_earth_branch(2)}人{self._by_heaven_stem(2)}丙'
def get_people_hoes(self):
return f'{self._by_earth_branch(2)}人{self._by_heaven_stem(3)}锄'
def get_name(self):
return '灶马头'
class Land(LoopTyme):
"""九野"""
NAMES: List[str] = ['玄天', '朱天', '苍天', '阳天', '钧天', '幽天', '颢天', '变天', '炎天']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Land:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Land:
return cls(index)
def next(self, n: int) -> Land:
return Land(self.next_index(n))
def get_direction(self) -> Direction:
"""
:return: 方位
"""
return Direction(self.get_index())
class Luck(LoopTyme):
"""吉凶"""
NAMES: List[str] = ['吉', '凶']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Luck:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Luck:
return cls(index)
def next(self, n: int) -> Luck:
return Luck(self.next_index(n))
class Phase(LoopTyme):
"""月相"""
NAMES: List[str] = ['新月', '蛾眉月', '上弦月', '盈凸月', '满月', '亏凸月', '下弦月', '残月']
"""名称"""
def __init__(self, lunar_year: int, lunar_month: int, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
from tyme4py.lunar import LunarMonth
if isinstance(index_or_name, int):
m = LunarMonth.from_ym(lunar_year, lunar_month).next(index_or_name // self.get_size())
self._lunar_year = m.get_year()
self._lunar_month = m.get_month_with_leap()
else:
self._lunar_year = lunar_year
self._lunar_month = lunar_month
@classmethod
def from_name(cls, lunar_year: int, lunar_month: int, name: str) -> Phase:
return cls(lunar_year, lunar_month, name)
@classmethod
def from_index(cls, lunar_year: int, lunar_month: int, index: int) -> Phase:
return cls(lunar_year, lunar_month, index)
def next(self, n: int) -> Phase:
from tyme4py.lunar import LunarMonth
size = self.get_size()
i = self.get_index() + n
if i < 0:
i -= size
i //= size
m = LunarMonth.from_ym(self._lunar_year, self._lunar_month)
if i != 0:
m = m.next(i)
return Phase(m.get_year(), m.get_month_with_leap(), self.next_index(n))
def _get_start_solar_time(self) -> SolarTime:
from tyme4py.jd import JulianDay
from tyme4py.lunar import LunarDay
n = floor((self._lunar_year - 2000) * 365.2422 / 29.53058886)
i = 0
jd = JulianDay.J2000 + ShouXingUtil.ONE_THIRD
d = LunarDay.from_ymd(self._lunar_year, self._lunar_month, 1).get_solar_day()
while True:
t = ShouXingUtil.msa_lon_t((n + i) * ShouXingUtil.PI_2) * 36525
if not JulianDay.from_julian_day(jd + t - ShouXingUtil.dt_t(t)).get_solar_day().is_before(d):
break
i += 1
t = ShouXingUtil.msa_lon_t((n + i + [0, 90, 180, 270][self.get_index() // 2] / 360.0) * ShouXingUtil.PI_2) * 36525
return JulianDay.from_julian_day(jd + t - ShouXingUtil.dt_t(t)).get_solar_time()
def get_solar_time(self) -> SolarTime:
t = self._get_start_solar_time()
if self.get_index() % 2 == 1:
return t.next(1)
return t
def get_solar_day(self) -> SolarDay:
d = self._get_start_solar_time().get_solar_day()
if self.get_index() % 2 == 1:
return d.next(1)
return d
class PhaseDay(AbstractCultureDay):
"""月相第几天"""
def __init__(self, phase: Phase, day_index: int):
super().__init__(phase, day_index)
def get_phase(self) -> Phase:
"""
月相
:return: 月相
"""
return self.get_culture()
class Sixty(LoopTyme):
"""元"""
NAMES: List[str] = ['上元', '中元', '下元']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Sixty:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Sixty:
return cls(index)
def next(self, n: int) -> Sixty:
return Sixty(self.next_index(n))
class Sound(LoopTyme):
"""纳音"""
NAMES: List[str] = ['海中金', '炉中火', '大林木', '路旁土', '剑锋金', '山头火', '涧下水', '城头土', '白蜡金', '杨柳木', '泉中水', '屋上土', '霹雳火', '松柏木', '长流水', '沙中金', '山下火', '平地木', '壁上土', '金箔金', '覆灯火', '天河水', '大驿土', '钗钏金', '桑柘木', '大溪水', '沙中土', '天上火', '石榴木', '大海水']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Sound:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Sound:
return cls(index)
def next(self, n: int) -> Sound:
return Sound(self.next_index(n))
class Taboo(LoopTyme):
"""宜忌"""
NAMES: List[str] = ['祭祀', '祈福', '求嗣', '开光', '塑绘', '齐醮', '斋醮', '沐浴', '酬神', '造庙', '祀灶', '焚香', '谢土', '出火', '雕刻', '嫁娶', '订婚', '纳采', '问名', '纳婿', '归宁', '安床', '合帐', '冠笄', '订盟', '进人口', '裁衣', '挽面', '开容', '修坟', '启钻', '破土', '安葬', '立碑', '成服', '除服', '开生坟', '合寿木', '入殓', '移柩', '普渡', '入宅', '安香', '安门', '修造', '起基', '动土', '上梁', '竖柱', '开井开池', '作陂放水', '拆卸', '破屋', '坏垣', '补垣', '伐木做梁', '作灶', '解除', '开柱眼', '穿屏扇架', '盖屋合脊', '开厕', '造仓', '塞穴', '平治道涂', '造桥', '作厕', '筑堤', '开池', '伐木', '开渠', '掘井', '扫舍', '放水', '造屋', '合脊', '造畜稠', '修门', '定磉', '作梁', '修饰垣墙', '架马', '开市', '挂匾', '纳财', '求财', '开仓', '买车', '置产', '雇佣', '出货财', '安机械', '造车器', '经络', '酝酿', '作染', '鼓铸', '造船', '割蜜', '栽种', '取渔', '结网', '牧养', '安碓磑', '习艺', '入学', '理发', '探病', '见贵', '乘船', '渡水', '针灸', '出行', '移徙', '分居', '剃头', '整手足甲', '纳畜', '捕捉', '畋猎', '教牛马', '会亲友', '赴任', '求医', '治病', '词讼', '起基动土', '破屋坏垣', '盖屋', '造仓库', '交易', '立券', '安机', '会友', '求医疗病', '诸事不宜', '馀事勿取', '行丧', '断蚁', '归岫']
"""名称"""
day_taboo: List[str] = [
'8219000776262322200C1E1D,06292C2E1F;0F11185C0001092A0D7014692982837B7C2C2E302F802D2B,06454F2089;111852828370795B302F404533802D152B39201E23221D212726,0F2E1F010D29;004023222088,0F29111847;11180001032A0D70795B2C2E302F802D4E152B33714161201F26,52095847;0F17000102061979454F3A15477677,241F8920;34357C88,7129;1551000403706A454F3A3D771F262322271E1D21,382B415220;0F000102037039297175261F1D21,454F2E156341;00076A54196348767765,792029711552890D382B;11180001020439332C2E302F2B5844477515634C1F2721,0F520D19267A29717020;297170192C2E2D2F2B3E363F4C,0F52156320010347;4C78,297172380D2A2E0F474841;18115C0001702A2C2E2F5282837129795B6375802D154C,1F208924;1811795B032C2E302F802D4163754C27261E1D2120,010D0F29521F;00401D232288,71290F4720;0F170001020E032A70692C2E302F802D2B0D7129474C201F2322,5211183809615D;0F1811000102062A0D2C2D804B2B672E2F7129,70471F8920;0007343588,0F71296B7080;175447440D15828377656A49,2B2E1F892022;11187129705B79000106032A0D397B6F7C802D2C2B61756627261E0C1D21,0F2E154147;0007385476771548,52061F20;0106111839513A2C2E2D2F8B804B4723221F63,71522920;1118000717161A2C2E3371292B56433D6375363F,0F0103472089;161A7888,292E1F0F3861;11180F00012A0D70795D7B7C39332D2C2E4E4863664C,064F478920;5452828379195D00012A0D7B7C2C2E3348156366242526201E,0F7129;00262788,292C2E1F2B2F;040318111A17332C15290D200C7A,47450638;0004031A170F11332C2E302F1571292A657677451949,70201D52;007B343588,87;00010670175B71292A152322271E,03637C2B38;04067033392C7161262322271E1D210C,;000715547776,521F;181100012C2E2F1F,0F38;70076A363F,2920;7888,292E1F;0F707B7C00012F75,5220;528303395B2F1E20,0F01;4088,87;02060418110D332C2E415B637566262322271F20,520F;0F181100012C2E7129,5220;7C343588,87;0001020603691817452C2E2D498244,412B6A096338;393588,87;076A48,45752F29384C0F204F612B;000301394F2E154763751F27,0F707A802629710D1920;4F2C2E2B383F443D433663,0F0147892015;201E27262322,88;0F000102700D335282835329711563,3804897D4520;6A0339332C20528283531563,29713801000F0C47806B;005088,87;291503000D332E53261F2075,0F5238584F45;003988,87;3435000788,87;150001021745512E443D65262322,2B63387C;394888,87;00036A7415384878,45751F20240F522E824F;00010203332C2E2F1558631F,0F1920707A29712646;0717363F1A2C4F3A67433D8A,71290F010347;',
'0007010618111A332D302F15262322271E530270164C,560F7129;003988,87;073918111A17332C2E71292322271F1E20481D45548283,38002F70;700F181126151E20001A7919,;5040262788,0F712903;7911192C2E302F00030401060F1571292A75,707C2052;0079701811072C2E01060F33152627200C7A1A302F4576631F2B,80523829;39343588,87;040370181123220F1326271E2021,2915;262322271E202188,1F45;0001060403232226380F767754,56802015;0070071A010618110F5B52836775,632620;00010607155B5C26271E2021165D82,38470F29;3948007888,;528283530339454F0D297115332E2F637520,0F007058;5282835444360F11756415,2C2F29016B472E2B2038;0039504088,;0F0001022E792D3E75663D19,472063703852292B;0F000102032971152C2E19,4720637038522B;343588,87;0F52828303700D332C29712E1F27201E2322,15450175;00261F23221E201D2188,;003988,87;52828354754C2971150301022E,0F63206A0938268941;151A82832627202322,580F7003632E1F297C;00394C786F88,0F2E4420;0704031118528283542D2E4E49201F1E1D2127,292B000C;0F706A151E201D528283544466,47010C2E292F2C38;394088,71294709636F7C44;0F0003450D3329712C2E2F1575,528963705A20587D7C;0F111829711500010370390D332E750C201F,4552822F382B80;0034353988,522E1F;0F1118032A0D545282831A802D2C2E2B71296366774744201F26232221,010900150C;0006261F1E201D212322,0F29381118;0006547677,0F5229151F20;111800010206071979697C67474475664C,0F16298920;000102071282542627201D210C4C78,29580F2E6352031F;00784C793988,0F29702E1F2089;0F03390D332C1929711563261D2E2322,382000521118750C706B;702D155482830F63262720,53292F017D4F38442B2E1F47;4088,030F565A61206B;0F181179005B712980152D4E2A0D533358,52702089;0776776A742623221F200C211D1E,11180F2F5206802B;00343588,060F52;07565A5282835463756677261F20,010F152961;0007363F8A3988,09292C20890F;0F11181200171A7919547638,5215201D;181179000607040D03302F5282834F3A45512B1533664C47,090F702E2089;828354151A4C200C1E23221D212726,030F522E1F;0039787988,1F2E20;111871545282832979397B7C69152B2A0D33485324251F1D1E26,6B00702F800C20;0F18110001027939706954528283685D15565A75201E1D26,29032E;00170F79191A6540,712909387C20;00676588,0F20;0F00071A706A717677492923221E202726,80522E1F;343588,0F5220;111800020D041A796933483E5347446563751F1D212026,010F09150C;262322271E201D21,52450F4F;0038262388,5215;040307177938494C,0F262070;',
'0F00030102705282832E544779,2920454F754C38;00010275261E0C2322,6303706F0F292E1F;033945302F828375262720,297071000F2E1F38;000102030F7039453319152E2D2F63751F0C1E20,71290D3847;7917155B0001025D,0F522E3820;38394088,0001202B;0F00175058,5D6B80382E;110F0001702C2E7129201F,5206;0007396A48343588,0F20;111800012A0D2C705271292E201F,15386179;3F656477,0F2B712920;11000170792C2E7129,0F52201F;110F00017052792E1F1E,71290D2B20;0001020626232227201E,0F2E03801F;1179302F832627201E,0071292E1F;0001067052832E71291F20,030F384775;79026A17657603,522E201F;004088,0F014720;010206110F452C2E7129095B5226232227201F0C,58804B036B2B38;69687011180F791966762627201E,0352292E80;00077B7C4834353988,295220;00170F332C2E2D2F802952443F26232227201F,15637C38;006526232227201F,88;0403010218111A17332C2E2D2B15713E6575,4538206429;0007030401021811171A0F2E2322271F1E706749528382,202F2938;000102081A158382262322270C1E,700F292E;1A162623227954,0001710F29;00061A161718110F292A0C26271F21797001022F49,47;1516291211020056,063820;3840,0001202B88;0403080618111A16332E2F152A09537919702C5445490D75072B,80632038;0001081811171A160F1571292A26271E20396476452B0D,632E5238;7B34,87;010206040318110F2E292A27200C70072C302F541F392B49,3815;64262322271F2021,0F2F2938;0002070818111A16175B153E445D5452838265647576,2038454F;000701020618111A1752838254230C7027,26203829;000102261E2027,03476F700F2971382E;15391A302F82835475662627201E,0F702E46290047;0F150370002E0D3979528283532971331F1E20,477D;0F0302791566046F,29710D722A38528283202E45;383940,6370018975202B454F66;3907,87;0F000170390D332E2971152F63751F1E20,52836A38;00397C343548,88;000102030D70332C2E29712F534426201F1E,0F3815;6526232227201F,87;7100030170391959152E2D2F2B,0F201F4F75668938;0F030102392E15634447001F1E,293845200D7075;00161A5D454F153826201E27,7D0D29;1A454F548283,87;0F00010203700D332E2F1929711552828353261F201E2322,;0F171170792F5B1566770001032C2B802D,29387C2071;50400088,87;5C11180001027170520D2983822B15200C,03802E3863;2E260F27201F,523815292F1A;7B7C343588,520F;00060724232227261F2025,520F157929382F;003F651F0C2027232288,0F29;00076A386563,0F7D892066454F52754C;',
'00077663,0F29713820;000304080618110F1A2E2D0D3371292A2C302F7566010239454E802B,6320;181117332C2E1526232227201F1E3E,38030F5229;0103040818111A155283262322271E20217A79708230,38472E63;00483F,6338200F;03041A174533302F56795B3E808239528354,700F2920;17262322274050,80387C6B;000F01111A1615292A2627200C2C670279538283543E49,6345;00010618111A16332C2E2F2D27200C07483A450D,15528338;34357B7C,87;002E2F18110F5B3315292A26271F20210C7A70710102393E19,035A;000304111A33152D2E302F71292A5283530770022B,0F634520;1A16170F13152654,3852204F;0018112C2E01040607332D292A09270C2322696870302F47023945,38205280;18111A16175B3315262322271F1E201D215D828354433E363F754551,00030F29;00700F1715262720,472E3863;3F87,2B38200F;030402111A16175B4F3A2B153E0079015D54528382696A51,7006200F;000F1320,63803829;0079181A165B332F2B262322271E2021030469702D4E49712930835D,454F;00030401061A16170F332E71292627200C02696A45514F0D2C2D4E497A,2B;007C343588,87;0F00701783821952712C2E1526271F,03380620;52838253000103297115332E2F19,0F89514F6A66207545;6A170F19,5845754C201F4F3824;0F000301020D297115332E1F0C,16522026;1545332C2E2F83826375662620,0F0003700D71292B;000102060F17705282797823221E2027,2E7129;3F74397677658887,0F384720;5452838203152F802C2D,2E1F20897A700F29710C7D;00010F17505840,565A803852828363;0F00030102700D19297115332C2B535448,2E452089;0F03000102700D29713963451F0C20,528238542F158061;34357B7C88,030F;118283155B20272E1F21,0F0338;0001020607036A5D397C2163664744,0F4E252089;5482836376656419786A,29803020;0F18110001702C2E71291F0D2B152F2127,52821620;1783822C2E5B26201F,0F010D29;00797083821754,0F2E472D4E1F;000739483F66,0F20892B;54528283036F796A153E65,712963;0F17795B54828358,52807C38;0F5C111800015B712952831F20,756A25;01067071292C2E1F20,1103150F52;343588,0F715229;0F170070792C2E261F,0403412322;03027011170D332D2C2E2F716152828354,010F201F;6A170F1963766F,5452201F;030102703945802D2C512B7129092322270C7566,112E5282;1A5D453A332C2E2F4B25262322271F201E1D21,000F7047;007983821A160F1719,632E20471D6B;483F88,87;040318111A16175B795452838215302F6563395D,38702920;000F1323222627,2E38290315;010203040618110F3315292A271D200C6339171A712C2E30491E21,7A;0039262322271E201D210C0748766465776A,150F3829;3435,87;007018111A1617192E15382627201F656477,4F09;00030418111617332E2D2F292A52835407020D302B,090F4520;',
'528283530003010215392C20,1112180F29560D2E1F7545;004D64547588,0F29;2A0D11180F52838253037039156358332C2E,38200026;00702C2E164C157126271F1E202425363F,29386A032B;005088,032C2E1F;0F00010206030D7129302F79802D7C2B5C4744,11701D20528338;000403110F527079156523221E2027,0129802E1F6B;00384088,15296763;000102060775261F20,71290F7015;1100010206702D804E2B2620,0F52540D;0007397B7C343588,01065220;0776776564,000F293820;00010206111803302F565A802D4E2B871F261E0C,0D0F52;00763988,0F20;110F70528375660D7129,012E1F2026;0001020617385482,030F47202B6B;0039787088,2E1F89034F206B;0706397B7C794C636A48,520F71294720;02703918110F7919155282756626232227201E,012C2E1F0C;00384088,0F202E157C;5C0001020652825B0E03804B2D4E2B752024210C,292E565A;000103020611187B7C2D4E616439201E0C26,522E4744;000734357B7C3988,0F52822920;87,;0004031811171A5B332C2E155D52,0D292045;0088,090F15;18110F197982832E230C271F1E7A70525463,26202915;00011A1615262322271F1E200C214C,472B0F11;00190F153917701A48,472E1F2003;11037B7C2E2F7129,0F5220;007952151E20,0F2E1F;00384740,0F20;0006522E261F20,0F7129;0F11000170717B,522E1F;007B7C3988,87;076564,0F2920;,87;393588,87;0F03700D33195283825329711563,01260038206B;0F70161715232238828326271F20,7D0352;70504C7888,87;0001030239450D297115332C2E4C,0F54207052833863;110F03706A795215636626271E,0C012F38062C292B;0040395088,87;000103392E54827548,19700F58157A2038;00010203390D3329152C2B751E20,2E1F544753524582;0039343588,87;3F4888,87;000102033911170D3319152E2F0947442627201F,;393488,87;0F0102037039330D5283822971152E1F0C,0026206B;001A1715828344363F261F1E200C2322,0F476B520363;0070784888,0345201F;000102031118396375664819,1D413870208029;0370823F0F6A5215,010D582E1F202C2F29;00387765504088,0F157C;070039201F0C2788,06030F292F;003926271E20747677642322480C06,2E1F;00073934357B7C88,0F52;073F7765644888,0120;',
'0F110001702E2F71291F20,06;110001527B7C2E75,0F20;0F11707129,2E1F20;1811002E1F8283,0F20;0F1A0070153871291F20,7A76;3F6588,87;0F1811700001062E2F1F20,7129;18117915384C,5220;07404826271F1E2088,87;0F00010203700D332E2F192971152B52828353631F20,;00037039041A26271F1E202322,0F2F2C335129452E0D3A;0039343588,87;0F0001020370332E2F0D19297115637566302B2C3979,;528283000103451915332C2E631F2720,29716A0D0F70;653988,87;0F00010203528283157033,752971206B452F2B262E;0F000102700D332C2E297115383F631F20,034756;394888,87;528283530370331929272E2B2F631F1D20,0F156B38;1979,3F2F2E45207D;074048261F202322,0F71454F15000180;0F000102030D70332E3919528283532971152B2F201F0C,;0001020339161745514F2C190F1A152E2D2F304979,;3435073988,87;11180F5C000102030D332C2E195329711563261F202322,5283;5282830001032E1570637566302F391F,0F47297120;39701117302F713819297566,004551152C2E201D1F;0001020370528283631575712D2E4E3E581F1E1D,292C2B45262080;0F82833D363F776424,15462F2C52032971;3F8A657788,0F2029702E7D;11180F0001020339700D29716375662E1F2620,38155680;03111A171538193E3F,0F632C2E70454F200C;110F1A6A702C2E1952828353712F6375,4520150001;5282835300010670802D2C2E4E155B201F1E232221,380F71296A;0F1118000102030D70332E2C192971153953631F0C262720,52836125;000739343588,0320;18110F3900010203700D3329711563752E1F0C201D,38525D;000102031811392E2D19528283543E4463751F20,152F1A290F;00657688,6B0F52;0001020311180F702E1F7952828368332D6749443E46630C1E1D21,292B20;0F1700707129385C363F3D1F1E232226,80412B202F;00398A7988,0F20;0F111800017C5C2C2E7129,5270153820;0F1118795B65170002195D,52382E8920;0007711F204840,010F291538;000106025B75712904032D302F382B2A0D801E20,2E1F0F;0F1118060300017B7C792E39767566261F20,71298051;000739343588,8920;074888,06520F38;5282835B79037B7C802D2C2E4E302F2B38493D4463664C1F2021,0F0D7129;63767788,522E0006206B;0F00010206181139702E1F686F6A792D2C304E153375664923221D21,52296B0D80;88,;3F8A6588,1F20;0370110F45510D3371290941614C522623222720,;1966583F6588,87;03700F,79192C2E2D715275262322271F201D21;0F11700001522E71291F20,2B;0F117B7C2C2E71291F20,5203;00343588,87;',
'00343588,7129565A;00060403702C2E4C154947443D651F,0D29;528283530339332E152C2F58631F20,380D000F29;006588,29704720;0F1118175C000301027039450D29332C2E2F15631F,895820;0F161A17452F0D33712C2E2B5443633F,150170208903;70786288,06802E1F;0F0001020370390D332C1929712E157563548283534C,202489;5B000102073911522C302F3A678B363F33490D482425200C1E2322,0F15382E1F61;00076A74504088,5229702C7D;0F110001708371292E1F20,0338805156;111817000106702C2E71292A0D33802D302F4E2B44,0F522520;0007343588,290F71;0F5B8270000102060403161A494447,386A418920;11177B7C52832C2E5B1F20,060071292F0F;003888,52201F1D47;000102062A397129797B7C2E1F2425,162F5D2026;0F172C2E387129363F7566512D4E4461,0103475220;008254,06462F2E1F;0F181117795B5C007054292A0D690403332D2C2E66632B3D,89454F38;030270170F45513A2C71295282832A0D532D24252623222720,155A382E1F;00076A0F3874485040,06707C25;5B71297000010611182A0D39792C2E332D4E80151F202621,52454F38;00077665776488,52820F2089;34357B7C7788,0F29;0F705B0004037C5D15653F1F26,522B4738;181179190E332C2E2D52637566262322271F20,;0076645088,87;0F1100017B7C702E7129,522B;1A38712975,0F20;0026271E20,2F2E1F;18117001061579,712920;0F11707B7C5271291E20,2E1F;0F00074850,8920;0F1811705200012E71291F20,38;18117000012C2E7129,5220;87,;0F18110001261F20,0352;037B7C2E2F261F20,0F;006388,87;0F030001027039452971150D332C2F6327,20528283;020F11161A17454F2C2E2D302F2B38434C,20700163;003988,87;0F00010D0302703352828353297115632E,2089454F;03027039450D332C2F2D2971528283636626202322,5815;006A5040077448,702B2C0F2F29;0F00030102700D332E2C192971155382836375261F1E20,;0001020370450D332C2E2D152971,0F528289201D;343588,87;52828354443D65002C2E15495D1F,0F417D712B3863;528283546315332C2E2F26201F2322,0F0D45002971756B;003888,87;393588,87;2C2E2D2B156343364C,0F4729710D708920036A19;00788A88,0671292E;11180F000152548371702C2E2D4E303348492A156144474C63,89201F384506;0F0300017039712952542D2C302F80380D2A363F3349483E616320,1118150C1F2E;0F006A385040740717,1F7063;0F1118000102030D70332C2E192971158283535426201E2322,471F;77766564000788,0F52201E89;',
'110001392E1F20,0F7129;00343588,87;0F1152702E2F71291F20,0001;0F1152702E2F71291F20,7A;00385476,521F;0F528300012E7129,0920;363F6526232227201E88,87;0F11700001397129,2E20;0F0001067C1F20,5229;0F705215261E20,012E1F;0F001A651707,565A58202E1F4763;297115030102195282830D332C2E,0F1F5863201D89;0039077426271F1E20,0F29713852822B63;343588,87;0F03706A4F0D332C528283532E29711563,450075;0F0370010239332E2C19528283532971156375262720,;003854637519,205D1D1F52151E21;0001020352666A,0F7020262938172F;00261F2322271E200C88,;007082624C,0F38202E7D4F45471F71;0F000102030D332C2E195282835329716375261E2322,;0F033915666A52261E272048,382E2F6329712C01;003988,87;00010203450D3329152C2E2F5375,0F63896A1D38;39006A26201F,0F520D38580629712B;343588,87;528283542E03700F111869565A7566631F1E2021,297138000C;0F1118000102030D70332C2E195282835329711563261F0C20,47457525;00173882546365756619,466115201F701D475224;0F18000102111A1703154F2C2E382D2F807566,716370891F207D;5D0007363F232227261E21,037C0F471F20;0F00701A17820E544C5C78,7129632E1F382089452F;2C2E5B000739337C38802D44484C2425201F1E272621,52297015;0F11185C0370332D152322528283636626271E,2F292C2E1F000106;000F7765,2E1F7C46;111879690001020370396A2E2D528283543E637566,0F380D582920;00013974150726271F1E200C,0F06520D297170382B45;34353988,0F20;0F528371295B795D2B155333565A446375661F201E272621,00016B0C41;0F181100010603797B7C802D302F2B6743441F202322,2952477D25;11180F71297000010604032A0D793969302F33802D636675,201F52565A1E;11180F000704030D7C684580302F153867534775,702041;00262322271F1E203F8A65,52290F0380;002C7080305C784C62,2E1F4720;000704036939487C4466,0F70112938;54528283700001020339482D301571565A363F637566,06292B201F89;005040,522E1F0F2C20;18110001032A0D835B7129302F791533536678,0F20891F1D;076A7626271F1E20,0D0F29382F2E;7B7C343588,0F70;11180F71297052828354792A0D33802D153853201F1E212627,012F564766;0001067011185B0D332C2E2D712909262322271F200C,0F526325;00195475667688,5229152E20;0004037B7C0F79494766754667,802938692089;003F657788,7152290F032B;525400045B17791A565D754C7866,2E1F207C;71297C790001062A0F802D,5215705D;0470170F191A134C8283662426232227201E,;00170F7665776488,;074888,87;',
'0F0001020D700339332C192A82832971152E1F0C20262322,0652563861;1F2027260076232288,0F295282;34357C88,0111180F2920;0F030001022A0D3945297115528283637020,476A382E1F44;5B11180001020328700D332C2E195282837115632F751F2720,290F4766;0F0001021A175D2C19152E302F7182836379,8920704F754541;0F11180300706A2E1549466319,292F26806B382B207545;00704F0D332C2E2D15363F261F20274C,0F2906036F47;0F11180001027039302971542F7526201E,63472E151F58;390001022C2E302F1575804B2D261F20,0D0F0319707D5229717A;076A79040363660F5D363F,52292E1F20382F155601;006A38075040,0F630141202B454F;0F1118000106287129705B032C2E302F802D4E2B201F,5283583841;002876396577261F20,5282290F;07343588,0652;181100012A0D52832953411E20,2E1F0F4715;0F0001062871292E7C528283032C5C2A15767765,11185D89206B;0F181138171A7975665B52835415,47701F8920;0F181100062839707952542C2E302F03565A7566441F1E,0D29802B20;0F280001363F8A4326232220,2E1F47032F7D;0F17000728705448757A,522E1F15562F;00076A74173926271F1E20,0F7029522B;04170F79195D1A637566363F76,01522E8920;700718111A302F717566,0F2B2E20;11180F000128032A0D7129302C2E2F2D802B09411F1E20,52835438;0076777566262322271F201E,0F11185229;34357C88,8920;010670170F0E3A294152828354262322271F201E,2E181544;01023918112E2D493E52756624262322271F20,;04033918110F0D2C2E7129332D2B72528283547566,;017018110F1A2E15495247828363462322271F,;0F000106387129,2E1F;0F707500261E20,382E1F;181100012C2E2F1F20,0F52;181170792C2F7129,5220;07504088,0F01;0F0001062E7129,5220;7665261F20,0F29;077C343588,87;0F18117052000171291E20,2E1F;0F181100017B7C2E71291F20,036F;181100015B3875,2E20;0F000102702E15471F1E,294F2B452C2F2680;0F000102700D332C712E15261F201E,80036A614738;0001020370392F80712B546675201E26,1F58472E15;0039076A7426271F2048,0F79197029717A38;04031975363F6366,0F5401202C5282832E2F;3807504088,87;00020370454F0D3933192C2E2D156375261F202322,0F71;003F261F202788,87;343588,87;002627651E20232288,87;0F0D33000103452E528283297115752620,63386F70;0003391982835475,2E1F0F6A702971722A0D;0F00010203703915632719792322,8026204529715875;002E4344793F26271F20,03702C2F292B381A;001A2B5448701938754C,152E202425;0039332C2E2D2F152B4644261F1E,0F7019382971637A;11180370392A0D3329712C2F156375795B5D,450C8900382E1F2001;5040000738,0F7D7C584F012063452B;',
'000150402627,0F292F2B;0079110F0304062A528323222627207A19701A2C2E2F5D82,2945;001779332D2322271E2007760304,38290F;0007343588,71297063;0004037039180F332D152952262322271F0C533A82,41178047;0079192E2F030417332D1552837A5D,4E20;001A170F1379232227761926,712938;87,26205282;001A170F5B332E2D7129261E203E5D,15035282;007022230726,2E17712952302F;00077A7088,87;87,;07262723221F40,0F712952;0F000102070D70332C2E19528283297115637526201E2322,;03392D2E332F211D201F1E27,0F7015380029710D1958;343588,87;0F0102700D332C2E2F0319528283531529716345261F2322,;5282835300031929150D332C2E63,0F21704520897175;006A79190F6F2627,6B4620453829;00211D1E232288,;0F7045332C2E71201F1D21,47011552295303;00704888,87;0F00040370396A742E15444948,4589384F20;5282835303702971150D2F,38896A6D0F20;0007504088,87;0F00010203700D332C2E1929711552828353637526202322,;393588,87;007C343588,87;0F11180003706A4F0D332C2E192971155363751F20262322,5247464161;528283545363000103332E15,0F1F197029710D757D20;0F006A1938271779,565A4575522F801F1E63;001D23221E2788,52290F2E1F20;0F175B3975660745514F2B4825201E211D,010352292E;007007482088,2E1F5847;0F110039702C2E522F1574487B7C2D4E804B,098920453861;111852828353546319297115030D332B2C,060F892E38201F;0007504088,0F291570;030102062C2E543E3D636679,380D1946297100;0339332C2E302B66201D1F27,0D2971010015520F6B;34357B7C88,7129;0F111800010203700D332C2E192971152F4B49471F270C2322,52562B20;0F111800010203391929710D1552828353,2075708945630941;00177688,0F52804F25;00396577647969271E2322,52012E1F262061;1707702C2E71291F20,0F52000106111D;0070,0F292C2E791F;0F18110001702C2E7129,6F454F098920;705282835B0D2F71,0F202E41;0007504088,060F71702F29;0F5C5B0001032A0D7052832C2E71291F20,1118517D46;07762623221F1E20,000F1552296B2F;88,6B;181100012A0D2C2E2F2B2D304E447129831F,0F0941613820;03020E0F18110D332C2E2D2F4971293E615244756653,892025;000F76,032E1F522C292B;0028397976771E232227,0F522E474420;7039170F45513A2C2E7129242526271F201D,0001035215;0001027007824878,2E3889201D;703911170E2C2E2D2F4B15712952633D,092B8920;03047039171A533852443D363F,;',
'111879076A1A171523221E272024,5229700F1D012E2B0C2F;390050404C88,0F5282296920;261F1E20232288,52290058363F;0F0001020370332C2E2F1575261F,2971476A45825238;0007343588,0F292F7020;00021719792B155D5466774962,010611180F2920;0F1118528283530001035C702971152B332C2E63201F1E23222621,6B75452D4F80;00177179546A76,0F52443D1F;0001020603700F7B7C2E1F692D48302F565A586366240C21,2B151A2920;0F1A1716007015713F261F2720,5263587D2B4703;005C702C2F802B154C78,5A562E1F2089454663;00037039454F0D332971152C4C48,090F476341382E;11185282837975661271393D692D15565A201E262322,292F060D0C;004088,0F52;767788,5282002920;0F111800010206032A0D097170292D302F1575761320,521F4725;000739343588,520F;181179828354637566,0F52290120;5C0F1811790070528371291F20,2F03805125;003854767788,2E1F5220;0F18110001707B7C0D7129,52565A152B20;170007386A7448363F261F1E,030F79636F20;11180F000102587B7C5282837971302F804B2B497675,09612E1F20;705C4C39171A4F0E7971295B5248,0F2E1F1D;076A171552837982546578,712970010F;004C504088,0F521547;7665262322271F201E21,0F00298071;00010206090D5B7952828354685D7B7C443D77656366201F1E,030F47454F;343588,87;790F181113332C2E2D302F1554,70012038;00040301067018111A0F332C15292A261E200C7A7919712F5D52828354,5617454F;003826232277,632E2052;000106073018110F3329271E0C7A0D75,38262015;0F005B261F20,2E2F;384C,8920;076A696819,0F29;036F791E20,522E1F;00654C88,;262322271F1E20,7129;0F18117000012E71291F20,527A;0039343588,;1811795B5466,0120;0F1811705200012E71291F20,062B;003F88,87;000102035270392E2D5863,0F381D2B29212015;00391A6A15384C4943363F7448,0F0379472B63;00701A17794C0F302F715475,2E454F892024;000102037039714515750D33,201D381F092E0F11;5282835479036A2627201E,0F380D70297115012F;4C4088,87;261F201E232288,;002627241F1E20232288,;0039343588,87;0F0211195465756679,2F384570202B6A;0F0052037029710D332C15,7545584F89201D21;0F003854,20521D21;0F0001020370390D1952828353542971631F0C,1520;0F0001022E154826271F1E203874362322,0363;0001020370392F2971152B54754C,45891F0F2046;000370396A450D332F4B154C,0F20897D41381F2E;',
'00790F072C2E0103047018111A262322271E7A302F5448637545,29381556;6A79363F65,0F292B71;000118111A332C2E2D1571292A23222627200C7A791970302F5D5282835456,387C454F;000118111A332C2E2D1571292A2627200C7A1979,387C;00040318110F1519262322271E2021,52821F38;0039343588,87;00390103040618111A17332C2E262322271E157A7071302F45631F2075,807C;000118111A16175B154C26271E200C232279302F5D528283547543,0F297C7A;074888,87;87,;010670181126271F202165,2938;000770171988,0F2E2038;000106040318111A170F33292A26276A201D0C7A71077C1F1E74694F,52;87,;5282835354037029711575262720,631F58000F2E3801;0F0001020370390D3319297115632E2C752620212322,;0339332C2E1575201E26,0F520D631F29712A724738;343588,87;0F00030D70332C2E3952828353542971156375,6B20;00010203396A79637566201D211E,29387D71707A;00076527262322,1552825A201D0F38;3988,;1500443626271F1E,29710F47380D195203;000788,;0F0370390D332C192E2971637547202322,5815;031A2B7915656A,0F177001204529710D632E2F;0F03700D332C2E2971152F52828363,01004547380C;0F000102030D7033528283534529711520,634758;006A6F391974,0F2E614447702C292F71201F3852;34357B7C88,0F20;11180F00010E715229702E79692C2D2B15093954444C66,2F565A8061;000102033945332C6375201D21,0F1929710D70;07487677393F88,0F2952151F1D;0F17000102060370392E52828353331F,452F2C266A79292B2038;161A0F1526271F4C,5861034738;3950177088,522E1F0F20;11180F0001020370391952835329712B632E7B7C792D2C8020,385D15;00046A7966444C7765,010C202F38520F70292E;70545282832E71291A7933192A5D5A5040,090C384F4520891D6B;0F11180006032A0D70332E011954828371152C202322,58477D63;0F111800037039450D2971332C632026,1F2E2B385282;003934357B7C88,0F20;00481F2023221E27262188,0F292C2E;18117900012C2E5B1F20,0F710D5229;000776776548,0F1118152E1F20;5254700001020612692D4E584647336375662E1F1E,71290D2620;006A583F232227261F20,0F29154703;00077088,522E1F8920;0F5C707971292C2E0E032A0D6A804B2D8B2B3348634C,521109154620;04795B3F651A5D,0F52010620;117154528283292C2E302D4E092A0D50407970443D,56804100;18115452830001712970802D2C2E302F2B2A0D78791F,0F20475861;0F1811000104037115454F7677657B7C392023222726210C,52092E1F;34350088,0F20;0F111800171A454F514E3A3871157765443D23221E262720,80612E1F;111800010206037939695482835D2D2E4E446375661F262120,0F52290D71;767779392623222788,152B1F1D20;000102060717706A33392D2E4E674447482322271E210C,71292B4F20;0F171511793F76584C,0347200C1D;000788,87;'
]
"""每日宜忌数据"""
hour_taboo: List[str] = [
'0F520120,6D61;0F7082520115000255,80262F;707A000855,0102;0100380806,707A2E2C;0F8252150255,70717A7D01002C0306;0F707A0120002C0855,87;,87;0F71822952202C,7A7D0102;0F70825201150255,2E2C;0F295220380255,707A01000306;0F82295201200255,70717A7D2C;0F707A0120002C0855,80262F;707A000855,0102;0F708252150255,2E01002C0806;0F522055,707A01000306;0F700120002C380855,;0F825201150255,70717A7D802C262F;0F70718229527A202C55,0102;,87;0F702952200255,7A7D01000306;0F7082527A01150255,;0F70012000380255,80262F;000855,70717A7D012C02;0F7071527A2055,2E2C;0F522055,707A01000306;0F7001200255,;0F7071297A0115202C55,80262F;0F71822952002C380806,707A0102;0F70825201150255,7A2E2C;0F200255,707A01000306;,87;0F700120002C0855,7A7D80262F;0F7082527A1555,0102;0100380806,2E2C;0F20190255,70717A7D01002C0306;0F707A0120002C0855,87;0F520120,707A6D80262F61;0F7082521555,0102;0F7071297A0115200255,2E2C;0F2952200255,707A01000306;0F825201150255,70717A7D2C;0F7001200255,80262F;,87;,7A2E7D2C;0F712915202C55,707A01000306;0F7029018020002C38,;0F825201150255,70717A7D802C262F;0F70718229527A202C55,0102;0F71822952012002,2E6D2C61;0F7029527A200255,01000806;0F71290115202C,707A55;01002C380806,707A80262F;0F8252150055,70717A7D012C02;0F715220,707A2E2C55;,87;0F7001200255,7A7D;0F825201150255,707A80262F;0F7182295220002C380806,707A010255;0F718229522002,707A2E2C55;0F2952200255,707A01000306',
'0F700120000255,;0F70290120000855,6D61;0F707129527A15802C381955,01000806;0F7101200019020655,707A2C;0F200855,707A2E01002C0306;0F7182520115802C0255,707A;0F700120000255,;,87;0F70297A01202C380955,;0F8252150255,707A01002C0306;0F0120000855,707A2E2C;0F7071297A01158020002C0855,;0F7082520115000255,;0F70717A01201955,6D61;0F7071295215802C3855,01000806;0F0120000206,707A2C;0F290120000855,707A2E2C;0F7082527A0115202C0255,;0100380806,2E2C;,87;0F707129527A011580202C380255,;0F7082520115000255,;0F71202C1955,707A;0F707129527A1556802C1955,;0F202C4B,707A01000306;0F71201955,707A6D61;0F70202C55,01000806;0F0120000206,707A2C;0F7101201955,707A2E2C;0F7129521556802C0255,707A01000306;01002C380806,;,87;0F7129527A0115802C380255,;0F82520115000255,707A2C;0F202C0855,707A01000306;0F7129521556802C1955,707A;0F700120002C0855,;202C,6D61;0F71295215802C3802,01000806;0F2002,707A01002C0306;0F29012002,707A2E2C;0F708229527A0115202C0255,;01002C380806,;,87;0F71295215802C380855,707A01000306;0F82520115000255,707A;0F0120000855,707A2E2C;0F707129527A1556802C1955,;0F7082520115000255,;,707A01000306;0F707129527A15802C3855,01000806;0F290120000855,707A2C;0F71201955,707A2E2C;0F7182520115802C02,707A55;0F202C0855,707A01000306;,87;0F0120002C086C,707A55;0F82520115000255,707A2C;0F2901202C3809,707A55;0F7129521556802C196C,707A0100030655',
'0F70297A0120000855,80262F;0F822952202C,0102;0F71822952012002,7A2E7D2C;0F712915202C55,707A01000306;0F718229520120002C380802066C,707A;707A01000855,80262F;0F7082527A1555,0102;0F7001200255,2E2C;,87;0F7071297A15202C55,01000806;0F7082527A0115000255,80262F;0F82521555,70717A7D012C02;0F70718229527A200255,2E01002C0806;0F52,0120002C080306;0F7182295201202C02,7A7D;0F708252150255,01800026082F06;0F7071297A20002C38080655,0102;0F0120000855,707A2E2C;0F708252150255,0120002C080306;0F822952202C02,01000806;,87;0F7071297A15202C55,0102;0F708252011500380255,2E2C;0F202C4B,01000806;0F71822952202C0255,707A;0F7082527A01150255,80262F;0F71822952202C,7A7D016D02;0F712915202C,01800026082F06;0F71292055,707A01000306;,707A01000806;0F7082527A0115000255,80262F;0F71822952202C,0102;,87;0F712915202C,707A01000306;0F825201150255,707A;0F70825201150255,80262F;0F70717A201955,0102;0F7001200255,2E2C;,707A01000306;0F7071297A15202C55,01000806;0F70297A012000380855,80262F;0F2920,70717A7D016D2C02;0F708252150255,2E01002C0806;,707A01000306;,87;0F7082527A01150255,2E2C;0F8252150038,707A010255;0F82520115000255,70717A7D2C;,707A01000306;0F5220,01000806;0F70297A0120000855,80262F;0F712915202C,016D000806;0F70718229527A01200038080206,2E2C;0F822952202C02,707A01000306;0F825201150255,707A;0F7082527A01150255,80262F;,87;0F7071297A011520002C55,;0F708252150255,01000806;0F8252150255,70717A7D01002C0806',
'0F71822952202C02,707A;0F7029527A0120000255,;0F7071527A202C55,87;0F71295215802C3802,707A01000306;55,707A01000806;0F292055,707A2E2C;0F708229527A202C0255,01000806;0F708252150255,01000806;0F202C0855,707A01000306;,87;0F8229520115200255,707A2C;0F7082527A01150255,;0F7129521556802C1955,707A;2C3808,707A01000306;70297A0120002C0855,87;29202C,6D61;0F708229527A202C0255,01000806;0F71522055,707A2E01002C0806;0F7129521556802C0855,707A01000306;0F7082520115000255,;0F71290120002C080206,87;,87;0F0120004B,707A2C;0F8252150255,707A2E01002C0306;71295201155680002C0855,707A;0F70290120002C06,;0F822952202C0255,01000806;71295215802C38,01000806;0F7071822952202C0255,01000806;0F70718229520120002C080255,;0F70718229527A202C0255,;0F7082527A01150255,;0F70717A01200008190655,87;,87;0F8229520115200255,707A2C;0F708229527A0115202C0255,;0F707129527A011556802C026C,;2C38,01000806;0F202C0855,707A01000306;0F70712952011580202C380255,;0F718229522002,707A01002C0806;0F295201200255,707A2E2C;0F707129527A011556802C026C,;0F8252150255,707A01000306;0F70297A01202C0255,87;,87;0F8252150255,707A01002C0806;0F8252150255,707A2E01002C0806;0F712952155680202C0255,707A01000306;0F7029012000080255,;0F70718229527A202C0255,87;0F707129527A0180202C0255,;,707A01000806;0F822952202C02,707A01000306;707129527A01155680002C0855,;0F70822952011520002C0255,;0F822952202C02,01000806;,87;0F8252150255,707A01002C0306;0F82520115000255,707A2E2C',
'0F82521555,70717A7D016D2C02;,2E2C;0F5220,707A01000306;0F0120000206,707A;0F825201150255,707A80262F;0F70717A202C381955,01000806;0F0120000206,70717A7D2C;0F7129202C1955,707A01000306;0F7082527A0115000255,;0F7082520115000255,80262F;,87;0F70717A0120003808190655,2E2C;0F8252150255,707A01000306;,2E2C;0F7082527A01150255,80262F;0F70200006,7A7D016D02;0F7071297A01152055,2E6D2C41;2C38,01000806;0F290120000855,70717A7D2C;0F70825201150255,80262F;0F702920002C,0102;0F0120004B,2E2C;,87;0F70717A0120002C3808190655,;0F7082520115000255,80262F;,0102;0F7071527A01200655,2E2C;0F702002,7A7D01000306;0F7129011520002C,6D41;0F70825215380255,01800026082F06;0F200006,70717A7D016D2C02;,2E2C;0F82521502,707A0100030655;0F7082520115000255,7A7D;,87;0F70717A20002C3808190655,016D02;0F825201150255,70717A7D2C;0F7129202C1955,707A01000306;0F520120006C,707A55;0F7082520115000255,7A7D80262F;0F712915202C,707A016D02;0F70717A20381955,2E01002C0806;0F29202C02,707A01000306;0F82295201202C02,707A;0F70825201150255,80262F;0F7082521555,7A7D016D02;,87;0F71202C38081955,707A01000306;0F82520115000255,70717A7D2C;0F70825201150255,80262F;0F70527A2055,016D02;0F0120000206,707A2E2C;0F712915202C,707A016D00034106;2C38,707A01000806;0F82520115000255,70717A7D802C262F;0F822952202C,0102;0F7082527A01150255,2E2C;0F708252150255,7A7D01000306;,87;01002C380806,80262F',
'0F8229520102,707A202C03;0F7182520115802C0255,707A;0F29522055,707A01000306;0F70718229527A01202C0255,87;0F707129527A15803855,202C03;0F71822952200255,707A2C03;0F71822952012002,707A2E2C;0F7129521556802C0855,707A01000306;0F700120000255,;0F70010255,202C03;0F707129520115800038,202C03;,87;0F29522055,707A2E01002C0306;0F707182527A0115802C0255,;0F70297A55,202C03;0F7071297A0255,202C03;0F718229520120002C080206,;0F29200855,707A01000306;55,707A2E01002C0806;0F7071295201155680000855,202C03;0F01004B,202C03;0F825201150255,707A;0F7129521580202C3855,707A01000306;,87;0F70297A55,202C03;0F707182520115800255,202C03;0F7182295201002C38080206,;0F29200855,707A01000306;0F70297A202C02,01000806;0F70297A01000855,202C03;0F712920,707A2E01002C080306;0F7129521556802C55,707A;0F8252150255,707A01000306;0F8252011502,707A55;0F29526C,707A202C0355;,87;0F718229522002,707A2E2C;0F71825215802C0255,707A01000306;0F70202C55,01000806;0F707A01000855,202C03;0F707129520115800038,202C03;0F290180202C380955,707A6D61;0F7029527A2055,01000806;0F707129527A1556802C0255,;0F71520106,707A202C03;0F70825201150255,202C03;0F718229520120002C080206,;,87;0F200255,707A2E01002C0806;0F70718252011580000255,202C03;0F715201066C,707A202C03;0F290180202C380955,707A;0F71295215802C3855,707A01000306;0F70717A20190255,016D00086106;0F712952,0120002C080306;0F70718229527A0255,202C03;0F7182295201002C38080206,707A;0F8252150255,707A01000306;0F70202C55,01000806;,87',
',87;0F822952200255,70717A7D01002C0306;0F70825201150255,87;0F7082527A01150255,2E2C;0F70202C55,7A7D0102;0F7029527A012055,2E2C;0F2920380855,707A01000306;0F82520115000255,70717A7D2C;0F7082527A01150255,80262F;0F52202C,016D02;0F70825201150255,7A2E7D2C;0F71822952202C0255,707A01000306;,87;0F825201150255,70717A7D802C262F;0F712952202C,0102;0F70527A012055,2E2C;700855,7A7D01000306;0F7071297A011520002C55,;0F8252011500380255,707A80262F;0F7082521555,010002;0F71290120,707A2E2C;0F71822952202C02,707A0100030655;0F7082527A01150255,;0F7001200255,2E2C;,87;0F707A01200255,2E2C;0F82521502,707A0100030655;0F0120002C086C,707A55;0F7082527A01150255,80262F;0F712915202C,016D02;0F2901203809,707A2E2C;0F708252150255,01000806;0F7182295201202C02,87;0F7082527A01150255,80262F;0F7082527A1555,0102;0F7071297A01152055,2E2C;,87;0F707A01200255,;0F70825201150255,80262F;0F52202C,016D02;0F71522055,707A2E2C;0F712915202C02,707A01000306;0F718229520120002C3802,6D41;0F7082527A150255,01800026082F06;0F71822952202C,0102;0F70527A012055,2E2C;0855,707A01000306;707A01000855,;,87;0F522055,70717A7D012C02;0F825201150255,707A2E2C;0F71822952202C02,707A01000306;0F707182295201202C0255,7A7D;0F7082527A01150255,80262F;0F71822952002C380806,016D0241;0F70200255,2E01002C0806;0855,707A01000306;0F700120002C0855,;0F70825201150255,7A7D80262F;0F712915202C,016D02',
'0F290120002C0855,707A;,87;0F7071295201155680002C0206,;0F70822952011520002C0255,;0F70297A01202C0255,87;0F70712901158020002C380855,;0F8252150255,707A01000306;0F71201955,707A2E6D2C61;0F70297A0120002C0206,;0F710120002C3808190655,707A;0F290120002C0855,707A;0F71825215802C380255,707A01000306;,707A2E2C;,87;0F7071295201155680002C0855,;0F7082520115000255,;0F7120081955,707A01000306;0F7071295201158020002C380206,;0F0120004B,707A2C;0F71201955,707A;0F707129521556802C55,01000806;2C3808,707A0100030655;0F71201955,707A;0F70822952011520002C0255,;0F01200255,707A2C;,87;0F7129521556802C0855,707A01000306;0F70290120002C,;0F2901202C,87;0F71295201158020002C380206,707A;0F01200255,707A2C;0F71201955,707A2E016D002C036106;0F7129521556802C02,01000806;0F8229520120002C02,;0F70297A01202C0255,87;0F7082520115000255,;0F202C0855,707A01000306;,87;0F7071297A0120002C19020655,;0F82520115000255,707A;0F70297A01202C0255,87;0F71295215802C3802,707A01000306;0F825201150255,707A2C;0F71201955,707A2E2C;0F70712952155680202C0255,01000806;0F70290120000855,;0F202C0855,707A01000306;0F70718252011580002C380255,;0F7129202C1955,707A;,87;0F707129520115568020002C0255,;0F8252150255,707A01000306;0F70717A201955,2E2C;0F70290120002C0206,;0F01200255,707A2C;0F290120000855,707A2E6D2C61;0F707129521556802C55,01000806;01002C380806,;0F71201955,707A;0F718252011580002C380255,707A',
'0F708252150255,01000806;0F707A010255,202C03;,87;2920002C0806,0102;0F7082527A01150255,2E2C;0F200255,707A01000306;0F7029527A0155,202C03;0F7082527A011500380255,80262F;0F82295220,70717A7D016D2C02;0F70717A201955,2E01002C0806;0F70527A2055,01000806;707A55,0120002C080306;0F70825201150255,80262F;002C380806,707A010255;,87;0F2002,707A0100030655;0F7029527A010255,202C03;0F0120002C4B02,80262F;0F7071297A15202C55,0102;0F70717A0120003808190655,2E2C;0F8229522002,70717A7D01002C0806;707A55,0120002C080306;0F7082527A01150255,80262F;29202C,7A7D016D02;0F7082520115000255,2E2C;0F71202C38081955,707A01000306;,87;0F70825201150255,80262F;0F7082521555,0102;0F7082527A01150255,2E2C;0F7071297A15202C55,01000806;0F700255,0120002C080306;0F825201150255,70717A7D6D802C262F61;,016D0002;0F70297A0120000855,2E2C;0F70200255,7A7D01000306;0F708229527A01150255,202C03;0F7082527A011500380255,80262F;,87;0F70717A201955,2E2C;0F708252150255,01000806;0F708252150255,0120002C080306;0F7082527A01150255,80262F;0F70717A2000381955,0102;0F290120000855,70717A7D2C;0F70202C55,01000806;0F70527A0155,202C03;0F70825201150255,7A7D80262F;0F7082521555,0102;0F70717A0120003808190655,2E2C;,87;0F7055,0120002C080306;0F70825201150255,80262F;0F7082521555,7A7D016D02;0F70297A0120000855,2E2C;0F71202C38081955,707A01000306;0F29522055,70717A7D2C03;0F708252150255,01800026082F06;0F522055,707A0102;0F71201955,707A2E2C',
'71295215802C380855,707A01000306;0F825201150255,707A2C;0F822952011520000255,707A2E2C;,87;0F708252150255,01000806;0F8252150255,707A01000306;0F70718229527A202C0255,;0F292055,707A2C;0F82295201200255,707A2E2C;0F707129527A011556802C55,6D41;707A55,01000806;,707A55;0F70297A0120002C0855,;0F7082520115000255,;,707A2E01002C0806;,87;0F718229520120002C080206,;0F825201150255,707A;0F82295201202C02,707A55;,707A55;0855,707A2E01002C0306;0F707129527A1556802C55,6D41;0F7029202C55,01000806;0F700120002C0855,87;0F707129527A15802C3855,01000806;0F708252150255,01000806;0F71822952012002,707A2E2C;,87;0F7082520115000255,;0F825201150255,707A;71295215802C380855,707A01000306;,707A2C;0F0120000855,707A2E2C;0F7029012000080255,6D41;0F707152202C,01000806;0F71822952202C02,01000806;0F70718229527A01202C0255,;0F708229527A0115202C0255,;0F8229520120000255,707A2E2C;,87;0F8252150255,707A01000306;0F70825201150255,87;0F707A0120002C0855,;0F700120002C080255,;,707A2E01002C0806;0F71822952202C02,01000806;0F718229522C3802,01000806;0F2952202C55,707A;0F707129527A0115802C380255,;0F2901802000,707A2C;0855,707A2E01002C0306;,87;0F70822952011520002C0255,;0F7082520115000255,;0F707129527A15802C380255,01000806;0F718229522002,707A01002C0806;0F7182295201200002,707A2E2C;0F702901202C0255,6D41;2C38,01000806;0F7071297A2055,87',
'0F7071201955,7A7D;0F71290115202C,707A80262F;0F70825215003855,016D02;0F825201150255,70717A7D2C;,87;0F520120,707A55;0F825201150255,707A80262F;0F71291520002C,016D02;0100380806,707A2E2C55;0F71201955,707A01000306;0F71295201202C,6D61;0F5220,01800026082F06;0F7071201955,7A7D016D02;0F7129011520,707A2E2C;2C3808,707A01000306;0F0120004B,70717A7D2C;,87;0F5220,016D02;0F70825201150255,7A2E7D2C;0F712915202C,707A01000306;0F70717A0120002C3808190655,;0F7082527A01150255,80262F;0F70200006,016D0261;0F5220,2E01002C0806;0F71201955,707A01000306;0F7129011520002C,707A;0F708252011500380255,80262F;0F82521555,70717A7D016D2C02;,87;0F5220,707A01000306;0F70825201150255,7A7D;0F825201150255,707A80262F;002C380806,016D02;0F201955,70717A7D2C;0F2002,707A016D00036106;0F5220,01000806;0F825201150255,707A80262F;0F71291520002C,016D02;0F708252011500380255,2E2C;0F8252150255,70717A7D01002C0306;,87;0F7082527A01150255,80262F;0F7082527A1555,016D02;0F7129011520,707A2E2C;2C3808,707A01000306;0F71201955,707A;0F7082520115000255,80262F;0F5220,016D0002;0F7071201955,7A2E7D2C;0F712915202C,707A01000306;0F7082527A011500380255,;0F825201150255,70717A7D802C262F;,87;0F7071520120002C06,;0F29202C55,707A01000306;0F7129011520002C,707A;0F8252011500380255,707A80262F;0F71201955,707A0102;0F700120000206,6D61;0F5220,01000806',
'0F7182295201202C02,707A55;0F7029527A0120002C0255,;0F82520115000255,707A2C03;0F82520115000255,707A2E2C;0F7129521556802C1955,707A01000306;,87;0F7129202C196C,707A55;0F7182520115803802,707A202C0355;0F29522055,707A2C;0F71822952200255,707A2E01002C0306;0F718229520120002C080206,;0F290120000855,707A;0F700255,0120002C080306;707129527A011580002C380855,;0F204B,707A01002C0306;0F825201150255,707A;0F7071297A202C1955,;,87;0F707A01200255,87;0F71825215802C380255,707A01000306;0F7182295201202C02,;0F290120000855,707A2E2C;0F7071295201155680000855,202C03;01000855,707A;0F70717A201955,01000806;0F7129520115802C3855,707A;0F8229520115200255,707A2C;0F825201150255,707A2E2C03;0F707129527A1580202C55,;,87;0F70718229527A202C0255,87;0F70718252011580002C380255,;0F01200255,707A2C03;01000855,707A2E2C;0F7129521556802C1955,707A01000306;01002C380806,707A6D41;0F7071297A202C1955,01000806;0F707129527A15803855,202C03;0F01200255,707A2C;0F8252150255,707A01000306;0F71822952202C02,;,87;0F707A010255,202C03;707129527A011580002C380855,;0F29202C3809,707A01000306;0F71201955,707A;0F7071297A202C1955,;0100380806,6D202C0341;0F7029527A2055,01000806;0F71295215802C3855,707A01000306;0F825201150255,707A2C;0F822952011520000255,707A2E2C;0F7071295201155680000855,202C03;,87;0F29202C380955,707A01000306;0F7182520115802C380255,707A;29202C,707A;0F71292055,707A2E2C03;0F707129527A1556802C55,;0F71822952202C02,707A016D00034106'
]
"""时辰宜忌数据"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Taboo:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Taboo:
return cls(index)
def next(self, n: int) -> Taboo:
return Taboo(self.next_index(n))
@classmethod
def _get_taboos(cls, data: List[str], sup_index: int, sub_index: int, index: int) -> List[Taboo]:
l: List[Taboo] = []
d: str = data[sup_index].split(';', -1)[sub_index].split(',', -1)[index]
for i in range(0, d.__len__(), 2):
l.append(Taboo(int(d[i:i + 2], 16)))
return l
@classmethod
def get_day_recommends(cls, month: SixtyCycle, day: SixtyCycle) -> List[Taboo]:
"""
日宜
:param month: 月干支
:param day: 日干支
:return: 宜忌列表
"""
return Taboo._get_taboos(Taboo.day_taboo, month.get_earth_branch().get_index(), day.get_index(), 0)
@classmethod
def get_day_avoids(cls, month: SixtyCycle, day: SixtyCycle) -> List[Taboo]:
"""
日忌
:param month:月干支
:param day: 日干支
:return: 宜忌列表
"""
return Taboo._get_taboos(Taboo.day_taboo, month.get_earth_branch().get_index(), day.get_index(), 1)
@classmethod
def get_hour_recommends(cls, day: SixtyCycle, hour: SixtyCycle) -> List[Taboo]:
"""
时辰宜
:param day: 日干支
:param hour: 时辰干支
:return: 宜忌列表
"""
return Taboo._get_taboos(Taboo.hour_taboo, hour.get_earth_branch().get_index(), day.get_index(), 0)
@classmethod
def get_hour_avoids(cls, day: SixtyCycle, hour: SixtyCycle) -> List[Taboo]:
"""
时辰忌
:param day: 日干支
:param hour:时辰干支
:return: 宜忌列表
"""
return Taboo._get_taboos(Taboo.hour_taboo, hour.get_earth_branch().get_index(), day.get_index(), 1)
class Ten(LoopTyme):
"""旬"""
NAMES: List[str] = ['甲子', '甲戌', '甲申', '甲午', '甲辰', '甲寅']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Ten:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Ten:
return cls(index)
def next(self, n: int):
return Ten(self.next_index(n))
class Terrain(LoopTyme):
"""地势(长生十二神)"""
NAMES: List[str] = ['长生', '沐浴', '冠带', '临官', '帝旺', '衰', '病', '死', '墓', '绝', '胎', '养']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Terrain:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Terrain:
return cls(index)
def next(self, n: int) -> Terrain:
return Terrain(self.next_index(n))
class Twenty(LoopTyme):
"""运(20年=1运,3运=1元)"""
NAMES: List[str] = ['一运', '二运', '三运', '四运', '五运', '六运', '七运', '八运', '九运']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Twenty:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Twenty:
return cls(index)
def next(self, n: int) -> Twenty:
return Twenty(self.next_index(n))
def get_sixty(self) -> Sixty:
"""
元
:return: 元
"""
return Sixty(self.get_index() // 3)
class Week(LoopTyme):
"""星期"""
NAMES: List[str] = ['日', '一', '二', '三', '四', '五', '六']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Week:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Week:
return cls(index)
def next(self, n: int) -> Week:
return Week(self.next_index(n))
def get_seven_star(self) -> SevenStar:
"""
七曜
:return: 七曜
"""
from tyme4py.culture.star.seven import SevenStar
return SevenStar(self.get_index())
class Zodiac(LoopTyme):
"""十二生肖"""
NAMES: List[str] = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Zodiac:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Zodiac:
return cls(index)
def next(self, n: int) -> Zodiac:
return Zodiac(self.next_index(n))
def get_earth_branch(self) -> EarthBranch:
"""
地支
:return: 地支
"""
from tyme4py.sixtycycle import EarthBranch
return EarthBranch(self.get_index())
class Zone(LoopTyme):
"""宫"""
NAMES: List[str] = ['东', '北', '西', '南']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Zone:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Zone:
return cls(index)
def next(self, n: int) -> Zone:
return Zone(self.next_index(n))
def get_direction(self) -> Direction:
"""
方位
:return: 方位
"""
return Direction(self.get_name())
def get_beast(self) -> Beast:
"""
神兽
:return: 神兽
"""
return Beast(self.get_index())
+40
View File
@@ -0,0 +1,40 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme, AbstractCultureDay
class Dog(LoopTyme):
"""三伏"""
NAMES: List[str] = ['初伏', '中伏', '末伏']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Dog:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Dog:
return cls(index)
def next(self, n: int) -> Dog:
return Dog(self.next_index(n))
class DogDay(AbstractCultureDay):
"""三伏天"""
def __init__(self, dog: Dog, day_index: int):
super().__init__(dog, day_index)
def get_dog(self) -> Dog:
"""
三伏
:return: 三伏
"""
return self.get_culture()
+149
View File
@@ -0,0 +1,149 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import TYPE_CHECKING, Union, List
from tyme4py import LoopTyme, AbstractCulture
from tyme4py.culture import Direction
from tyme4py.enums import Side
if TYPE_CHECKING:
from tyme4py.lunar import LunarDay, LunarMonth
from tyme4py.sixtycycle import SixtyCycle, SixtyCycleDay
class FetusEarthBranch(LoopTyme):
"""地支六甲胎神"""
NAMES: List[str] = ['碓', '厕', '炉', '门', '栖', '床']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> FetusEarthBranch:
return cls(name)
@classmethod
def from_index(cls, index: int) -> FetusEarthBranch:
return cls(index)
def next(self, n: int):
return FetusEarthBranch(self.next_index(n))
class FetusHeavenStem(LoopTyme):
"""天干六甲胎神"""
NAMES: List[str] = ['门', '碓磨', '厨灶', '仓库', '房床']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> FetusHeavenStem:
return cls(name)
@classmethod
def from_index(cls, index: int) -> FetusHeavenStem:
return cls(index)
def next(self, n: int) -> FetusHeavenStem:
return FetusHeavenStem(self.next_index(n))
class FetusMonth(LoopTyme):
"""逐月胎神"""
NAMES: List[str] = ['占房床', '占户窗', '占门堂', '占厨灶', '占房床', '占床仓', '占碓磨', '占厕户', '占门房', '占房床', '占灶炉', '占房床']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> FetusMonth:
return cls(name)
@classmethod
def from_index(cls, index: int) -> FetusMonth:
return cls(index)
@classmethod
def from_lunar_month(cls, lunar_month: LunarMonth) -> Union[FetusMonth, None]:
"""
从农历月初始化
:param lunar_month: 农历月
:return: 逐月胎神
"""
return None if lunar_month.is_leap() else cls(lunar_month.get_month() - 1)
def next(self, n: int) -> FetusMonth:
return FetusMonth(self.next_index(n))
class FetusDay(AbstractCulture):
"""逐日胎神"""
def __init__(self, sixty_cycle: SixtyCycle):
self._fetus_heaven_stem = FetusHeavenStem(sixty_cycle.get_heaven_stem().get_index() % 5)
self._fetus_earth_branch = FetusEarthBranch(sixty_cycle.get_earth_branch().get_index() % 6)
index: int = [3, 3, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, -9, -9, -9, -9, -9, -5, -5, -1, -1, -1, -3, -7, -7, -7, -7, -5, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 3, 3, 3, 3][sixty_cycle.get_index()]
self._side = Side.IN if index < 0 else Side.OUT
self._direction = Direction(index)
@classmethod
def from_lunar_day(cls, lunar_day: LunarDay) -> FetusDay:
return cls(lunar_day.get_sixty_cycle())
@classmethod
def from_sixty_cycle_day(cls, sixty_cycle_day: SixtyCycleDay) -> FetusDay:
return cls(sixty_cycle_day.get_sixty_cycle())
def get_name(self) -> str:
s: str = self._fetus_heaven_stem.get_name() + self._fetus_earth_branch.get_name()
if '门门' == s:
s = '占大门'
elif '碓磨碓' == s:
s = '占碓磨'
elif '房床床' == s:
s = '占房床'
elif s.startswith('门'):
s = '占' + s
s += ' '
if Side.IN == self._side:
s += '房内'
else:
s += '外'
direction_name: str = self._direction.get_name()
if Side.OUT == self._side and '北南西东'.find(direction_name) != -1:
s += '正'
s += direction_name
return s
def get_side(self) -> Side:
"""
内外
:return: 内外
"""
return self._side
def get_direction(self) -> Direction:
"""
方位
:return: 方位
"""
return self._direction
def get_fetus_heaven_stem(self) -> FetusHeavenStem:
"""
天干六甲胎神
:return: 天干六甲胎神
"""
return self._fetus_heaven_stem
def get_fetus_earth_branch(self) -> FetusEarthBranch:
"""
地支六甲胎神
:return: 地支六甲胎神
"""
return self._fetus_earth_branch
+41
View File
@@ -0,0 +1,41 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import Union, List
from tyme4py import LoopTyme, AbstractCultureDay
class Nine(LoopTyme):
"""数九"""
NAMES: List[str] = ['一九', '二九', '三九', '四九', '五九', '六九', '七九', '八九', '九九']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Nine:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Nine:
return cls(index)
def next(self, n: int):
return Nine(self.next_index(n))
class NineDay(AbstractCultureDay):
"""数九天"""
def __init__(self, nine: Nine, day_index: int):
super().__init__(nine, day_index)
def get_nine(self) -> Nine:
"""
数九
:return: 数九
"""
return self.get_culture()
+78
View File
@@ -0,0 +1,78 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import TYPE_CHECKING, List, Union
from tyme4py import LoopTyme, AbstractCulture
if TYPE_CHECKING:
from tyme4py.sixtycycle import SixtyCycle
class PengZuEarthBranch(LoopTyme):
"""地支彭祖百忌"""
NAMES: List[str] = ['子不问卜自惹祸殃', '丑不冠带主不还乡', '寅不祭祀神鬼不尝', '卯不穿井水泉不香', '辰不哭泣必主重丧', '巳不远行财物伏藏', '午不苫盖屋主更张', '未不服药毒气入肠', '申不安床鬼祟入房', '酉不会客醉坐颠狂', '戌不吃犬作怪上床', '亥不嫁娶不利新郎']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> PengZuEarthBranch:
return cls(name)
@classmethod
def from_index(cls, index: int) -> PengZuEarthBranch:
return cls(index)
def next(self, n: int):
return PengZuEarthBranch(self.next_index(n))
class PengZuHeavenStem(LoopTyme):
"""天干彭祖百忌"""
NAMES: List[str] = ['甲不开仓财物耗散', '乙不栽植千株不长', '丙不修灶必见灾殃', '丁不剃头头必生疮', '戊不受田田主不祥', '己不破券二比并亡', '庚不经络织机虚张', '辛不合酱主人不尝', '壬不泱水更难提防', '癸不词讼理弱敌强']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> PengZuHeavenStem:
return cls(name)
@classmethod
def from_index(cls, index: int) -> PengZuHeavenStem:
return cls(index)
def next(self, n: int) -> PengZuHeavenStem:
return PengZuHeavenStem(self.next_index(n))
class PengZu(AbstractCulture):
"""彭祖百忌"""
def __init__(self, sixty_cycle: SixtyCycle):
self._peng_zu_heaven_stem = PengZuHeavenStem(sixty_cycle.get_heaven_stem().get_index())
self._peng_zu_earth_branch = PengZuEarthBranch(sixty_cycle.get_earth_branch().get_index())
@classmethod
def from_sixty_cycle(cls, sixty_cycle: SixtyCycle) -> PengZu:
return cls(sixty_cycle)
def get_name(self) -> str:
return self._peng_zu_heaven_stem.get_name() + " " + self._peng_zu_earth_branch.get_name()
def get_peng_zu_heaven_stem(self) -> PengZuHeavenStem:
"""
天干彭祖百忌
:return: 天干彭祖百忌
"""
return self._peng_zu_heaven_stem
def get_peng_zu_earth_branch(self) -> PengZuEarthBranch:
"""
地支彭祖百忌
:return: 地支彭祖百忌
"""
return self._peng_zu_earth_branch
+87
View File
@@ -0,0 +1,87 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme, AbstractCultureDay
from tyme4py.jd import JulianDay
from tyme4py.util import ShouXingUtil
class Phenology(LoopTyme):
"""候"""
NAMES: List[str] = ['蚯蚓结', '麋角解', '水泉动', '雁北乡', '鹊始巢', '雉始雊', '鸡始乳', '征鸟厉疾', '水泽腹坚', '东风解冻', '蛰虫始振', '鱼陟负冰', '獭祭鱼', '候雁北', '草木萌动', '桃始华', '仓庚鸣', '鹰化为鸠', '玄鸟至', '雷乃发声', '始电', '桐始华', '田鼠化为鴽', '虹始见', '萍始生', '鸣鸠拂其羽', '戴胜降于桑', '蝼蝈鸣', '蚯蚓出', '王瓜生', '苦菜秀', '靡草死', '麦秋至', '螳螂生', '鵙始鸣', '反舌无声', '鹿角解', '蜩始鸣', '半夏生', '温风至', '蟋蟀居壁', '鹰始挚', '腐草为萤', '土润溽暑', '大雨行时', '凉风至', '白露降', '寒蝉鸣', '鹰乃祭鸟', '天地始肃', '禾乃登', '鸿雁来', '玄鸟归', '群鸟养羞', '雷始收声', '蛰虫坯户', '水始涸', '鸿雁来宾', '雀入大水为蛤', '菊有黄花', '豺乃祭兽', '草木黄落', '蛰虫咸俯', '水始冰', '地始冻', '雉入大水为蜃', '虹藏不见', '天气上升地气下降', '闭塞而成冬', '鹖鴠不鸣', '虎始交', '荔挺出']
"""名称"""
def __init__(self, year: int, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
if isinstance(index_or_name, int):
size: int = self.get_size()
self._year = (year * size + index_or_name) // size
else:
self._year = year
@classmethod
def from_name(cls, year: int, name: str) -> Phenology:
return cls(year, name)
@classmethod
def from_index(cls, year: int, index: int) -> Phenology:
return cls(year, index)
def next(self, n: int) -> Phenology:
size: int = self.get_size()
i: int = self.get_index() + n
return Phenology((self.get_year() * size + i) // size, self.index_of(i, size))
def get_year(self) -> int:
"""
:return: 年
"""
return self._year
def get_three_phenology(self) -> ThreePhenology:
"""
:return: 三候
"""
return ThreePhenology(self.get_index() % 3)
def get_julian_day(self) -> JulianDay:
"""
:return: 儒略日
"""
t = ShouXingUtil.sa_lon_t((self.get_year() - 2000 + (self.get_index() - 18) * 5.0 / 360 + 1) * 2 * ShouXingUtil.PI)
return JulianDay.from_julian_day(t * 36525 + JulianDay.J2000 + 8.0 / 24 - ShouXingUtil.dt_t(t * 36525))
class ThreePhenology(LoopTyme):
"""三候"""
NAMES: List[str] = ['初候', '二候', '三候']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> ThreePhenology:
return cls(name)
@classmethod
def from_index(cls, index: int) -> ThreePhenology:
return cls(index)
def next(self, n: int) -> ThreePhenology:
return ThreePhenology(self.next_index(n))
def get_three_phenology(self) -> ThreePhenology:
return ThreePhenology(self.get_index() % 3)
class PhenologyDay(AbstractCultureDay):
"""七十二候"""
def __init__(self, phenology: Phenology, day_index: int):
super().__init__(phenology, day_index)
def get_phenology(self) -> Phenology:
return super().get_culture()
+43
View File
@@ -0,0 +1,43 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme, AbstractCultureDay
class PlumRain(LoopTyme):
"""梅雨"""
NAMES: List[str] = ['入梅', '出梅']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> PlumRain:
return cls(name)
@classmethod
def from_index(cls, index: int) -> PlumRain:
return cls(index)
def next(self, n: int) -> PlumRain:
return PlumRain(self.next_index(n))
class PlumRainDay(AbstractCultureDay):
"""梅雨天"""
def __init__(self, plum_rain: PlumRain, day_index: int):
super().__init__(plum_rain, day_index)
def get_plum_rain(self) -> PlumRain:
"""
梅雨
:return: 梅雨
"""
return super().get_culture()
def __str__(self) -> str:
return super().__str__() if self.get_plum_rain().get_index() == 0 else self.get_plum_rain().get_name()
+33
View File
@@ -0,0 +1,33 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Luck, Element
class MinorRen(LoopTyme):
"""小六壬"""
NAMES: List[str] = ['大安', '留连', '速喜', '赤口', '小吉', '空亡']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
def next(self, n: int) -> MinorRen:
return MinorRen(self.next_index(n))
def get_luck(self) -> Luck:
"""
吉凶
:return: 吉凶
"""
return Luck(self.get_index() % 2)
def get_element(self) -> Element:
"""
五行
:return: 五行
"""
return Element([0, 4, 1, 3, 0, 2][self.get_index()])
+1
View File
@@ -0,0 +1 @@
# -*- coding:utf-8 -*-
+80
View File
@@ -0,0 +1,80 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Direction, Element
class Dipper(LoopTyme):
"""北斗九星"""
NAMES: List[str] = ['天枢', '天璇', '天玑', '天权', '玉衡', '开阳', '摇光', '洞明', '隐元']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Dipper:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Dipper:
return cls(index)
def next(self, n: int) -> Dipper:
return Dipper(self.next_index(n))
class NineStar(LoopTyme):
"""九星"""
NAMES: List[str] = ['一', '二', '三', '四', '五', '六', '七', '八', '九']
"""名称"""
COLORS: List[str] = ['白', '黑', '碧', '绿', '黄', '白', '赤', '白', '紫']
"""颜色"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> NineStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> NineStar:
return cls(index)
def next(self, n: int) -> NineStar:
return NineStar(self.next_index(n))
def get_color(self) -> str:
"""
颜色
:return: 颜色
"""
return self.COLORS[self.get_index()]
def get_element(self) -> Element:
"""
五行
:return: 五行
"""
return self.get_direction().get_element()
def get_dipper(self) -> Dipper:
"""
北斗九星
:return: 北斗九星
"""
return Dipper(self.get_index())
def get_direction(self) -> Direction:
"""
方位
:return: 方位
"""
return Direction(self.get_index())
def __str__(self) -> str:
return f'{self.get_name()}{self.get_color()}{self.get_element().get_name()}'
+33
View File
@@ -0,0 +1,33 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Week
class SevenStar(LoopTyme):
"""七曜(七政、七纬、七耀)"""
NAMES: List[str] = ['日', '月', '火', '水', '木', '金', '土']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> SevenStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> SevenStar:
return cls(index)
def next(self, n: int) -> SevenStar:
return SevenStar(super().next_index(n))
def get_week(self) -> Week:
"""
:return:星期
"""
return Week(self.get_index())
+26
View File
@@ -0,0 +1,26 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
class SixStar(LoopTyme):
"""六曜"""
NAMES: List[str] = ['先胜', '友引', '先负', '佛灭', '大安', '赤口']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> SixStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> SixStar:
return cls(index)
def next(self, n: int) -> SixStar:
return SixStar(self.next_index(n))
+26
View File
@@ -0,0 +1,26 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
class TenStar(LoopTyme):
"""十神"""
NAMES: List[str] = ['比肩', '劫财', '食神', '伤官', '偏财', '正财', '七杀', '正官', '偏印', '正印']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> TenStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> TenStar:
return cls(index)
def next(self, n: int) -> TenStar:
return TenStar(self.next_index(n))
+61
View File
@@ -0,0 +1,61 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Luck
class TwelveStar(LoopTyme):
"""黄道黑道十二神"""
NAMES: List[str] = ['青龙', '明堂', '天刑', '朱雀', '金匮', '天德', '白虎', '玉堂', '天牢', '玄武', '司命', '勾陈']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> TwelveStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> TwelveStar:
return cls(index)
def next(self, n: int) -> TwelveStar:
return TwelveStar(self.next_index(n))
def get_ecliptic(self) -> Ecliptic:
"""
黄道黑道
:return: 黄道黑道
"""
return Ecliptic([0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1][self.get_index()])
class Ecliptic(LoopTyme):
"""黄道黑道就两种,依次为:黄道、黑道。"""
NAMES: List[str] = ["黄道", "黑道"]
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> Ecliptic:
return cls(name)
@classmethod
def from_index(cls, index: int) -> Ecliptic:
return cls(index)
def next(self, n: int) -> Ecliptic:
return Ecliptic(self.next_index(n))
def get_luck(self) -> Luck:
"""
吉凶
:return: 吉凶
"""
return Luck(self.get_index())
+61
View File
@@ -0,0 +1,61 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import TYPE_CHECKING, List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Land, Animal, Luck, Zone
if TYPE_CHECKING:
from tyme4py.culture.star.seven import SevenStar
class TwentyEightStar(LoopTyme):
"""二十八宿"""
NAMES: List[str] = ['角', '亢', '氐', '房', '心', '尾', '箕', '斗', '牛', '女', '虚', '危', '室', '壁', '奎', '娄', '胃', '昴', '毕', '觜', '参', '井', '鬼', '柳', '星', '张', '翼', '轸']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> TwentyEightStar:
return cls(name)
@classmethod
def from_index(cls, index: int) -> TwentyEightStar:
return cls(index)
def next(self, n: int) -> TwentyEightStar:
return TwentyEightStar(self.next_index(n))
def get_seven_star(self) -> SevenStar:
"""
:return: 七曜
"""
from tyme4py.culture.star.seven import SevenStar
return SevenStar(self.get_index() % 7 + 4)
def get_land(self) -> Land:
"""
:return: 九野
"""
return Land([4, 4, 4, 2, 2, 2, 7, 7, 7, 0, 0, 0, 0, 5, 5, 5, 6, 6, 6, 1, 1, 1, 8, 8, 8, 3, 3, 3][self.get_index()])
def get_zone(self) -> Zone:
"""
:return: 宫
"""
return Zone(self.get_index() // 7)
def get_animal(self) -> Animal:
"""
:return: 动物
"""
return Animal(self.get_index())
def get_luck(self) -> Luck:
"""
:return: 吉凶
"""
return Luck([0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0][self.get_index()])
+501
View File
@@ -0,0 +1,501 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
import warnings
from math import ceil
from typing import TYPE_CHECKING, Union, List
from tyme4py import AbstractCulture, AbstractTyme
from tyme4py.culture import Duty
from tyme4py.eightchar.provider import ChildLimitProvider
from tyme4py.eightchar.provider.impl import DefaultChildLimitProvider
from tyme4py.enums import Gender, YinYang
if TYPE_CHECKING:
from tyme4py.lunar import LunarYear
from tyme4py.solar import SolarTime, SolarTerm, SolarDay
from tyme4py.sixtycycle import SixtyCycle, SixtyCycleYear, ThreePillars
class EightChar(AbstractCulture):
"""八字"""
def __init__(self, year: Union[SixtyCycle, str], month: Union[SixtyCycle, str], day: Union[SixtyCycle, str], hour: Union[SixtyCycle, str]):
"""
初始化
:param year: 年干支
:param month: 月干支
:param day: 日干支
:param hour: 时干支
"""
from tyme4py.sixtycycle import SixtyCycle, ThreePillars
self._three_pillars = ThreePillars(year if isinstance(year, SixtyCycle) else SixtyCycle(year), month if isinstance(month, SixtyCycle) else SixtyCycle(month), day if isinstance(day, SixtyCycle) else SixtyCycle(day))
self._hour = hour if isinstance(hour, SixtyCycle) else SixtyCycle(hour)
def get_year(self) -> SixtyCycle:
"""
年柱
:return: 干支 SixtyCycle
"""
return self._three_pillars.get_year()
def get_month(self) -> SixtyCycle:
"""
月柱
:return: 干支 SixtyCycle
"""
return self._three_pillars.get_month()
def get_day(self) -> SixtyCycle:
"""
日柱
:return: 干支 SixtyCycle
"""
return self._three_pillars.get_day()
def get_hour(self) -> SixtyCycle:
"""
时柱
:return: 干支 SixtyCycle
"""
return self._hour
def get_fetal_origin(self) -> SixtyCycle:
"""
胎元
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
m: SixtyCycle = self.get_month()
return SixtyCycle.from_index(m.get_heaven_stem().next(1).get_index() * 6 - m.get_earth_branch().next(3).get_index() * 5)
def get_fetal_breath(self) -> SixtyCycle:
"""
胎息
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
d: SixtyCycle = self.get_day()
return SixtyCycle.from_index(d.get_heaven_stem().next(5).get_index() * 6 + d.get_earth_branch().get_index() * 5 - 65)
def get_own_sign(self) -> SixtyCycle:
"""
命宫
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle.from_index(self.get_year().get_heaven_stem().get_index() * 12 + (27 - self.get_month().get_earth_branch().get_index() - self._hour.get_earth_branch().get_index()) % 12 + 2)
def get_body_sign(self) -> SixtyCycle:
"""
身宫
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle.from_index(self.get_year().get_heaven_stem().get_index() * 12 + (11 + self.get_month().get_earth_branch().get_index() + self._hour.get_earth_branch().get_index()) % 12 + 2)
def get_duty(self) -> Duty:
"""
建除十二值神
:return: 建除十二值神
"""
warnings.warn('get_duty() is deprecated, please use SixtyCycleDay.get_duty() instead.', DeprecationWarning)
return Duty(self.get_day().get_earth_branch().get_index() - self.get_month().get_earth_branch().get_index())
def get_name(self) -> str:
return f'{self._three_pillars} {self._hour}'
def get_solar_times(self, start_year: int, end_year: int) -> List[SolarTime]:
"""
八字转公历时刻列表
:param start_year: 开始年份,支持1-9999年
:param end_year: 结束年份,支持1-9999年
:return: 公历时刻 SolarTime的列表
"""
from tyme4py.sixtycycle import HeavenStem
from tyme4py.solar import SolarTime, SolarTerm
l: List[SolarTime] = []
year = self.get_year()
month = self.get_month()
day = self.get_day()
# 月地支距寅月的偏移值
m: int = month.get_earth_branch().next(-2).get_index()
# 月天干要一致
if not HeavenStem((year.get_heaven_stem().get_index() + 1) * 2 + m) == month.get_heaven_stem():
return l
# 1年的立春是辛酉,序号57
y: int = year.next(-57).get_index() + 1
# 节令偏移值
m *= 2
# 时辰地支转时刻
h: int = self._hour.get_earth_branch().get_index() * 2
# 兼容子时多流派
hours: List[int] = [0, 23] if h == 0 else [h]
base_year: int = start_year - 1
if base_year > y:
y += 60 * int(ceil((base_year - y) / 60.0))
while y <= end_year:
# 立春为寅月的开始
term: SolarTerm = SolarTerm(y, 3)
# 节令推移,年干支和月干支就都匹配上了
if m > 0:
term = term.next(m)
solar_time: SolarTime = term.get_julian_day().get_solar_time()
if solar_time.get_year() >= start_year:
# 日干支和节令干支的偏移值
solar_day: SolarDay = solar_time.get_solar_day()
d: int = day.next(-solar_day.get_lunar_day().get_sixty_cycle().get_index()).get_index()
if d > 0:
# 从节令推移天数
solar_day = solar_day.next(d)
for i in range(0, hours.__len__()):
mi: int = 0
s: int = 0
hour: int = hours[i]
if d == 0 and hour == solar_time.get_hour():
# 如果正好是节令当天,且小时和节令的小时数相等的极端情况,把分钟和秒钟带上
mi = solar_time.get_minute()
s = solar_time.get_second()
time: SolarTime = SolarTime(solar_day.get_year(), solar_day.get_month(), solar_day.get_day(), hour, mi, s)
if d == 30:
time = time.next(-3600)
# 验证一下
if time.get_lunar_hour().get_eight_char() == self:
l.append(time)
y += 60
return l
class ChildLimitInfo:
"""童限信息"""
def __init__(self, start_time: SolarTime, end_time: SolarTime, year_count: int, month_count: int, day_count: int, hour_count: int, minute_count: int):
"""
初始化
:param start_time: 开始(即出生)的公历时刻
:param end_time: 结束(即开始起运)的公历时刻
:param year_count: 年数
:param month_count: 月数
:param day_count: 日数
:param hour_count: 小时数
:param minute_count: 分钟数
"""
self._start_time = start_time
self._end_time = end_time
self._year_count = year_count
self._month_count = month_count
self._day_count = day_count
self._hour_count = hour_count
self._minute_count = minute_count
def get_start_time(self) -> SolarTime:
"""
:return: 开始(即出生)的公历时刻
"""
return self._start_time
def get_end_time(self) -> SolarTime:
"""
:return: 结束(即开始起运)的公历时刻
"""
return self._end_time
def get_year_count(self) -> int:
"""
:return: 年数
"""
return self._year_count
def get_month_count(self) -> int:
"""
:return: 月数
"""
return self._month_count
def get_day_count(self) -> int:
"""
:return: 日数
"""
return self._day_count
def get_hour_count(self) -> int:
"""
:return: 小时数
"""
return self._hour_count
def get_minute_count(self) -> int:
"""
:return: 分钟数
"""
return self._minute_count
class ChildLimit:
"""童限(从出生到起运的时间段)"""
provider: ChildLimitProvider = DefaultChildLimitProvider()
"""童限计算接口"""
def __init__(self, birth_time: SolarTime, gender: Gender):
"""
通过出生公历时刻初始化
:param birth_time: 出生公历时刻
:param gender: 性别
"""
self._gender = gender
self._eight_char = birth_time.get_lunar_hour().get_eight_char()
# 阳男阴女顺推,阴男阳女逆推
yang: bool = YinYang.YANG == self._eight_char.get_year().get_heaven_stem().get_yin_yang()
man: bool = Gender.MAN == gender
self._forward = (yang and man) or (not yang and not man)
term: SolarTerm = birth_time.get_term()
if not term.is_jie():
term = term.next(-1)
if self._forward:
term = term.next(2)
self._info = ChildLimit.provider.get_info(birth_time, term)
def get_eight_char(self) -> EightChar:
"""
:return: 八字
"""
return self._eight_char
def get_gender(self) -> Gender:
"""
:return: 性别
"""
return self._gender
def get_year_count(self) -> int:
"""
:return: 年数
"""
return self._info.get_year_count()
def get_month_count(self) -> int:
"""
:return: 月数
"""
return self._info.get_month_count()
def get_day_count(self) -> int:
"""
:return: 日数
"""
return self._info.get_day_count()
def get_hour_count(self) -> int:
"""
:return: 小时数
"""
return self._info.get_hour_count()
def get_minute_count(self) -> int:
"""
:return: 分钟数
"""
return self._info.get_minute_count()
def get_start_time(self) -> SolarTime:
"""
开始(即出生)的公历时刻
:return: 公历时刻
"""
return self._info.get_start_time()
def get_end_time(self) -> SolarTime:
"""
结束(即开始起运)的公历时刻
:return: 公历时刻
"""
return self._info.get_end_time()
def is_forward(self) -> bool:
"""
是否顺推
:return: true/false
"""
return self._forward
def get_start_decade_fortune(self) -> DecadeFortune:
"""
:return: 起运大运
"""
return DecadeFortune(self, 0)
def get_decade_fortune(self) -> DecadeFortune:
"""
:return: 所属大运
"""
return DecadeFortune(self, -1)
def get_start_fortune(self) -> Fortune:
"""
:return: 小运
"""
return Fortune(self, 0)
def get_end_lunar_year(self) -> LunarYear:
"""
结束农历年
:return: 农历年
"""
warnings.warn('get_end_lunar_year() is deprecated, please use SixtyCycleDay.get_duty() instead.', DeprecationWarning)
from tyme4py.lunar import LunarYear
return LunarYear.from_year(self.get_start_time().get_lunar_hour().get_year() + self.get_end_time().get_year() - self.get_start_time().get_year())
def get_start_sixty_cycle_year(self) -> SixtyCycleYear:
"""
开始(即出生)干支年
:return: 干支年
"""
from tyme4py.sixtycycle import SixtyCycleYear
return SixtyCycleYear.from_year(self.get_start_time().get_year())
def get_end_sixty_cycle_year(self) -> SixtyCycleYear:
"""
结束(即起运)干支年
:return: 干支年
"""
from tyme4py.sixtycycle import SixtyCycleYear
return SixtyCycleYear.from_year(self.get_end_time().get_year())
@staticmethod
def get_start_age() -> int:
"""
开始年龄
:return: 数字
"""
return 1
def get_end_age(self) -> int:
"""
结束年龄
:return: 数字
"""
n: int = self.get_end_sixty_cycle_year().get_year() - self.get_start_sixty_cycle_year().get_year()
return max(n, 1)
class Fortune(AbstractTyme):
"""小运--在十年大运中,每一年为一小运。童限结束的公历时刻,既是大运的开始,也是小运的开始。"""
def __init__(self, child_limit: ChildLimit, index: int):
"""
通过童限初始化
:param child_limit: 童限
:param index: 序号
"""
self._child_limit = child_limit
self._index = index
def get_age(self) -> int:
"""
:return: 年龄
"""
return self._child_limit.get_end_sixty_cycle_year().get_year() - self._child_limit.get_start_sixty_cycle_year().get_year() + 1 + self._index
def get_lunar_year(self) -> LunarYear:
"""
:return: 农历年
"""
warnings.warn('get_lunar_year() is deprecated, please use get_sixty_cycle_year() instead.', DeprecationWarning)
return self._child_limit.get_end_lunar_year().next(self._index)
def get_sixty_cycle_year(self) -> SixtyCycleYear:
"""
:return: 干支年
"""
return self._child_limit.get_end_sixty_cycle_year().next(self._index)
def get_sixty_cycle(self) -> SixtyCycle:
"""
:return: 干支
"""
n: int = self.get_age()
return self._child_limit.get_eight_char().get_hour().next(n if self._child_limit.is_forward() else -n)
def get_name(self) -> str:
return self.get_sixty_cycle().get_name()
def next(self, n: int) -> Fortune:
return Fortune(self._child_limit, self._index + n)
class DecadeFortune(AbstractTyme):
"""大运(10年1大运)--自起运开始,每十年为一大运。童限结束的公历时刻,即开始起运,是大运的开始。"""
def __init__(self, child_limit: ChildLimit, index: int):
"""
通过童限初始化
:param child_limit: 童限
:param index: 序号
"""
self._child_limit = child_limit
self._index = index
def get_start_age(self) -> int:
"""
:return: 开始年龄
"""
return self._child_limit.get_end_sixty_cycle_year().get_year() - self._child_limit.get_start_sixty_cycle_year().get_year() + 1 + self._index * 10
def get_end_age(self) -> int:
"""
:return: 结束年龄
"""
return self.get_start_age() + 9
def get_start_lunar_year(self) -> LunarYear:
"""
开始农历年
:return: 农历年
"""
warnings.warn('get_lunar_year() is deprecated, please use get_sixty_cycle_year() instead.', DeprecationWarning)
return self._child_limit.get_end_lunar_year().next(self._index * 10)
def get_end_lunar_year(self) -> LunarYear:
"""
结束农历年
:return: 农历年
"""
warnings.warn('get_lunar_year() is deprecated, please use get_sixty_cycle_year() instead.', DeprecationWarning)
return self.get_start_lunar_year().next(9)
def get_start_sixty_cycle_year(self) -> SixtyCycleYear:
"""
开始干支年
:return: 干支年
"""
return self._child_limit.get_end_sixty_cycle_year().next(self._index * 10)
def get_end_sixty_cycle_year(self) -> SixtyCycleYear:
"""
结束干支年
:return: 干支年
"""
return self.get_start_sixty_cycle_year().next(9)
def get_sixty_cycle(self) -> SixtyCycle:
"""
:return: 干支
"""
return self._child_limit.get_eight_char().get_month().next(self._index + 1 if self._child_limit.is_forward() else -self._index - 1)
def get_name(self) -> str:
return self.get_sixty_cycle().get_name()
def next(self, n: int) -> DecadeFortune:
return DecadeFortune(self._child_limit, self._index + n)
def get_start_fortune(self) -> Fortune:
"""
本轮大运中开始的小运
:return: 小运 Fortune
"""
return Fortune(self._child_limit, self._index * 10)
+38
View File
@@ -0,0 +1,38 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from tyme4py.eightchar import EightChar
from tyme4py.lunar import LunarHour
from tyme4py.solar import SolarTime, SolarTerm
from tyme4py.eightchar import ChildLimitInfo
class EightCharProvider(ABC):
"""八字计算接口"""
@abstractmethod
def get_eight_char(self, hour: LunarHour) -> EightChar:
"""
八字
:param hour: 农历时辰
:return: 八字 EightChar
"""
pass
class ChildLimitProvider(ABC):
"""童限计算接口"""
@abstractmethod
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
"""
童限信息
:param birth_time:出生公历时刻
:param term: 节令
:return: 童限信息
"""
pass
+141
View File
@@ -0,0 +1,141 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from abc import abstractmethod
from typing import TYPE_CHECKING
from tyme4py.eightchar.provider import EightCharProvider, ChildLimitProvider
if TYPE_CHECKING:
from tyme4py.eightchar import EightChar, ChildLimitInfo
from tyme4py.lunar import LunarHour
from tyme4py.solar import SolarTime, SolarTerm, SolarMonth
class DefaultEightCharProvider(EightCharProvider):
"""默认的八字计算(晚子时算第二天)"""
def get_eight_char(self, hour: LunarHour) -> EightChar:
return hour.get_sixty_cycle_hour().get_eight_char()
class LunarSect2EightCharProvider(EightCharProvider):
"""Lunar流派2的八字计算(晚子时日柱算当天)"""
def get_eight_char(self, hour: LunarHour) -> EightChar:
from tyme4py.eightchar import EightChar
from tyme4py.sixtycycle import SixtyCycleHour
h: SixtyCycleHour = hour.get_sixty_cycle_hour()
return EightChar(h.get_year(), h.get_month(), hour.get_lunar_day().get_sixty_cycle(), h.get_sixty_cycle())
class AbstractChildLimitProvider(ChildLimitProvider):
"""童限计算抽象"""
@staticmethod
def next(birth_time: SolarTime, add_year: int, add_month: int, add_day: int, add_hour: int, add_minute: int, add_second: int) -> ChildLimitInfo:
from tyme4py.solar import SolarTime, SolarMonth
from tyme4py.eightchar import ChildLimitInfo
d: int = birth_time.get_day() + add_day
h: int = birth_time.get_hour() + add_hour
mi: int = birth_time.get_minute() + add_minute
s: int = birth_time.get_second() + add_second
mi += s // 60
s %= 60
h += mi // 60
mi %= 60
d += h // 24
h %= 24
sm: SolarMonth = SolarMonth(birth_time.get_year() + add_year, birth_time.get_month()).next(add_month)
dc: int = sm.get_day_count()
while d > dc:
d -= dc
sm = sm.next(1)
dc = sm.get_day_count()
return ChildLimitInfo(birth_time, SolarTime(sm.get_year(), sm.get_month(), d, h, mi, s), add_year, add_month, add_day, add_hour, add_minute)
@abstractmethod
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
pass
class DefaultChildLimitProvider(AbstractChildLimitProvider):
"""默认的八字计算(晚子时算第二天)"""
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
# 出生时刻和节令时刻相差的秒数
seconds: int = abs(term.get_julian_day().get_solar_time().subtract(birth_time))
# 3天 = 1年,3天=60*60*24*3秒=259200秒 = 1年
year: int = seconds // 259200
seconds %= 259200
# 1天 = 4月,1天=60*60*24秒=86400秒 = 4月,85400秒/4=21600秒 = 1月
month: int = seconds // 21600
seconds %= 21600
# 1时 = 5天,1时=60*60秒=3600秒 = 5天,3600秒/5=720秒 = 1天
day: int = seconds // 720
seconds %= 720
# 1分 = 2时,60秒 = 2时,60秒/2=30秒 = 1时
hour: int = seconds // 30
seconds %= 30
# 1秒 = 2分,1秒/2=0.5秒 = 1分
minute: int = seconds * 2
return AbstractChildLimitProvider.next(birth_time, year, month, day, hour, minute, 0)
class China95ChildLimitProvider(AbstractChildLimitProvider):
"""元亨利贞的童限计算"""
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
# 出生时刻和节令时刻相差的分钟数
minutes: int = int(abs(term.get_julian_day().get_solar_time().subtract(birth_time)) / 60)
year: int = minutes // 4320
minutes %= 4320
month: int = minutes // 360
minutes %= 360
day: int = minutes // 12
return AbstractChildLimitProvider.next(birth_time, year, month, day, 0, 0, 0)
class LunarSect1ChildLimitProvider(AbstractChildLimitProvider):
"""Lunar的流派1童限计算(按天数和时辰数计算,3天1年,1天4个月,1时辰10天)"""
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
term_time: SolarTime = term.get_julian_day().get_solar_time()
end: SolarTime = term_time
start: SolarTime = birth_time
if birth_time.is_after(term_time):
end = birth_time
start = term_time
end_time_zhi_index: int = 11 if end.get_hour() == 23 else end.get_lunar_hour().get_index_in_day()
start_time_zhi_index: int = 11 if start.get_hour() == 23 else start.get_lunar_hour().get_index_in_day()
# 时辰差
hour_diff: int = end_time_zhi_index - start_time_zhi_index
# 天数差
day_diff: int = end.get_solar_day().subtract(start.get_solar_day())
if hour_diff < 0:
hour_diff += 12
day_diff -= 1
month_diff: int = int(hour_diff * 10 / 30)
month: int = day_diff * 4 + month_diff
day: int = hour_diff * 10 - month_diff * 30
year: int = int(month / 12)
month = month - year * 12
return AbstractChildLimitProvider.next(birth_time, year, month, day, 0, 0, 0)
class LunarSect2ChildLimitProvider(AbstractChildLimitProvider):
"""Lunar的流派2童限计算(按分钟数计算)"""
def get_info(self, birth_time: SolarTime, term: SolarTerm) -> ChildLimitInfo:
# 出生时刻和节令时刻相差的分钟数
minutes: int = int(abs(term.get_julian_day().get_solar_time().subtract(birth_time)) / 60)
year: int = int(minutes / 4320)
minutes %= 4320
month: int = int(minutes / 360)
minutes %= 360
day: int = int(minutes / 12)
minutes %= 12
hour: int = minutes * 2
return AbstractChildLimitProvider.next(birth_time, year, month, day, hour, 0, 0)
+52
View File
@@ -0,0 +1,52 @@
# -*- coding:utf-8 -*-
from enum import Enum
class YinYang(Enum):
"""阴阳:YIN=0=阴,YANG=1=阳"""
YIN = 0
"""阴"""
YANG = 1
"""阳"""
class Side(Enum):
"""内外:IN=0=内,OUT=1=外"""
IN = 0
"""内"""
OUT = 1
"""外"""
class Gender(Enum):
"""性别:WOMAN=0=女,MAN=1=男"""
WOMAN = 0
"""女"""
MAN = 1
"""男"""
class HideHeavenStemType(Enum):
"""藏干类型:RESIDUAL=0=余气,MIDDLE=1=中气,MAIN=2=本气"""
RESIDUAL = 0
"""余气"""
MIDDLE = 1
"""中气"""
MAIN = 2
"""本气"""
class EventType(Enum):
"""事件类型"""
SOLAR_DAY = 0
"""公历日期"""
SOLAR_WEEK = 1
"""几月第几个星期几"""
LUNAR_DAY = 2
"""农历日期"""
TERM_DAY = 3
"""节气日期"""
TERM_HS = 4
"""节气天干"""
TERM_EB = 5
"""节气地支"""
+361
View File
@@ -0,0 +1,361 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
import re
from typing import Union, List, TYPE_CHECKING
from tyme4py import AbstractCulture
from tyme4py.enums import EventType
if TYPE_CHECKING:
from tyme4py.solar import SolarMonth, SolarDay, SolarTerm
from tyme4py.lunar import LunarMonth, LunarDay
class Event(AbstractCulture):
"""事件"""
def __init__(self, name: str, data: str):
Event.validate(data)
self._name = name
self._data = data
@staticmethod
def validate(data: str) -> None:
if len(data) != 9:
raise ValueError(f'illegal event data: {data}')
@staticmethod
def builder() -> EventBuilder:
"""构造器"""
return EventBuilder()
@classmethod
def from_name(cls, name: str) -> Union[Event, None]:
pattern: re.Pattern[str] = re.compile(f'{EventManager.REGEX}{name}')
matcher: Union[re.Match[str], None] = pattern.search(EventManager.DATA)
return cls(name, matcher.group(1)) if matcher else None
def _get_char_index(self, index: int) -> int:
return EventManager.CHARS.index(self._data[index])
def get_value(self, index: int) -> int:
return self._get_char_index(index) - 31
def get_month(self, year: int) -> List[int]:
y: int = year
m: int = self.get_value(2)
if m > 12:
m = 1
y += 1
return [y, m]
def get_type(self) -> EventType:
"""事件类型"""
n: int = self._get_char_index(1)
if n == 1:
return EventType.SOLAR_WEEK
if n == 2:
return EventType.LUNAR_DAY
if n == 3:
return EventType.TERM_DAY
if n == 4:
return EventType.TERM_HS
if n == 5:
return EventType.TERM_EB
return EventType.SOLAR_DAY
def get_name(self) -> str:
"""名称"""
return self._name
def get_data(self) -> str:
"""数据"""
return self._data
def get_start_year(self) -> int:
"""起始年"""
n: int = 0
size: int = len(EventManager.CHARS)
for i in range(0, 3):
n = n * size + self._get_char_index(6 + i)
return n
def get_solar_day(self, year: int) -> Union[SolarDay, None]:
if year < self.get_start_year():
return None
t: EventType = self.get_type()
d: Union[SolarDay, None] = None
if t == EventType.SOLAR_DAY:
d = self._get_solar_day_by_solar_day(year)
elif t == EventType.SOLAR_WEEK:
d = self._get_solar_day_by_week(year)
elif t == EventType.LUNAR_DAY:
d = self._get_solar_day_by_lunar_day(year)
elif t == EventType.TERM_DAY:
d = self._get_solar_day_by_term(year)
elif t == EventType.TERM_HS:
d = self._get_solar_day_by_term_heaven_stem(year)
elif t == EventType.TERM_EB:
d = self._get_solar_day_by_term_earth_branch(year)
if d is None:
return None
offset: int = self.get_value(5)
return d if 0 == offset else d.next(offset)
def _get_solar_day_by_solar_day(self, year: int) -> Union[SolarDay, None]:
from tyme4py.solar import SolarMonth, SolarDay
month: List[int] = self.get_month(year)
y: int = month[0]
m: int = month[1]
d: int = self.get_value(3)
delay: int = self.get_value(4)
last_day: int = SolarMonth.from_ym(y, m).get_day_count()
if d > last_day:
if 0 == delay:
return None
elif delay < 0:
return SolarDay.from_ymd(y, m, d + delay)
return SolarDay.from_ymd(y, m, last_day).next(delay)
return SolarDay.from_ymd(y, m, d)
def _get_solar_day_by_lunar_day(self, year: int) -> Union[SolarDay, None]:
from tyme4py.lunar import LunarMonth, LunarDay
month: List[int] = self.get_month(year)
y: int = month[0]
m: int = month[1]
d: int = self.get_value(3)
delay: int = self.get_value(4)
last_day: int = LunarMonth.from_ym(y, m).get_day_count()
if d > last_day:
if 0 == delay:
return None
elif delay < 0:
return LunarDay.from_ymd(y, m, d + delay).get_solar_day()
return LunarDay.from_ymd(y, m, last_day).get_solar_day().next(delay)
return LunarDay.from_ymd(y, m, d).get_solar_day()
def _get_solar_day_by_week(self, year: int) -> Union[SolarDay, None]:
from tyme4py.solar import SolarMonth, SolarDay
# 第几个星期
n: int = self.get_value(3)
if n == 0:
return None
m: SolarMonth = SolarMonth.from_ym(year, self.get_value(2))
# 星期几
w: int = self.get_value(4)
if n > 0:
# 当月第1天
d: SolarDay = m.get_first_day()
# 往后找第几个星期几
return d.next(d.get_week().steps_to(w) + 7 * n - 7)
# 当月最后一天
d: SolarDay = SolarDay.from_ymd(year, m.get_month(), m.get_day_count())
# 往前找第几个星期几
return d.next(d.get_week().steps_back_to(w) + 7 * n + 7)
def _get_solar_day_by_term(self, year: int) -> Union[SolarDay, None]:
from tyme4py.solar import SolarTerm, SolarDay
d: SolarDay = SolarTerm.from_index(year, self.get_value(2)).get_solar_day()
offset: int = self.get_value(4)
return d if 0 == offset else d.next(offset)
def _get_solar_day_by_term_heaven_stem(self, year: int) -> Union[SolarDay, None]:
from tyme4py.solar import SolarDay
d: SolarDay = self._get_solar_day_by_term(year)
return d.next(d.get_lunar_day().get_sixty_cycle().get_heaven_stem().steps_to(self.get_value(3)))
def _get_solar_day_by_term_earth_branch(self, year: int) -> Union[SolarDay, None]:
from tyme4py.solar import SolarDay
d: SolarDay = self._get_solar_day_by_term(year)
return d.next(d.get_lunar_day().get_sixty_cycle().get_earth_branch().steps_to(self.get_value(3)))
@classmethod
def from_solar_day(cls, d: SolarDay) -> List[Event]:
"""
指定公历日的事件列表
:param d: 公历日
"""
l: List[Event] = []
for e in cls.all():
if d == e.get_solar_day(d.get_year()):
l.append(e)
return l
@classmethod
def all(cls) -> List[Event]:
l: List[Event] = []
pattern: re.Pattern[str] = re.compile(f'{EventManager.REGEX}(.[^@]+)')
matcher: Union[re.Match[str], None] = pattern.search(EventManager.DATA)
while matcher:
l.append(cls(matcher.group(2), matcher.group(1)))
matcher = pattern.search(EventManager.DATA, matcher.end())
return l
class EventBuilder:
"""事件构造器"""
def __init__(self):
self._name = ''
self._data = ['@', '_', '_', '_', '_', '_', '0', '0', '0']
def name(self, n: str) -> EventBuilder:
self._name = n
return self
@staticmethod
def _get_char(index: int) -> str:
return EventManager.CHARS[index]
def _set_value(self, index: int, n: int) -> EventBuilder:
self._data[index] = self._get_char(31 + n)
return self
@staticmethod
def encode_type(t: EventType) -> str:
n: int = 0
if t == EventType.SOLAR_WEEK:
n = 1
elif t == EventType.LUNAR_DAY:
n = 2
elif t == EventType.TERM_DAY:
n = 3
elif t == EventType.TERM_HS:
n = 4
elif t == EventType.TERM_EB:
n = 5
return EventBuilder._get_char(n)
def _content(self, t: EventType, a: int, b: int, c: int) -> EventBuilder:
self._data[1] = self.encode_type(t)
return self._set_value(2, a)._set_value(3, b)._set_value(4, c)
def solar_day(self, solar_month: int, solar_day: int, delay_days: int) -> EventBuilder:
"""
公历日
:param solar_month: 公历月(1至12)
:param solar_day: 公历日(1至31)
:param delay_days: 顺延天数,例如生日在2月29,非闰年没有2月29,是+1天,还是-1天(最远支持-31至31天)
:return: 事件构造器
"""
return self._content(EventType.SOLAR_DAY, solar_month, solar_day, delay_days)
def lunar_day(self, lunar_month: int, lunar_day: int, delay_days: int) -> EventBuilder:
"""
农历日
:param lunar_month: 农历月(-12至-1,1至12,闰月为负)
:param lunar_day: 农历日(1至30)
:param delay_days: 顺延天数,例如生日在某月的三十,但下一年当月可能只有29天,是+1天,还是-1天(最远支持-31至31天)
:return: 事件构造器
"""
return self._content(EventType.LUNAR_DAY, lunar_month, lunar_day, delay_days)
def solar_week(self, solar_month: int, week_index: int, week: int) -> EventBuilder:
"""
公历第几个星期几
:param solar_month: 公历月(1至12)
:param week_index: 第几个星期(1为第1个星期,-1为倒数第1个星期)
:param week: 星期几(0至6,0代表星期天,1代表星期一)
:return: 事件构造器
"""
return self._content(EventType.SOLAR_WEEK, solar_month, week_index, week)
def term_day(self, term_index: int, delay_days: int) -> EventBuilder:
"""
节气
:param term_index: 节气索引(0至23)
:param delay_days: 顺延天数(最远支持-31至31天)
:return: 事件构造器
"""
return self._content(EventType.TERM_DAY, term_index, 0, delay_days)
def term_heaven_stem(self, term_index: int, heaven_stem_index: int, delay_days: int) -> EventBuilder:
"""
节气天干
:param term_index: 节气索引(0至23)
:param heaven_stem_index: 天干索引(0至9)
:param delay_days: 顺延天数(最远支持-31至31天)
:return: 事件构造器
"""
return self._content(EventType.TERM_HS, term_index, heaven_stem_index, delay_days)
def term_earth_branch(self, term_index: int, earth_branch_index: int, delay_days: int) -> EventBuilder:
"""
节气地支
:param term_index: 节气索引(0至23)
:param earth_branch_index: 地支索引(0至11)
:param delay_days: 顺延天数(最远支持-31至31天)
:return: 事件构造器
"""
return self._content(EventType.TERM_EB, term_index, earth_branch_index, delay_days)
def start_year(self, year: int) -> EventBuilder:
"""
起始年
:param year: 年
:return: 事件构造器
"""
size: int = len(EventManager.CHARS)
n: int = year
for i in range(3):
self._data[8 - i] = self._get_char(n % size)
n //= size
return self
def offset(self, days: int) -> EventBuilder:
"""
偏移天数
:param days: 天数(最远支持-31至31天)
:return: 事件构造器
"""
return self._set_value(5, days)
def build(self) -> Event:
"""
生成事件
:return: 事件
"""
return Event(self._name, ''.join(self._data))
class EventManager:
"""事件管理器"""
CHARS: str = '0123456789ABCDEFGHIJKLMNOPQRSTU_VWXYZabcdefghijklmnopqrstuvwxyz'
"""有效字符"""
DATA: str = ''
"""全量事件数据"""
REGEX: str = '(@[0-9A-Za-z_]{8})'
"""数据匹配的正则表达式"""
@classmethod
def remove(cls, name: str) -> None:
"""
删除事件
:param name: 名称
"""
cls.DATA = re.sub(rf'{cls.REGEX}{name}', '', cls.DATA)
@classmethod
def _save_or_update(cls, name: str, data: str) -> None:
"""
删除事件
:param name: 名称
"""
pattern: re.Pattern[str] = re.compile(f'{cls.REGEX}{name}')
matcher: Union[re.Match[str], None] = pattern.search(cls.DATA)
if matcher:
cls.DATA = re.sub(rf'{cls.REGEX}{name}', data, EventManager.DATA)
else:
cls.DATA += data
@classmethod
def update(cls, name: str, e: Event) -> None:
cls._save_or_update(name, e.get_data() + name if e.get_name() is None or len(e.get_name()) < 1 else e.get_name())
@classmethod
def update_data(cls, name: str, data: str) -> None:
Event.validate(data)
cls._save_or_update(name, data)
+205
View File
@@ -0,0 +1,205 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from abc import abstractmethod
from typing import TYPE_CHECKING, List, Union
from tyme4py import AbstractTyme, Tyme
from tyme4py.enums import EventType
from tyme4py.event import Event
from tyme4py.unit import DayUnit
if TYPE_CHECKING:
from tyme4py.lunar import LunarDay
from tyme4py.solar import SolarTerm, SolarDay
class AbstractFestival(AbstractTyme):
@abstractmethod
def next(self, n: int) -> Union[Tyme, None]:
pass
def __init__(self, index: int, event: Event, day: DayUnit):
self._index = index
self._event = event
self._day = day
def get_name(self) -> str:
return self._event.get_name()
def get_index(self) -> int:
"""
:return: 索引
"""
return self._index
def get_day(self) -> DayUnit:
"""
:return: 日
"""
return self._day
def __str__(self) -> str:
return f'{self._day} {self.get_name()}'
class LunarFestival(AbstractFestival):
"""
农历传统节日--依据国家标准《农历的编算和颁行》GB/T 33661-2017
农历传统节日有:春节、元宵节、龙头节、上巳节、清明节、端午节、七夕节、中元节、中秋节、重阳节、冬至节、腊八节、除夕。
"""
NAMES: List[str] = ['春节', '元宵节', '龙头节', '上巳节', '清明节', '端午节', '七夕节', '中元节', '中秋节', '重阳节', '冬至节', '腊八节', '除夕']
"""名称"""
DATA: str = '2VV__0002Vj__0002WW__0002XX__0003b___0002ZZ__0002bb__0002bj__0002cj__0002dd__0003s___0002gc__0002hV_U000'
def __init__(self, index: int, event: Event, day: LunarDay):
"""
实例化
:param index: 索引
:param event: 事件
:param day: 农历日
"""
super().__init__(index, event, day)
@classmethod
def from_index(cls, year: int, index: int) -> Union[LunarFestival, None]:
"""
指定索引得到
:param year: 年
:param index: 索引
:return:
"""
if index < 0 or index >= cls.NAMES.__len__():
return None
from tyme4py.lunar import LunarDay
from tyme4py.solar import SolarTerm
start: int = index * 8
e: Event = Event(LunarFestival.NAMES[index], '@' + LunarFestival.DATA[start: start + 8])
t: EventType = e.get_type()
if t == EventType.LUNAR_DAY:
m: List[int] = e.get_month(year)
d: LunarDay = LunarDay.from_ymd(m[0], m[1], e.get_value(3))
offset: int = e.get_value(5)
return LunarFestival(index, e, d if offset == 0 else d.next(offset))
elif t == EventType.TERM_DAY:
return LunarFestival(index, e, SolarTerm.from_index(year, e.get_value(2)).get_solar_day().get_lunar_day())
return None
@classmethod
def from_ymd(cls, year: int, month: int, day: int) -> Union[LunarFestival, None]:
"""
指定农历年、月、日得到
:param year: 农历年
:param month: 农历月
:param day: 农历日
:return:
"""
from tyme4py.lunar import LunarDay
from tyme4py.solar import SolarTermDay
d: LunarDay = LunarDay.from_ymd(year, month, day)
for i in range(0, LunarFestival.NAMES.__len__()):
start: int = i * 8
e: Event = Event(LunarFestival.NAMES[i], '@' + LunarFestival.DATA[start: start + 8])
t: EventType = e.get_type()
if t == EventType.LUNAR_DAY:
offset: int = e.get_value(5)
if offset == 0:
if d.get_month() == e.get_value(2) and d.get_day() == e.get_value(3):
return LunarFestival(i, e, d)
else:
m: List[int] = e.get_month(d.get_year())
n: LunarDay = d.next(-offset)
if n.get_year() == m[0] and n.get_month() == m[1] and n.get_day() == e.get_value(3):
return LunarFestival(i, e, d)
elif t == EventType.TERM_DAY:
term: SolarTermDay = d.get_solar_day().get_term_day()
if term.get_day_index() == 0 and term.get_solar_term().get_index() == e.get_value(2) % 24:
return LunarFestival(i, e, d)
return None
def get_day(self) -> LunarDay:
"""
:return: 农历日
"""
return super().get_day()
def get_solar_term(self) -> Union[SolarTerm, None]:
"""
节气,非节气返回None
:return: 节气
"""
from tyme4py.solar import SolarTermDay
t: SolarTermDay = self.get_day().get_solar_day().get_term_day()
return t.get_solar_term() if t.get_day_index() == 0 else None
def next(self, n: int) -> LunarFestival:
size: int = LunarFestival.NAMES.__len__()
i: int = self._index + n
return LunarFestival.from_index(int((self._day.get_year() * size + i) / size), self.index_of(i, size))
class SolarFestival(AbstractFestival):
"""公历现代节日"""
NAMES: List[str] = ['元旦', '妇女节', '植树节', '劳动节', '青年节', '儿童节', '建党节', '建军节', '教师节', '国庆节']
DATA: str = '0VV__0Ux0Xc__0Ux0Xg__0_Q0ZV__0Ux0ZY__0Ux0aV__0Ux0bV__0Uo0cV__0Ug0de__0_V0eV__0Ux'
def __init__(self, index: int, event: Event, day: SolarDay):
"""
实例化
:param index: 索引
:param event: 事件
:param day: 公历日
"""
super().__init__(index, event, day)
@classmethod
def from_index(cls, year: int, index: int) -> Union[SolarFestival, None]:
"""
指定索引得到
:param year: 年份
:param index: 索引
:return:
"""
if index < 0 or index >= cls.NAMES.__len__():
return None
start: int = index * 8
e: Event = Event(SolarFestival.NAMES[index], '@' + SolarFestival.DATA[start: start + 8])
if year < e.get_start_year():
return None
from tyme4py.solar import SolarDay
return SolarFestival(index, e, SolarDay.from_ymd(year, e.get_value(2), e.get_value(3)))
@classmethod
def from_ymd(cls, year: int, month: int, day: int) -> Union[SolarFestival, None]:
"""
指定年、月、日得到
:param year: 年
:param month: 月
:param day: 日
:return:
"""
from tyme4py.solar import SolarDay
d: SolarDay = SolarDay.from_ymd(year, month, day)
for i in range(0, SolarFestival.NAMES.__len__()):
start: int = i * 8
e: Event = Event(SolarFestival.NAMES[i], '@' + SolarFestival.DATA[start: start + 8])
if d.get_year() >= e.get_start_year() and d.get_month() == e.get_value(2) and d.get_day() == e.get_value(3):
return SolarFestival(i, e, d)
return None
def get_day(self) -> SolarDay:
"""
:return: 公历日
"""
return super().get_day()
def get_start_year(self) -> int:
"""
起始年
:return: 年
"""
return self._event.get_start_year()
def next(self, n: int) -> Union[SolarFestival, None]:
size: int = SolarFestival.NAMES.__len__()
i: int = self._index + n
return SolarFestival.from_index(int((self._day.get_year() * size + i) / size), self.index_of(i, size))
+151
View File
@@ -0,0 +1,151 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import List
from tyme4py.jd import JulianDay
from tyme4py.solar import SolarDay
from tyme4py.unit import YearUnit, MonthUnit, DayUnit
class HijriYear(YearUnit):
"""回历年"""
def __init__(self, year):
HijriYear.validate(year)
super().__init__(year)
@staticmethod
def validate(year):
if year < -640 or year > 9666:
raise ValueError(f'illegal hijri year: {year}')
@classmethod
def from_year(cls, year):
return cls(year)
def get_day_count(self):
return 355 if self.is_leap() else 354
def is_leap(self):
i = (self._year - 1) % 30
return i in (1, 4, 6, 9, 12, 15, 17, 20, 23, 25, 28)
def get_name(self):
return f'{self._year}年'
def next(self, n):
return HijriYear.from_year(self._year + n)
def get_months(self):
months = []
for i in range(1, 13):
months.append(HijriMonth(self._year, i))
return months
def get_first_month(self):
return HijriMonth(self._year, 1)
class HijriMonth(MonthUnit):
NAMES: List[str] = ['穆哈兰姆月', '色法尔月', '赖比尔·敖外鲁月', '赖比尔·阿色尼月', '主马达·敖外鲁月', '主马达·阿色尼月', '赖哲卜月', '舍尔邦月', '赖买丹月', '闪瓦鲁月', '都尔喀尔德月', '都尔黑哲月']
@staticmethod
def validate(year, month):
if month < 1 or month > 12:
raise ValueError(f'illegal hijri month: {month}')
HijriYear.validate(year)
def __init__(self, year, month):
HijriMonth.validate(year, month)
super().__init__(year, month)
@classmethod
def from_ym(cls, year, month):
return cls(year, month)
def get_hijri_year(self):
return HijriYear(self._year)
def get_day_count(self):
d = 29 if self._month % 2 == 0 else 30
if self._month == 12 and self.get_hijri_year().is_leap():
d += 1
return d
def get_index_in_year(self):
return self._month - 1
def get_name(self):
return self.NAMES[self.get_index_in_year()]
def __str__(self):
return f'{self.get_hijri_year()}{self.get_name()}'
def next(self, n):
i: int = self._month - 1 + n
return HijriMonth((self._year * 12 + i) // 12, self.index_of(i, 12) + 1)
def get_days(self):
size = self.get_day_count()
days = []
for i in range(1, size + 1):
days.append(HijriDay(self._year, self._month, i))
return days
def get_first_day(self):
return HijriDay(self._year, self._month, 1)
class HijriDay(DayUnit):
NAMES: List[str] = ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日', '30日']
@staticmethod
def validate(year, month, day):
if day < 1 or day > HijriMonth.from_ym(year, month).get_day_count():
raise ValueError(f'illegal hijri day: {year}-{month}-{day}')
def __init__(self, year, month, day):
HijriDay.validate(year, month, day)
super().__init__(year, month, day)
@classmethod
def from_ymd(cls, year, month, day):
return cls(year, month, day)
def get_hijri_month(self):
return HijriMonth(self._year, self._month)
def get_name(self):
return self.NAMES[self._day - 1]
def __str__(self):
return f'{self.get_hijri_month()}{self.get_name()}'
def next(self, n):
return self.get_solar_day().next(n).get_hijri_day()
def is_before(self, target: HijriDay):
if self._year != target._year:
return self._year < target._year
if self._month != target._month:
return self._month < target._month
return self._day < target._day
def is_after(self, target: HijriDay):
if self._year != target._year:
return self._year > target._year
if self._month != target._month:
return self._month > target._month
return self._day > target._day
def get_index_in_year(self):
return self.subtract(HijriDay(self._year, 1, 1))
def subtract(self, target):
return int(self.get_julian_day().subtract(target.get_julian_day()))
def get_julian_day(self):
return JulianDay((11 * self._year + 3) // 30 + 354 * self._year + 30 * self._month - (self._month - 1) // 2 + self._day + 1948055)
def get_solar_day(self):
return SolarDay(622, 7, 16).next(self.subtract(HijriDay(1, 1, 1)))
File diff suppressed because one or more lines are too long
+111
View File
@@ -0,0 +1,111 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from tyme4py import AbstractTyme
from tyme4py.culture import Week
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from tyme4py.solar import SolarDay, SolarTime
class JulianDay(AbstractTyme):
"""儒略日"""
J2000: float = 2451545
"""2000年儒略日数(2000-1-1 12:00:00 UTC)"""
def __init__(self, day: float):
"""
:param day: 为小数
"""
self._day = day
@classmethod
def from_julian_day(cls, day: float) -> JulianDay:
return cls(day)
@classmethod
def from_ymd_hms(cls, year: int, month: int, day: int, hour: int, minute: int, second: int) -> JulianDay:
"""
通过公历年月日时分秒进行初始化
:param year: 年
:param month: 月
:param day: 日
:param hour: 时
:param minute: 分
:param second: 秒
:return:
"""
d: float = day + ((second / 60 + minute) / 60 + hour) / 24
n: int = 0
g: bool = year * 372 + month * 31 + int(d) >= 588829
if month <= 2:
month += 12
year -= 1
if g:
n = int(year * 0.01)
n = 2 - n + int(n * 0.25)
return cls(int(365.25 * (year + 4716)) + int(30.6001 * (month + 1)) + d + n - 1524.5)
def get_day(self) -> float:
"""
:return: 儒略日
"""
return self._day
def get_name(self) -> str:
return f'{self._day}'
def next(self, n: float) -> JulianDay:
return JulianDay(self._day + n)
def get_solar_day(self) -> SolarDay:
"""
:return: 公历日
"""
return self.get_solar_time().get_solar_day()
def get_solar_time(self) -> SolarTime:
"""
:return: 公历时刻
"""
d: int = int(self._day + 0.5)
f: float = self._day + 0.5 - d
if d >= 2299161:
c: int = int((d - 1867216.25) / 36524.25)
d += 1 + c - int(c * 0.25)
d += 1524
y: int = int((d - 122.1) / 365.25)
d -= int(365.25 * y)
m: int = int(d / 30.601)
d -= int(30.601 * m)
if m > 13:
m -= 12
else:
y -= 1
m -= 1
y -= 4715
f *= 24
hour: int = int(f)
f -= hour
f *= 60
minute: int = int(f)
f -= minute
f *= 60
second: int = round(f)
from tyme4py.solar import SolarTime
return SolarTime(y, m, d, hour, minute, second) if second < 60 else SolarTime(y, m, d, hour, minute, second - 60).next(60)
def get_week(self) -> Week:
"""
通过儒略日计算的星期是最准的,基姆拉尔森和蔡勒公式计算星期的准确性,在儒略日面前都是弟弟,不服来辩
:return: 星期
"""
return Week(int(self._day + 0.5) + 7000001)
def subtract(self, target: JulianDay) -> float:
"""
儒略日相减
:param target: 儒略日
:return: 差
"""
return self._day - target.get_day()
+941
View File
@@ -0,0 +1,941 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
import warnings
from math import floor, ceil
from typing import TYPE_CHECKING, List, Union
from tyme4py import LoopTyme
from tyme4py.culture import Twenty, Direction, KitchenGodSteed, Week, Duty, Phase, God, Taboo, PhaseDay
from tyme4py.culture.star.twentyeight import TwentyEightStar
from tyme4py.culture.fetus import FetusMonth, FetusDay
from tyme4py.culture.ren import MinorRen
from tyme4py.culture.star.nine import NineStar
from tyme4py.culture.star.six import SixStar
from tyme4py.culture.star.twelve import TwelveStar
from tyme4py.eightchar import EightChar
from tyme4py.eightchar.provider import EightCharProvider
from tyme4py.eightchar.provider.impl import DefaultEightCharProvider
from tyme4py.festival import LunarFestival
from tyme4py.jd import JulianDay
from tyme4py.unit import YearUnit, MonthUnit, WeekUnit, DayUnit, SecondUnit
from tyme4py.util import ShouXingUtil
if TYPE_CHECKING:
from tyme4py.solar import SolarDay, SolarTime, SolarTerm
from tyme4py.sixtycycle import SixtyCycle, SixtyCycleDay, SixtyCycleHour, ThreePillars
class LunarYear(YearUnit):
"""
农历年
依据国家标准《农历的编算和颁行》GB/T 33661-2017,农历年以正月初一开始,至除夕结束。
"""
_IS_INIT: bool = False
_LEAP: List[List[int]] = []
@staticmethod
def _init():
if LunarYear._IS_INIT:
return
chars: str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_@'
months: List[str] = [
'080b0r0j0j0j0C0j0j0C0j0j0j0C0j0C0j0C0F0j0V0V0V0u0j0j0C0j0j0j0j0V0C0j1v0u0C0V1v0C0b080u110u0C0j0C1v9K1v2z0j1vmZbl1veN3s1v0V0C2S1v0V0C2S2o0C0j1Z1c2S1v0j1c0j2z1v0j1c0j392H0b2_2S0C0V0j1c0j2z0C0C0j0j1c0j0N250j0C0j0b081n080b0C0C0C1c0j0N',
'0r1v1c1v0V0V0F0V0j0C0j0C0j0V0j0u1O0j0C0V0j0j0j0V0b080u0r0u080b0j0j0C0V0C0V0j0b080V0u080b0j0j0u0j1v0u080b1c0j080b0j0V0j0j0V0C0N1v0j1c0j0j1v2g1v420j1c0j2z1v0j1v5Q9z1v4l0j1vfn1v420j9z4l1v1v2S1c0j1v2S3s1v0V0C2S1v1v2S1c0j1v2S2_0b0j2_2z0j1c0j',
'0z0j0j0j0C0j0j0C0j0j0j0C0j0C0j0j0j0j0m0j0C0j0j0C0j0j0j0j0b0V0j0j0C0j0j0j0j0V0j0j0j0V0b0V0V0C0V0C0j0j0b080u110u0V0C0j0N0j0b080b080b0j0r0b0r0b0j0j0j0j0C0j0b0r0C0j0b0j0C0C0j0j0j0j0j0j0j0j0j0b110j0b0j0j0j0C0j0C0j0j0j0j0b080b080b0V080b080b0j0j0j0j0j0j0V0j0j0u1v0j0j0j0C0j0j0j0V0C0N1c0j0C0C0j0j0j1n080b0j0V0C0j0C0C2g0j1c0j0j1v2g1v0j0j1v7N0j1c0j3L0j0j1v5Q1Z5Q1v4lfn1v420j1v5Q1Z5Q1v4l1v2z1v',
'0H140r0N0r140r0u0r0V171c11140C0j0u110j0u0j1v0j0C0j0j0j0b080V0u080b0C1v0j0j0j0C0j0b080V0j0j0b080b0j0j0j0j0b080b0C080j0b080b0j0j0j0j0j0j0b080j0b080C0b080b080b080b0j0j0j0j080b0j0C0j0j0j0b0j0j080C0b0j0j0j0j0j0j0b08080b0j0C0j0j0j0b0j0j0K0b0j0C0j0j0j0b080b080j0C0b0j080b080b0j0j0j0j080b0j0b0r0j0j0j0b0j0C0r0b0j0j0j0j0j0j0j0b080j0b0r0C0j0b0j0j0j0r0b0j0C0j0j0j0u0r0b0C0j080b0j0j0j0j0j0j0j1c0j0b0j0j0j0C0j0j0j0j0j0j0j0b080j1c0u0j0j0j0C0j1c0j0u0j1c0j0j0j0j0j0j0j0j1c0j0u1v0j0j0V0j0j2g0j0j0j0C1v0C1G0j0j0V0C1Z1O0j0V0j0j2g1v0j0j0V0C2g5x1v4l1v421O7N0V0C4l1v2S1c0j1v2S2_',
'050b080C0j0j0j0C0j0j0C0j0j0j0C0j0C0j0C030j0j0j0j0j0j0j0j0j0C0j0b080u0V080b0j0j0V0j0j0j0j0j0j0j0j0j0V0N0j0C0C0j0j0j0j0j0j0j0j1c0j0u0j1v0j0j0j0j0j0b080b080j0j0j0b080b080b080b080b0j0j0j080b0j0b080j0j0j0j0b080b0j0j0r0b080b0b080j0j0j0j0b080b080j0b080j0b080b080b080b080b0j0j0r0b0j0b080j0j0j0j0b080b0j0j0C080b0b080j0j0j0j0j0j0j0b080u080j0j0b0j0j0j0C0j0b080j0j0j0j0b080b080b080b0C080b080b080b0j0j0j0j0j0j0b0C080j0j0b0j0j0j0C0j0b080j0j0C0b080b080j0b0j0j0C080b0j0j0j0j0j0j0b0j0j080C0b0j080b0j0j0j0j0j0j0j0C0j0j0j0b0j0j0C080b0j0j0j0j0j0j0b080b080b0K0b080b080b0j0j0j0j0j0j0j0C0j0j0u0j0j0V0j080b0j0C0j0j0j0b0j0r0C0b0j0j0j0j0j0j0j0j0j0C0j0b080b080b0j0C0C0j0C0j0j0j0u110u0j0j0j0j0j0j0j0j0C0j0j0u0j1c0j0j0j0j0j0j0j0j0V0C0u0j0C0C0V0C1Z0j0j0j0C0j0j0j1v0u0j1c0j0j0j0C0j0j2g0j1c1v0C1Z0V0j4l0j0V0j0j2g0j1v0j1v2S1c7N1v',
'0w0j1c0j0V0j0j0V0V0V0j0m0V0j0C1c140j0j0j0C0V0C0j1v0j0N0j0C0j0j0j0V0j0j1v0N0j0j0V0j0j0j0j0j0j080b0j0j0j0j0j0j0j080b0j0C0j0j0j0b0j0j080u080b0j0j0j0j0j0j0b080b080b080C0b0j080b080b0j0j0j0j080b0j0C0j0j0j0b0j0j080u080b0j0j0j0j0j0j0b080b080b080b0r0b0j080b080b0j0j0j0j080b0j0b0r0j0j0b080b0j0j080b0j080b0j080b080b0j0j0j0j0j0b080b0r0C0b080b0j0j0j0j080b0b080b080j0j0j0b080b080b080b0j0j0j0j080b0j0b080j0j0j0j0b080b0j0j0r0b080b0j0j0j0j0j0b080b080j0b0r0b080j0b080b0j0j0j0j080b0j0b080j0j0j0j0b080b0j080b0r0b0j080b080b0j0j0j0j0j0b080b0r0C0b080b0j0j0j0j0j0j0b080j0j0j0b080b080b080b0j0j0j0r0b0j0b080j0j0j0j0b080b0r0b0r0b0j080b080b0j0j0j0j0j0j0b0r0j0j0j0b0j0j0j0j080b0j0b080j0j0j0j0b080b080b0j0r0b0j080b0j0j0j0j0j0j0j0b0r0C0b0j0j0j0j0j0j0j080b0j0C0j0j0j0b0j0C0r0b0j0j0j0j0j0j0b080b080u0r0b0j080b0j0j0j0j0j0j0j0b0r0C0u0j0j0j0C0j080b0j0C0j0j0j0u110b0j0j0j0j0j0j0j0j0j0C0j0b080b0j0j0C0C0j0C0j0j0j0b0j1c0j080b0j0j0j0j0j0j0V0j0j0u0j1c0j0j0j0C0j0j2g0j0j0j0C0j0j0V0j0b080b1c0C0V0j0j2g0j0j0V0j0j1c0j1Z0j0j0C0C0j1v',
'160j0j0V0j1c0j0C0j0C0j1f0j0V0C0j0j0C0j0j0j1G080b080u0V080b0j0j0V0j1v0j0u0j1c0j0j0j0C0j0j0j0C0C0j1D0b0j080b0j0j0j0j0C0j0b0r0C0j0b0j0C0C0j0j0j0j0j0j0j0j0j0b0r0b0r0j0b0j0j0j0C0j0b0r0j0j0j0b080b080j0b0C0j080b080b0j0j0j0j0j0j0b0C080j0j0b0j0j0j0C0j0b080j0j0j0j0b080b080j0b0C0r0j0b0j0j0j0j0j0j0b0C080j0j0b0j0j0j0C0j0j0j0j0C0j0j0b080b0j0j0C080b0j0j0j0j0j0j0b080b080b080C0b080b080b080b0j0j0j0j0j0b080C0j0j0b080b0j0j0C080b0j0j0j0j0j0j0b080j0b0C080j0j0b0j0j0j0j0j0j0b080j0b080C0b080b080b080b0j0j0j0j080b0j0C0j0j0b080b0j0j0C080b0j0j0j0j0j0j0b080j0b080u080j0j0b0j0j0j0j0j0j0b080C0j0j0b080b0j0j0C0j0j080b0j0j0j0j0j0b080b0C0r0b080b0j0j0j0j0j0j0b080j0b080u080b080b080b0j0j0j0C0j0b080j0j0j0j0b0j0j0j0C0j0j080b0j0j0j0j0j0b080b0C0r0b080b0j0j0j0j0j0j0b080j0b0r0b080b080b080b0j0j0j0r0b0j0b0r0j0j0j0b0j0j0j0r0b0j080b0j0j0j0j0j0j0j0b0r0C0b0j0j0j0j0j0j0j0b080j0C0u080b080b0j0j0j0r0b0j0C0C0j0b0j110b0j080b0j0j0j0j0j0j0u0r0C0b0j0j0j0j0j0j0j0j0j0C0j0j0j0b0j1c0j0C0j0j0j0b0j0814080b080b0j0j0j0j0j0j1c0j0u0j0j0V0j0j0j0j0j0j0j0u110u0j0j0j',
'020b0r0C0j0j0j0C0j0j0V0j0j0j0j0j0C0j1f0j0C0j0V1G0j0j0j0j0V0C0j0C1v0u0j0j0j0V0j0j0C0j0j0j1v0N0C0V0j0j0j0K0C250b0C0V0j0j0V0j0j2g0C0V0j0j0C0j0j0b081v0N0j0j0V0V0j0j0u0j1c0j080b0j0j0j0j0j0j0V0j0j0u0j0j0V0j0j0j0C0j0b080b080V0b0j080b0j0j0j0j0j0j0j0b0r0C0j0b0j0j0j0C0j080b0j0j0j0j0j0j0u0r0C0u0j0j0j0j0j0j0b080j0C0j0b080b080b0j0C0j080b0j0j0j0j0j0j0b080b110b0j0j0j0j0j0j0j0j0j0b0r0j0j0j0b0j0j0j0r0b0j0b080j0j0j0j0b080b080b080b0r0b0j080b080b0j0j0j0j0j0j0b0r0C0b080b0j0j0j0j080b0j0b080j0j0j0j0b080b080b0j0j0j0r0b0j0j0j0j0j0j0b080b0j080C0b0j080b080b0j0j0j0j080b0j0b0r0C0b080b0j0j0j0j080b0j0j0j0j0j0b080b080b080b0j0j080b0r0b0j0j0j0j0j0j0b0j0j080C0b0j080b080b0j0j0j0j0j0b080C0j0j0b080b0j0j0C0j0b080j0j0j0j0b080b080b080b0C0C080b0j0j0j0j0j0j0b0C0C080b080b080b0j0j0j0j0j0j0b0C080j0j0b0j0j0j0C0j0b080j0b080j0j0b080b080b080b0C0r0b0j0j0j0j0j0j0b080b0r0b0r0b0j080b080b0j0j0j0j0j0j0b0r0C0j0b0j0j0j0j0j0j0b080j0C0j0b080j0b0j0j0K0b0j0C0j0j0j0b080b0j0K0b0j080b0j0j0j0j0j0j0V0j0j0b0j0j0j0C0j0j0j0j',
'0l0C0K0N0r0N0j0r1G0V0m0j0V1c0C0j0j0j0j1O0N110u0j0j0j0C0j0j0V0C0j0u110u0j0j0j0C0j0j0j0C0C0j250j1c2S1v1v0j5x2g0j1c0j0j1c2z0j1c0j0j1c0j0N1v0V0C1v0C0b0C0V0j0j0C0j0C1v0u0j0C0C0j0j0j0C0j0j0j0u110u0j0j0j0C0j0C0C0C0b080b0j0C0j080b0j0C0j0j0j0u110u0j0j0j0C0j0j0j0C0j0j0j0u0C0r0u0j0j0j0j0j0j0b0r0b0V080b080b0j0C0j0j0j0V0j0j0b0j0j0j0C0j0j0j0j0j0j0j0b080j0b0C0r0j0b0j0j0j0C0j0b0r0b0r0j0b080b080b0j0C0j0j0j0j0j0j0j0j0b0j0C0r0b0j0j0j0j0j0j0b080b080j0b0r0b0r0j0b0j0j0j0j080b0j0b0r0j0j0j0b080b080b0j0j0j0j080b0j0j0j0j0j0j0b0j0j0j0r0b0j0j0j0j0j0j0b080b080b080b0r0C0b080b0j0j0j0j0j0b080b0r0C0b080b080b080b0j0j0j0j080b0j0C0j0j0j0b0j0j0C080b0j0j0j0j0j0j0b080j0b0C080j0j0b0j0j0j0j0j0j0b0r0b080j0j0b080b080b0j0j0j0j0j0j0b080j0j0j0j0b0j0j0j0r0b0j0b080j0j0j0j0j0b080b080b0C0r0b0j0j0j0j0j0j0b080b080j0C0b0j080b080b0j0j0j0j0j0j',
'0a0j0j0j0j0C0j0j0C0j0C0C0j0j0j0j0j0j0j0m0C0j0j0j0j0u080j0j0j1n0j0j0j0j0C0j0j0j0V0j0j0j1c0u0j0C0V0j0j0V0j0j1v0N0C0V2o1v1O2S2o141v0j1v4l0j1c0j1v2S2o0C0u1v0j0C0C2S1v0j1c0j0j1v0N251c0j1v0b1c1v1n1v0j0j0V0j0j1v0N1v0C0V0j0j1v0b0C0j0j0V1c0j0u0j1c0j0j0j0j0j0j0j0j1c0j0u0j0j0V0j0j0j0j0j0j0b080u110u0j0j0j0j0j0j1c0j0b0j080b0j0C0j0j0j0V0j0j0u0C0V0j0j0j0C0j0b080j1c0j0b0j0j0j0C0j0C0j0j0j0b080b080b0j0C0j080b0j0j0j0j0j0j0j0b0C0r0u0j0j0j0j0j0j0b080j0b0r0C0j0b0j0j0j0r0b0j0b0r0j0j0j0b080b080b0j0r0b0j080b0j0j0j0j0j0j0b0j0r0C0b0j0j0j0j0j0j0b080j0j0C0j0j0b080b0j0j0j0j0j0j0j0j0j0j0b080b080b080b0C0j0j080b0j0j0j0j0j0j0b0j0j0C080b0j0j0j0j0j0j0j0j0b0C080j0j0b0j0j0j0j0j',
'0n0Q0j1c14010q0V1c171k0u0r140V0j0j1c0C0N1O0j0V0j0j0j1c0j0u110u0C0j0C0V0C0j0j0b671v0j1v5Q1O2S2o2S1v4l1v0j1v2S2o0C1Z0j0C0C1O141v0j1c0j2z1O0j0V0j0j1v0b2H390j1c0j0V0C2z0j1c0j1v2g0C0V0j1O0b0j0j0V0C1c0j0u0j1c0j0j0j0j0j0j0j0j1c0N0j0j0V0j0j0C0j0j0b081v0u0j0j0j0C0j1c0N0j0j0C0j0j0j0C0j0j0j0u0C0r0u0j0j0j0C0j0b080j1c0j0b0j0C0C0j0C0C0j0b080b080u0C0j080b0j0C0j0j0j0u110u0j0j0j0j0j0j0j0j0C0C0j0b0j0j0j0C0j0C0C0j0b080b080b0j0C0j080b0j0C0j0j0j0b0j110b0j0j0j0j0j',
'0B0j0V0j0j0C0j0j0j0C0j0C0j0j0C0j0m0j0j0j0j0C0j0C0j0j0u0j1c0j0j0C0C0j0j0j0j0j0j0j0j0u110N0j0j0V0C0V0j0b081n080b0CrU1O5e2SbX2_1Z0V2o141v0j0C0C0j2z1v0j1c0j7N1O420j1c0j1v2S1c0j1v2S2_0b0j0V0j0j1v0N1v0j0j1c0j1v140j0V0j0j0C0C0b080u1v0C0V0u110u0j0j0j0C0j0j0j0C0C0N0C0V0j0j0C0j0j0b080u110u0C0j0C0u0r0C0u080b0j0j0C0j0j0j'
]
for m in months:
n: int = 0
size: int = int(m.__len__() / 2)
l: List[int] = []
for y in range(0, size):
z: int = y * 2
t: int = 0
c: int = 1
for x in range(1, -1, -1):
t += c * chars.index(m[z + x])
c *= 64
n += t
l.append(n)
LunarYear._LEAP.append(l)
LunarYear._IS_INIT = True
@staticmethod
def validate(year: int) -> None:
if year < -1 or year > 9999:
raise ValueError(f'illegal lunar year: {year}')
def __init__(self, year: int):
LunarYear._init()
LunarYear.validate(year)
super().__init__(year)
@classmethod
def from_year(cls, year: int) -> LunarYear:
return cls(year)
def get_day_count(self) -> int:
"""
当年的总天数
:return: 数字,从正月初一到除夕的总天数
"""
n: int = 0
months: List[LunarMonth] = self.get_months()
for i in range(0, months.__len__()):
n += months[i].get_day_count()
return n
def get_month_count(self) -> int:
"""
当年的总月数
:return: 数字,有闰月为13,无闰月为12
"""
return 12 if self.get_leap_month() < 1 else 13
def get_name(self) -> str:
"""
:return: 农历{六十甲子}年
"""
return f'农历{self.get_sixty_cycle().get_name()}年'
def next(self, n: int) -> LunarYear:
return LunarYear(self._year + n)
def get_leap_month(self) -> int:
"""
当年的闰月月份
:return: 数字,代表当年的闰月月份,例如:5代表闰五月,0代表当年没有闰月
"""
if self._year == -1:
return 11
for i in range(0, self._LEAP.__len__()):
if self._year in self._LEAP[i]:
return i + 1
return 0
def get_sixty_cycle(self) -> SixtyCycle:
"""
当年的干支
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle(self._year - 4)
def get_twenty(self) -> Twenty:
"""
:return: 运 Twenty
"""
return Twenty(floor((self._year - 1864) / 20))
def get_nine_star(self) -> NineStar:
"""
:return: 九星 NineStar
"""
return NineStar(63 + self.get_twenty().get_sixty().get_index() * 3 - self.get_sixty_cycle().get_index())
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
return Direction([0, 7, 7, 2, 3, 3, 8, 1, 1, 6, 0, 0][self.get_sixty_cycle().get_earth_branch().get_index()])
def get_first_month(self) -> LunarMonth:
"""
首月(农历月,即一月,俗称正月)
:return: 农历月
"""
return LunarMonth.from_ym(self._year, 1)
def get_months(self) -> List[LunarMonth]:
"""
农历月列表
:return: 农历月 LunarMonth 的列表,从正月到十二月,包含闰月
"""
l: List[LunarMonth] = []
leap_month: int = self.get_leap_month()
for i in range(1, 13):
l.append(LunarMonth.from_ym(self._year, i))
if i == leap_month:
l.append(LunarMonth.from_ym(self._year, -i))
return l
def get_kitchen_god_steed(self) -> KitchenGodSteed:
"""
灶马头
:return: 灶马头
"""
return KitchenGodSteed.from_lunar_year(self._year)
class LunarSeason(LoopTyme):
"""
农历季节
从正月开始,依次为:孟春、仲春、季春、孟夏、仲夏、季夏、孟秋、仲秋、季秋、孟冬、仲冬、季冬。
"""
NAMES: List[str] = ['孟春', '仲春', '季春', '孟夏', '仲夏', '季夏', '孟秋', '仲秋', '季秋', '孟冬', '仲冬', '季冬']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> LunarSeason:
return cls(name)
@classmethod
def from_index(cls, index: int) -> LunarSeason:
return cls(index)
def next(self, n: int) -> LunarSeason:
return LunarSeason(self.next_index(n))
class LunarMonth(MonthUnit):
"""
农历月
农历月以初一开始,大月30天,小月29天
"""
NAMES: List[str] = ['正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
@staticmethod
def validate(year: int, month: int) -> None:
if month == 0 or month > 12 or month < -12:
raise ValueError(f'illegal lunar month: {month}')
if month < 0 and -month != LunarYear.from_year(year).get_leap_month():
raise ValueError(f'illegal leap month {-month} in lunar year {year}')
def __init__(self, year: int, month: int):
"""
:param year: 农历年
:param month: 农历月,闰月为负
"""
LunarMonth.validate(year, month)
super().__init__(year, abs(month))
self._leap = month < 0
@classmethod
def from_ym(cls, year: int, month: int) -> LunarMonth:
"""
从农历年、月初始化
:param year: 农历年,支持从-1到9999年
:param month: 农历月,支持1到12,如果为闰月的,使用负数,即-3代表闰三月
:return: LunarMonth
"""
return cls(year, month)
def _get_new_moon(self):
from tyme4py.solar import SolarTerm
# 冬至
dong_zhi_jd: float = SolarTerm(self._year, 0).get_cursory_julian_day()
# 冬至前的初一,今年首朔的日月黄经差
w: int = ShouXingUtil.calc_shuo(dong_zhi_jd)
if w > dong_zhi_jd:
w -= 29.53
# 正常情况正月初一为第3个朔日,但有些特殊的
offset: int = 2
if 8 < self._year < 24:
offset = 1
elif LunarYear(self._year - 1).get_leap_month() > 10 and self._year != 239 and self._year != 240:
offset = 3
# 本月初一
return w + 29.5306 * (offset + self.get_index_in_year())
def get_lunar_year(self) -> LunarYear:
"""
农历年
:return: 农历年
"""
return LunarYear.from_year(self._year)
def get_month_with_leap(self) -> int:
"""
月(支持闰月)
:return: 月份数字,范围为1到12,闰月为负数,如闰7月返回-7
"""
return -self._month if self._leap else self._month
def get_day_count(self) -> int:
"""
当月的总天数
:return: 数字,从初一开始的总天数,大月有30天,小月有29天
"""
w: float = self._get_new_moon()
return ~~(ShouXingUtil.calc_shuo(w + 29.5306) - ShouXingUtil.calc_shuo(w))
def get_index_in_year(self) -> int:
"""
位于当年的月索引
:return: 数字,范围0到12,正月为0,依次类推,例如五月索引值为4,闰五月索引值为5
"""
# 位于当年的索引
index: int = self._month - 1
if self._leap:
index += 1
else:
leap_month: int = LunarYear.from_year(self._year).get_leap_month()
if 0 < leap_month < self._month:
index += 1
return index
def get_season(self) -> LunarSeason:
"""
:return: 农历季节
"""
return LunarSeason(self._month - 1)
def get_first_julian_day(self) -> JulianDay:
"""
初一的儒略日
:return: 儒略日
"""
from tyme4py.jd import JulianDay
return JulianDay.from_julian_day(JulianDay.J2000 + ShouXingUtil.calc_shuo(self._get_new_moon()))
def is_leap(self) -> bool:
"""
是否闰月
:return: 布尔值,闰月返回true,非闰月返回false
"""
return self._leap
def get_week_count(self, start: int) -> int:
"""
当月有几周
:param start: 参数为起始星期,1234560分别代表星期一至星期天
:return: 数字
"""
return ceil((self.index_of(self.get_first_julian_day().get_week().get_index() - start, 7) + self.get_day_count()) / 7)
def get_name(self) -> str:
"""
依据国家标准《农历的编算和颁行》GB/T 33661-2017中农历月的命名方法。
:return: 名称
"""
return ('闰' if self._leap else '') + self.NAMES[self._month - 1]
def __str__(self) -> str:
return f'{self.get_lunar_year()}{self.get_name()}'
def next(self, n: int) -> LunarMonth:
if n == 0:
return LunarMonth.from_ym(self._year, self.get_month_with_leap())
m: int = self.get_index_in_year() + 1 + n
y: LunarYear = self.get_lunar_year()
if n > 0:
month_count: int = y.get_month_count()
while m > month_count:
m -= month_count
y = y.next(1)
month_count = y.get_month_count()
else:
while m <= 0:
y = y.next(-1)
m += y.get_month_count()
leap: bool = False
leap_month: int = y.get_leap_month()
if leap_month > 0:
if m == leap_month + 1:
leap = True
if m > leap_month:
m -= 1
return LunarMonth.from_ym(y.get_year(), -m if leap else m)
def get_days(self) -> List[LunarDay]:
"""
本月的农历日列表
:return: 农历日 LunarDay 的列表,从初一开始
"""
m: int = self.get_month_with_leap()
l: List[LunarDay] = []
for i in range(1, self.get_day_count() + 1):
l.append(LunarDay(self._year, m, i))
return l
def get_first_day(self) -> LunarDay:
"""
初一
"""
return LunarDay.from_ymd(self._year, self.get_month_with_leap(), 1)
def get_weeks(self, start: int) -> List[LunarWeek]:
"""
本月的农历周列表
:param start: 参数为起始星期,1234560分别代表星期一至星期天
:return: 农历周 LunarWeek 的列表
"""
m: int = self.get_month_with_leap()
l: List[LunarWeek] = []
for i in range(0, self.get_week_count(start)):
l.append(LunarWeek(self._year, m, i, start))
return l
def get_sixty_cycle(self) -> SixtyCycle:
"""
当月的干支
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle.from_index(self._year * 12 + self._month - 47)
def get_nine_star(self) -> NineStar:
"""
:return: 九星 NineStar
"""
index = self.get_sixty_cycle().get_earth_branch().get_index()
if index < 2:
index += 3
return NineStar(27 - self.get_lunar_year().get_sixty_cycle().get_earth_branch().get_index() % 3 * 3 - index)
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
from tyme4py.sixtycycle import SixtyCycle
sixty_cycle: SixtyCycle = self.get_sixty_cycle()
n: int = [7, -1, 1, 3][sixty_cycle.get_earth_branch().next(-2).get_index() % 4]
return Direction(n) if n != -1 else sixty_cycle.get_heaven_stem().get_direction()
def get_fetus(self) -> Union[FetusMonth, None]:
"""
:return: 逐月胎神 FetusMonth。闰月无胎神。
"""
return FetusMonth.from_lunar_month(self)
def get_minor_ren(self) -> MinorRen:
"""
:return: 小六壬
"""
return MinorRen((self._month - 1) % 6)
class LunarWeek(WeekUnit):
"""
农历周
农历一个月最多有6个周,分别为:第一周、第二周、第三周、第四周、第五周、第六周。
"""
@staticmethod
def validate(year: int, month: int, index: int, start: int) -> None:
WeekUnit.validate(year, month, index, start)
m: LunarMonth = LunarMonth.from_ym(year, month)
if index >= m.get_week_count(start):
raise ValueError(f'illegal lunar week index: {index} in month: {m}')
def __init__(self, year: int, month: int, index: int, start: int):
"""
:param year: 年
:param month: 月
:param index: 周索引,0-5
:param start: 起始星期 (1234560分别代表星期一至星期日)
"""
LunarWeek.validate(year, month, index, start)
super().__init__(year, month, index, start)
@classmethod
def from_ym(cls, year: int, month: int, index: int, start: int) -> LunarWeek:
return cls(year, month, index, start)
def get_lunar_month(self) -> LunarMonth:
"""
:return:农历月
"""
return LunarMonth.from_ym(self._year, self._month)
def get_name(self) -> str:
return self.NAMES[self._index]
def __str__(self) -> str:
return f'{self.get_lunar_month()}{self.get_name()}'
def next(self, n: int) -> LunarWeek:
d: int = self._index + n
m: LunarMonth = self.get_lunar_month()
if n > 0:
week_count: int = m.get_week_count(self._start)
while d >= week_count:
d -= week_count
m = m.next(1)
if m.get_first_day().get_week().get_index() != self._start:
d += 1
week_count = m.get_week_count(self._start)
else:
while d < 0:
if m.get_first_day().get_week().get_index() != self._start:
d -= 1
m = m.next(-1)
d += m.get_week_count(self._start)
return LunarWeek(m.get_year(), m.get_month_with_leap(), d, self._start)
def get_first_day(self) -> LunarDay:
"""
本周第一天的农历日
:return: 农历日 LunarDay
"""
first_day: LunarDay = LunarDay(self._year, self._month, 1)
return first_day.next(self._index * 7 - self.index_of(first_day.get_week().get_index() - self._start, 7))
def get_days(self) -> List[LunarDay]:
"""
本周农历日列表
:return: 农历日 LunarDay的列表
"""
l: List[LunarDay] = []
d: LunarDay = self.get_first_day()
l.append(d)
for i in range(1, 7):
l.append(d.next(i))
return l
def __eq__(self, other: LunarWeek) -> bool:
return other and other.get_first_day() == self.get_first_day()
class LunarDay(DayUnit):
"""农历日"""
NAMES: List[str] = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']
"""名称"""
@staticmethod
def validate(year: int, month: int, day: int) -> None:
if day < 1:
raise ValueError(f'illegal lunar day {day}')
m: LunarMonth = LunarMonth.from_ym(year, month)
if day > m.get_day_count():
raise ValueError(f'illegal day {day} in {m}')
def __init__(self, year: int, month: int, day: int):
"""
:param year: 农历年
:param month: 农历月,闰月为负
:param day: 农历日
"""
LunarDay.validate(year, month, day)
super().__init__(year, month, day)
@classmethod
def from_ymd(cls, year: int, month: int, day: int) -> LunarDay:
return cls(year, month, day)
def get_lunar_month(self) -> LunarMonth:
"""
:return: 农历月
"""
return LunarMonth.from_ym(self._year, self._month)
def get_name(self) -> str:
"""
:return: 农历日名,如:初一
"""
return self.NAMES[self._day - 1]
def __str__(self) -> str:
return f'{self.get_lunar_month()}{self.get_name()}'
def next(self, n: int) -> LunarDay:
return self.get_solar_day().next(n).get_lunar_day()
def is_before(self, target: LunarDay) -> bool:
"""
是否在指定农历日之前
:param target: 农历日 LunarDay
:return: true/false
"""
y: int = target.get_year()
if self._year != y:
return self._year < y
m: int = target.get_month()
if self._month != m:
t: int = abs(m)
return self._month == t or abs(self._month) < t
return self._day < target.get_day()
def is_after(self, target: LunarDay) -> bool:
"""
是否在指定农历日之后
:param target: 农历日 LunarDay
:return:
"""
y: int = target.get_year()
if self._year != y:
return self._year > y
m: int = target.get_month()
if self._month != m:
t: int = abs(self._month)
return t == m or t > abs(m)
return self._day > target.get_day()
def get_week(self) -> Week:
"""
:return: 星期
"""
return self.get_solar_day().get_week()
def get_year_sixty_cycle(self) -> SixtyCycle:
"""
当天的年干支 非当天所属的农历年干支,以立春换年。
:return: 干支 SixtyCycle
"""
warnings.warn('get_year_sixty_cycle() is deprecated, please use SixtyCycleDay.get_year() instead.', DeprecationWarning)
return self.get_sixty_cycle_day().get_year()
def get_month_sixty_cycle(self) -> SixtyCycle:
"""
当天的月干支 非当天所属的农历月干支,以节令换月。
:return: 干支 SixtyCycle
"""
warnings.warn('get_month_sixty_cycle() is deprecated, please use SixtyCycleDay.get_month() instead.', DeprecationWarning)
return self.get_sixty_cycle_day().get_month()
def get_sixty_cycle(self) -> SixtyCycle:
"""
当天的干支
:return: 干支
"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle.from_index(int(self.get_lunar_month().get_first_julian_day().next(self._day - 12).get_day()))
def get_duty(self) -> Duty:
"""
建除十二值神
:return: 建除十二值神 Duty
"""
return self.get_sixty_cycle_day().get_duty()
def get_twelve_star(self) -> TwelveStar:
"""
黄道黑道十二神
:return: 黄道黑道十二神 TwelveStar
"""
return self.get_sixty_cycle_day().get_twelve_star()
def get_nine_star(self) -> NineStar:
"""
:return: 九星 NineStar
"""
return self.get_solar_day().get_nine_star()
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
index: int = self.get_sixty_cycle().get_index()
from tyme4py.culture import Element
return Element(index // 12).get_direction() if index % 12 < 6 else self.get_lunar_month().get_lunar_year().get_jupiter_direction()
def get_fetus_day(self) -> FetusDay:
"""
:return:逐日胎神 FetusDay
"""
return FetusDay.from_lunar_day(self)
def get_phase_day(self) -> PhaseDay:
"""
月相第几天
:return: 月相第几天
"""
today = self.get_solar_day()
m = self.get_lunar_month().next(1)
p = Phase.from_index(m.get_year(), m.get_month_with_leap(), 0)
d = p.get_solar_day()
while d.is_after(today):
p = p.next(-1)
d = p.get_solar_day()
return PhaseDay(p, today.subtract(d))
def get_phase(self) -> Phase:
"""
月相
:return: 月相 Phase
"""
return self.get_phase_day().get_phase()
def get_solar_day(self) -> SolarDay:
"""
公历日
:return: 公历日 SolarDay
"""
return self.get_lunar_month().get_first_julian_day().next(self._day - 1).get_solar_day()
def get_sixty_cycle_day(self) -> SixtyCycleDay:
"""
干支日
:return: 干支日
"""
return self.get_solar_day().get_sixty_cycle_day()
def get_twenty_eight_star(self) -> TwentyEightStar:
"""
:return: 二十八宿 TwentyEightStar
"""
return TwentyEightStar(10 + 8 * self.get_week().get_index()).next(-7 * self.get_sixty_cycle().get_earth_branch().get_index())
def get_festival(self) -> Union[LunarFestival, None]:
"""
农历传统节日,如果当天不是农历传统节日,返回None
:return:农历传统节日 LunarFestival
"""
return LunarFestival.from_ymd(self._year, self._month, self._day)
def get_six_star(self) -> SixStar:
"""
:return: 六曜
"""
return SixStar((abs(self._month) + self._day - 2) % 6)
def get_gods(self) -> List[God]:
"""
神煞列表(吉神宜趋,凶神宜忌)
:return: 神煞列表
"""
return self.get_sixty_cycle_day().get_gods()
def get_recommends(self) -> List[Taboo]:
"""
今日 宜
:return: 宜忌列表
"""
return self.get_sixty_cycle_day().get_recommends()
def get_avoids(self) -> List[Taboo]:
"""
今日 忌
:return: 宜忌列表
"""
return self.get_sixty_cycle_day().get_avoids()
def get_hours(self) -> List[LunarHour]:
"""
当天的时辰列表
:return: 由于23:00-23:59、00:00-00:59均为子时,而农历日是从00:00-23:59为一天,所以获取当天的时辰列表,实际会返回13个。
"""
l: List[LunarHour] = [LunarHour(self._year, self._month, self._day, 0, 0, 0)]
for i in range(0, 24, 2):
l.append(LunarHour(self._year, self._month, self._day, i + 1, 0, 0))
return l
def get_minor_ren(self) -> MinorRen:
"""
小六壬
:return: 小六壬
"""
return self.get_lunar_month().get_minor_ren().next(self._day - 1)
def get_three_pillars(self) -> ThreePillars:
"""
三柱
@return: 三柱
"""
return self.get_sixty_cycle_day().get_three_pillars()
class LunarHour(SecondUnit):
"""
农历时辰
"""
provider: EightCharProvider = DefaultEightCharProvider()
"""八字计算接口"""
@staticmethod
def validate(year: int, month: int, day: int, hour: int, minute: int, second: int) -> None:
SecondUnit.validate(year, month, day, hour, minute, second)
LunarDay.validate(year, month, day)
def __init__(self, year: int, month: int, day: int, hour: int, minute: int = 0, second: int = 0):
"""
:param year: 农历年,支持从-1到9999年
:param month: 农历月,支持1到12,如果为闰月的,使用负数,即-3代表闰三月
:param day: 农历日,支持1到30,大月30天,小月29天
:param hour: 时为0-23
:param minute: 分为0-59
:param second: 秒为0-59
"""
LunarHour.validate(year, month, day, hour, minute, second)
super().__init__(year, month, day, hour, minute, second)
@classmethod
def from_ymd_hms(cls, year: int, month: int, day: int, hour: int, minute: int = 0, second: int = 0) -> LunarHour:
return cls(year, month, day, hour, minute, second)
def get_lunar_day(self) -> LunarDay:
"""
:return: 农历日
"""
return LunarDay.from_ymd(self._year, self._month, self._day)
def get_name(self) -> str:
from tyme4py.sixtycycle import EarthBranch
return f'{EarthBranch(self.get_index_in_day()).get_name()}时'
def __str__(self) -> str:
return f'{self.get_lunar_day()}{self.get_sixty_cycle().get_name()}时'
def get_index_in_day(self) -> int:
"""
位于当天的索引
:return: 数字,范围0到11
"""
return int((self._hour + 1) / 2)
def next(self, n: int) -> LunarHour:
if n == 0:
return LunarHour(self._year, self._month, self._day, self._hour, self._minute, self._second)
h: int = self._hour + n * 2
diff: int = -1 if h < 0 else 1
hour: int = abs(h)
days: int = int(hour / 24) * diff
hour = (hour % 24) * diff
if hour < 0:
hour += 24
days -= 1
d: LunarDay = self.get_lunar_day().next(days)
return LunarHour(d.get_year(), d.get_month(), d.get_day(), hour, self._minute, self._second)
def is_before(self, target: LunarHour) -> bool:
"""
是否在指定农历时辰之前
:param target: 农历时辰
:return: true/false
"""
a_day: LunarDay = self.get_lunar_day()
b_day: LunarDay = target.get_lunar_day()
if a_day != b_day:
return a_day.is_before(b_day)
h = target.get_hour()
if self._hour != h:
return self._hour < h
m = target.get_minute()
return self._minute < m if self._minute != m else self._second < target.get_second()
def is_after(self, target: LunarHour) -> bool:
"""
是否在指定农历时辰之后
:param target: 农历时辰
:return: true/false
"""
a_day: LunarDay = self.get_lunar_day()
b_day: LunarDay = target.get_lunar_day()
if a_day != b_day:
return a_day.is_after(b_day)
h = target.get_hour()
if self._hour != h:
return self._hour > h
m = target.get_minute()
return self._minute > m if self._minute != m else self._second > target.get_second()
def get_year_sixty_cycle(self) -> SixtyCycle:
"""
当时的年干支 非当时所属的农历年干支
:return: 干支 SixtyCycle
"""
warnings.warn('get_year_sixty_cycle() is deprecated, please use SixtyCycleHour.get_year() instead.', DeprecationWarning)
return self.get_sixty_cycle_hour().get_year()
def get_month_sixty_cycle(self) -> SixtyCycle:
"""
当时的月干支 非当天所属的农历月干支,以节令具体时刻换月。
:return: 干支 SixtyCycle
"""
warnings.warn('get_year_sixty_cycle() is deprecated, please use SixtyCycleHour.get_month() instead.', DeprecationWarning)
return self.get_sixty_cycle_hour().get_month()
def get_day_sixty_cycle(self) -> SixtyCycle:
"""
当时的日干支
:return: 干支 SixtyCycle。注意:23:00开始算做第二天。
"""
warnings.warn('get_year_sixty_cycle() is deprecated, please use SixtyCycleHour.get_day() instead.', DeprecationWarning)
return self.get_sixty_cycle_hour().get_day()
def get_sixty_cycle(self) -> SixtyCycle:
"""
时辰干支
:return: 干支 SixtyCycle
"""
from tyme4py.sixtycycle import SixtyCycle, HeavenStem
e: int = self.get_index_in_day()
h: HeavenStem = self.get_lunar_day().get_sixty_cycle().get_heaven_stem()
if self._hour >= 23:
h = h.next(1)
e = 0
return SixtyCycle.from_index(h.get_index() * 12 + e)
def get_twelve_star(self) -> TwelveStar:
"""
:return: 黄道黑道十二神 TwelveStar
"""
return TwelveStar(self.get_sixty_cycle().get_earth_branch().get_index() + (8 - self.get_sixty_cycle_hour().get_day().get_earth_branch().get_index() % 6) * 2)
def get_nine_star(self) -> NineStar:
"""
九星(时家紫白星歌诀:三元时白最为佳,冬至阳生顺莫差,孟日七宫仲一白,季日四绿发萌芽,每把时辰起甲子,本时星耀照光华,时星移入中宫去,顺飞八方逐细查。夏至阴生逆回首,孟归三碧季加六,仲在九宫时起甲,依然掌中逆轮跨。)
:return: 九星 NineStar
"""
from tyme4py.solar import SolarTerm
d: LunarDay = self.get_lunar_day()
solar: SolarDay = d.get_solar_day()
dong_zhi: SolarTerm = SolarTerm(solar.get_year(), 0)
earth_branch_index: int = self.get_index_in_day() % 12
index: int = 8 - 3 * (d.get_sixty_cycle().get_earth_branch().get_index() % 3)
if (not solar.is_before(dong_zhi.get_julian_day().get_solar_day())) and solar.is_before(dong_zhi.next(12).get_julian_day().get_solar_day()):
index = 8 + earth_branch_index - index
else:
index -= earth_branch_index
return NineStar(index)
def get_solar_time(self) -> SolarTime:
"""
公历时刻
:return: 公历时刻 SolarTime
"""
from tyme4py.solar import SolarTime
d: SolarDay = self.get_lunar_day().get_solar_day()
return SolarTime(d.get_year(), d.get_month(), d.get_day(), self._hour, self._minute, self._second)
def get_sixty_cycle_hour(self) -> SixtyCycleHour:
"""
干支时辰
:return: 干支时辰 SixtyCycleHour
"""
return self.get_solar_time().get_sixty_cycle_hour()
def get_eight_char(self) -> EightChar:
"""
八字
:return: 八字
"""
return LunarHour.provider.get_eight_char(self)
def get_recommends(self) -> List[Taboo]:
"""
宜
:return: 宜忌列表
"""
return Taboo.get_hour_recommends(self.get_sixty_cycle_hour().get_day(), self.get_sixty_cycle())
def get_avoids(self) -> List[Taboo]:
"""
忌
:return: 宜忌列表
"""
return Taboo.get_hour_avoids(self.get_sixty_cycle_hour().get_day(), self.get_sixty_cycle())
def get_minor_ren(self) -> MinorRen:
"""
:return: 小六壬
"""
return self.get_lunar_day().get_minor_ren().next(self.get_index_in_day())
+408
View File
@@ -0,0 +1,408 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import TYPE_CHECKING, Union, List, Dict
from tyme4py import AbstractTyme
from tyme4py.culture import Element, Zodiac
from tyme4py.lunar import LunarMonth
from tyme4py.unit import MonthUnit, DayUnit
if TYPE_CHECKING:
from tyme4py.sixtycycle import SixtyCycle
from tyme4py.solar import SolarYear, SolarDay
class RabByungElement(Element):
"""藏历五行"""
NAMES: List[str] = ['木', '火', '土', '铁', '水']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(index_or_name, self.NAMES)
@classmethod
def from_index(cls, index: int) -> RabByungElement:
return cls(index)
@classmethod
def from_name(cls, name: str) -> RabByungElement:
return cls(name)
def next(self, n: int) -> RabByungElement:
return RabByungElement(self.next_index(n))
def get_reinforce(self) -> RabByungElement:
"""我生者"""
return self.next(1)
def get_restrain(self) -> RabByungElement:
"""我克者"""
return self.next(2)
def get_reinforced(self) -> RabByungElement:
"""生我者"""
return self.next(-1)
def get_restrained(self) -> RabByungElement:
"""克我者"""
return self.next(-2)
class RabByungYear(AbstractTyme):
"""藏历年(公历1027年为藏历元年,第一饶迥火兔年)"""
def __init__(self, rab_byung_index: int, element_index: int, zodiac_index: int):
"""
:param rab_byung_index: 饶迥(胜生周)序号,从0开始
:param element_index: 五行索引,从0开始
:param zodiac_index: 生肖索引,从0开始
"""
if rab_byung_index < 0 or rab_byung_index > 150:
raise ValueError(f'illegal rab-byung index: {rab_byung_index}')
if element_index < 0 or element_index >= len(Element.NAMES):
raise ValueError(f'illegal element index: {element_index}')
if zodiac_index < 0 or zodiac_index > len(Zodiac.NAMES):
raise ValueError(f'illegal zodiac index: {zodiac_index}')
self._rab_byung_index = rab_byung_index
self._element_index = element_index
self._zodiac_index = zodiac_index
@staticmethod
def validate(year: int) -> None:
if year < 1027 or year > 9999:
raise ValueError(f'illegal rab-byung year: {year}')
@classmethod
def from_sixty_cycle(cls, rab_byung_index: int, sixty_cycle: SixtyCycle) -> RabByungYear:
return cls(rab_byung_index, sixty_cycle.get_heaven_stem().get_element().get_index(), sixty_cycle.get_earth_branch().get_zodiac().get_index())
@classmethod
def from_element_zodiac(cls, rab_byung_index: int, element: RabByungElement, zodiac: Zodiac) -> RabByungYear:
return cls(rab_byung_index, element.get_index(), zodiac.get_index())
@classmethod
def from_year(cls, year: int) -> RabByungYear:
from tyme4py.sixtycycle import SixtyCycle
cls.validate(year)
return cls.from_sixty_cycle((year - 1024) // 60, SixtyCycle.from_index(year - 4))
def get_rab_byung_index(self) -> int:
"""饶迥序号(从0开始)"""
return self._rab_byung_index
def get_sixty_cycle(self) -> SixtyCycle:
"""干支"""
from tyme4py.sixtycycle import SixtyCycle
return SixtyCycle.from_index(6 * (self._element_index * 2 + self._zodiac_index % 2) - 5 * self._zodiac_index)
def get_zodiac(self) -> Zodiac:
"""生肖"""
return Zodiac.from_index(self._zodiac_index)
def get_element(self) -> RabByungElement:
"""五行"""
return RabByungElement.from_index(self._element_index)
def get_name(self) -> str:
"""完整名称"""
digits: List[str] = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
units: List[str] = ['', '十', '百']
n: int = self._rab_byung_index + 1
s: str = ''
pos: int = 0
while n > 0:
digit: int = n % 10
if digit > 0:
s = digits[digit] + units[pos] + s
elif s:
s = digits[digit] + s
n //= 10
pos += 1
if s.startswith('一十'):
s = s.replace('一十', '十', 1)
return f'第{s}饶迥{self.get_element()}{self.get_zodiac()}年'
def next(self, n: int) -> RabByungYear:
return RabByungYear.from_year(self.get_year() + n)
def get_year(self) -> int:
"""公历年份"""
return 1024 + self._rab_byung_index * 60 + self.get_sixty_cycle().get_index()
def get_leap_month(self) -> int:
"""闰月(闰月数字,1代表闰1月,0代表无闰月)"""
y: int = 1
m: int = 4
t: int = 1
current_year: int = self.get_year()
while y < current_year:
i: int = m + 31 + t
y += 2
m = i - 23
if i > 35:
y += 1
m -= 12
t = 1 - t
return m if y == current_year else 0
def get_solar_year(self) -> SolarYear:
"""对应的公历年"""
from tyme4py.solar import SolarYear
return SolarYear.from_year(self.get_year())
def get_first_month(self) -> RabByungMonth:
"""首月"""
return RabByungMonth(self.get_year(), 1)
def get_month_count(self) -> int:
"""月份数量"""
return 12 if self.get_leap_month() < 1 else 13
def get_months(self) -> List[RabByungMonth]:
"""所有月份列表"""
months: List[RabByungMonth] = []
y: int = self.get_year()
leap_month: int = self.get_leap_month()
for i in range(1, 13):
months.append(RabByungMonth(y, i))
if i == leap_month:
months.append(RabByungMonth(y, -i))
return months
def __str__(self) -> str:
return self.get_name()
class RabByungMonth(MonthUnit):
"""藏历月,仅支持藏历1950年十二月至藏历2050年十二月"""
ALIAS = ['神变月', '苦行月', '具香月', '萨嘎月', '作净月', '明净月', '具醉月', '具贤月', '天降月', '持众月', '庄严月', '满意月']
DAYS: Dict[int, List[int]] = {}
_IS_INIT: bool = False
# 初始化特殊日数据(1950-2050年)
@staticmethod
def _init():
if RabByungMonth._IS_INIT:
return
years: List[str] = "2c>,182[>1:2TA4ZI=n1E2Bk1J2Ff3Mk503Oc62g=,172^>1:2XA1>2UE2Bo1I2Fj3Lo62Fb3Mf5,03N^72b=1:2]A1>2ZF1B2VI2Em1K2Fe,2Lh1R3Na603P\\:172Y>1;2UB2=m2Dq1J2Eh,2Kl1Q3Me603Pa:172^>1;2YA2=p1C2UI,2Dk2Jp3QEc3Mi603Pf:3L[72b?1:2]A1<2UB2XH,2Cn1I2Ei1L2Ie1Q3Na703Q\\:2`@1;2XA,4\\H;m1B2TI2Em1L2Ij1Q3Nf603Q`903QW:,2[@1;2TB2XI1E4TMAh2Io3RFe3Mj603Pc803Q[;,2^?1;2WA2>q1E2Bm1I2Fi1M2Hc3Of70,3P^82a>1:2[A1>2WE1B2TI2Fm1L2Hf3Ni6,03Oa703PZ:3`A62V>4]F;q1B4YJ>l2Eq1L2Gi3Ml5,03Nd603Q_9172[>1;2XB2>p1E2VK2Fl,1K2Fc3Mh603Pc9172`>1;2\\B1>2UD2=j2En,1J2Fg3Mm62Ib3Pj;3M_703R[:2`B1=2YB2=n,1C2TI2Fk1L2Ig1P3Nd703Q_:152X<2[A,2<q1B2WI2Ep1L2Il1Q3Ni703Qc9152[:2^@,1;2WB2>o1E2Bk1I2Fh1M2Ib3Pf803R^9,2a?1;2ZA1>2UE2Bp1I2Fl1M2If3Oi80,3Pa803QY:2^A1>2ZE1B4WJ>j2Fp1M2Hi1N2H`,3Od703Q]:162Y>1;2VB2?o1E4VM@h2Gl1M,2Hd3Ng603Qa9172^>1;2ZB1?2UE2@l2Fo1L,2Gg3Mk62H`3Pf:172c?3QY;2_B1>2YD2?o1E,2TK2Fj1M2Ie1P3Mb703R^;172X=2\\C1>,2TD2WJ2Fn1L2Ij1P3Ng703Rb:162[<2_B1=,2VC2>m1E4TMAh2Io3QFe3Nl82Ja3Qf:152_;0,3RU<2ZB1>2TE2Bn1I2Fj1M2Je3Pk:2K^3Ra:,03RY;2]A1>2XE1B2TI2Fo1M2Ii1P2Ka3Qd8,03R]:3bB62W>4]F:q1B2?n1F4VNAh2Il1O2Jd,3Pg803Q`:162\\=1;2XB1?2TF2Bl2Ho1N,2Ig3Nk703Qd9162`>1;2]B1?2XE2Ao1G2TM,2Hj1M2Id1P3M_603R\\;172W>2\\E1@2TE,2?i2Gm1M2Ih1P3Md603Ra;172[=28q1?2WD,2?m2Fq1M2Il1P3Mi72I^3Re:162_<172W=,2ZC2?q1E2Bk1I2Fh1M2Jd1Q3M^52b;16,2Y<2]B1>2VE2Bp1I2Fm1M2Jh1Q2Lb3Re:15,2\\;3aC62U>2[E1B4WJ>k1F4TNBg2Jl1P2Le3Qh9,03R`:172Z=1:2VB2?q1F2Bk2Ip1P2Jg,1P2J_3Qc:162^=1;2[B1?2WF2Bo1H2Bg2Ij,1O2Jc3Qg:3L\\62c>3QY;3aC72V?2[F1A2TG2Bj,2Hm1N2Jg1P3Mb603R_;182Z>1:2T@2WF2Am,2Gp1M2Ik1P3Mg603Rc;172^>192W?2ZE,2@p1F2Bj2Io3QEe1M2Jb1Q3M]72b=182Z>,2]D1?2VE2Bn1I2Fk1M2Jg1Q3Ma62e<172]=,172U>2YE1B2UI2Fp1N2Jk1Q3Me503M\\6,2`<172Y>3_F:2TB2?n1F2Cj2Jo3QDc2Lh1R,3L_52c;172]=1:2XB1?2UF2Cn1I2Eg2Kk1P,2Lb3Rf;162a=1:2]B1?2ZF1B2TH2Dj2Jm,1O2Kf1Q3M`603Q\\;182Y?2;q1A2WH2Cm,2Hq1O2Ji1P3Me603Qa;182]>1:2WA2[G2Ap,1G2Bi2Im1P3Mi72I_3Qf;3N\\72Eh1:2Z?29o,1@2UF2Bm1I2Fh1M2Je1Q3N`72f?3PY92]>19,2U?2YF2Bq1I2Fm1M2Jj1Q3Nd603O]72`=,182X?4]F:o1B4WI=k1F4UNCi2Jn3REc3Mh503N`6,2c<182\\>1:2VA2?q1F2Cm1J2Fg2Lk1R3Mc5,2f<172`=1:2[A1?2XF2Cq1I2Ek2Kn1R,2Lf1R3N_62d>3PZ:3aC72W?2;p1B2WI2Dn1J,2De2Ki1Q3Mc603Q_:182\\?1;2VB2<m2Cq1I,2Dh2Jl1P3Mg603Qd;182`?1;2ZA2<p1B,2UH2Cl1I2Ef3Mm82Jc1Q3N_703QY:2]@1;2UA,2XG2Bp1I2Fk1M2Jh1Q3Nc703Q]92`?1:,2X@4\\G:n1B2VI2Fp1M2Jl1R3Ng603P`82d>,192[?1;2UA2>o1F2Ck1J2Gg3Mk603Oc70,3OZ82_>1:2YA1?2VF2Cp1J2Fj1M2Gc3Nf5,03O^72b>1:2^B1?4[G;n1C2VJ2Fn1L2Gf,3Mi503Nb603Q]:172Y?1<2UB2>m2Eq1K2Fi,2Kl1R3Mf603Qa:182^?1;2YB2>q1D2VJ,2Dl1J2Fe3Mj603Qg;3N]72c@3QX;2]A1=2VB,2YI2Co1J2Fi1M2Je1Q3Nb703R]:2aA1<2XA,2<n1C2UI2Fn1M2Jj1Q3Nf703Q`903RX:,2[@1<2TB4YJ>l1E4UNBi1J2Ge3Mk703Pc803Q[9,2^?1;2XB2>q1E2Cn1J2Gj1M2Ic3Of70,3P^82b?1;2\\A1>2XF1C2UJ2Fm1M2Hf3Ni6,03Oa703Q[:3aB72W>1<2TC2?m2Fq1L2Gi3Ml5,03Ne703Q_:172\\>1<2XB2?q1E2WL2Fl,1L2Gd3Ni603Qd:172a?1;2\\B1>2VD2>k,2Eo1K2Gh1M2Ic1Q3N`703R\\;3aC62U=2YC2>o,1D2TJ2Fl1M2Jh1Q3Ne703R`:162Y<2\\B,1=2TC4XJ=j2Fp1M2Jm3QFc3Ni803Qc:152\\;2_A,1<2WB2>o1E2Bl1J2Gh1N2Jc3Qg903R^:,2b@1;2[B1>2VE2Cq1J2Gl1N2Jf3Pj80,3Qa803RZ;2_B1>4[F:o1C4XK?k2Fp1M2Ii1O2Ia,3Pd703R^:172Y>1<2VC2?p1F2Ai2Hl1M,2Hd3Oh703Qb:172^>1<2[C1?2UE2Al2Go,1L2Hg3Nl82Ia3Qg;3M]72e@3RZ;3`C72T>2YD2@o1E,2TK2Gk1M2Jf1Q3Nb703R^;172Y=2\\D1>,2TD4XK>i2Fo1M2Jj1Q3Ng703Rb;172\\<2`C1=,2WC2?n1F4VNBi1J2Gf1N2Kb3Rf:162_;15,2V<2ZB1?2TE2Bn1J2Gk1N2Kf1Q2L^3Rb:,152Z;2^B1>2YE1B2UJ2Go1N2Ji1P2Kb3Qd9,03R];172X>1;2TC2@n1G2Bi2Im1O2Jd,3Ph803Ra:172\\>1;2YC1@2UF2Bl2Hp1N,2Ig3Ol82J`3Qe:172a>1;4^C7q1?2XF2Ao1G2UN,2Hj1N2Jd1Q3N`703R];182X>2]F1@2TF,2@j2Gn1M2Jq1Q3Ne703Ra;172\\>192T?,2WE2@m1F4TMAf2Im3QEc3Nj82J`3Rf;172_=182W>,2ZD2?q1F2Bl1I2Gj1N2Ke1R3M_62b<17,2Z=2]C1?2WE2Bq1I2Gn1N2Ki1Q3Mb52e;16,2]<172V>4[F:o1B4XK?l1G4UOCh2Jl1Q2Le3Rh:,152`;172Z>1;2WB2@q1G2Cl2Ip1P2K_".split(',')
y: int = 1950
m: int = 11
for ys in years:
data: str = ys.strip()
while data:
length: int = ord(data[0]) - 48
chunk: str = data[1:1+length]
data: str = data[1+length:]
days_data: List[int] = [ord(c) - 53 - 30 for c in chunk]
RabByungMonth.DAYS[y * 13 + m] = days_data
m += 1
y += 1
m = 0
RabByungMonth._IS_INIT = True
def __init__(self, year: int, month: int):
RabByungMonth._init()
RabByungMonth.validate(year, month)
super().__init__(year, abs(month))
self._leap = month < 0
@staticmethod
def validate(year: int, month: int) -> None:
if month == 0 or month > 12 or month < -12:
raise ValueError(f'illegal rab-byung month: {month}')
if year < 1950 or year > 2050:
raise ValueError(f'rab-byung year {year} must between 1950 and 2050')
leap: bool = month < 0
m: int = abs(month)
if year == 1950 and m < 12:
raise ValueError(f'month {month} must be 12 in rab-byung year {year}')
if leap and m != RabByungYear.from_year(year).get_leap_month():
raise ValueError(f'illegal leap month {m} in rab-byung year {year}')
@classmethod
def from_ym(cls, year: int, month: int) -> RabByungMonth:
return cls(year, month)
def get_rab_byung_year(self) -> RabByungYear:
return RabByungYear.from_year(self._year)
def get_month_with_leap(self) -> int:
return -self._month if self._leap else self._month
def get_index_in_year(self) -> int:
index: int = self._month - 1
if self._leap:
index += 1
else:
leap_month: int = self.get_rab_byung_year().get_leap_month()
if 0 < leap_month < self._month:
index += 1
return index
def is_leap(self) -> bool:
return self._leap
def get_name(self) -> str:
return ('闰' if self._leap else '') + LunarMonth.NAMES[self._month - 1]
def get_alias(self) -> str:
return ('闰' if self._leap else '') + self.ALIAS[self._month - 1]
def next(self, n: int) -> RabByungMonth:
if n == 0:
return RabByungMonth.from_ym(self.get_year(), self.get_month_with_leap())
m: int = self.get_index_in_year() + 1 + n
y: RabByungYear = self.get_rab_byung_year()
if n > 0:
month_count: int = y.get_month_count()
while m > month_count:
m -= month_count
y = y.next(1)
month_count = y.get_month_count()
else:
while m <= 0:
y = y.next(-1)
m += y.get_month_count()
leap: bool = False
leap_month: int = y.get_leap_month()
if leap_month > 0:
if m == leap_month + 1:
leap = True
if m > leap_month:
m -= 1
return RabByungMonth(y.get_year(), -m if leap else m)
def get_first_day(self) -> RabByungDay:
return RabByungDay(self._year, self.get_month_with_leap(), 1)
def get_days(self) -> List[RabByungDay]:
days: List[RabByungDay] = []
miss_days: List[int] = self.get_miss_days()
leap_days: List[int] = self.get_leap_days()
m: int = self.get_month_with_leap()
for day in range(1, 31):
if day in miss_days:
continue
days.append(RabByungDay(self._year, m, day))
if day in leap_days:
days.append(RabByungDay(self._year, m, -day))
return days
def get_day_count(self) -> int:
return 30 + len(self.get_leap_days()) - len(self.get_miss_days())
def get_special_days(self) -> List[int]:
return self.DAYS.get(self.get_year() * 13 + self.get_index_in_year(), [])
def get_leap_days(self) -> List[int]:
return [d for d in self.get_special_days() if d > 0]
def get_miss_days(self) -> List[int]:
return [-d for d in self.get_special_days() if d < 0]
def __str__(self) -> str:
return f'{self.get_rab_byung_year()}{self.get_name()}'
class RabByungDay(DayUnit):
"""藏历日,仅支持藏历1950年十二月初一(公历1951年1月8日)至藏历2050年十二月三十(公历2051年2月11日)"""
NAMES: List[str] = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']
def __init__(self, year: int, month: int, day: int):
RabByungDay.validate(year, month, day)
super().__init__(year, month, abs(day))
self._leap = day < 0
@staticmethod
def validate(year: int, month: int, day: int) -> None:
if day == 0 or day < -30 or day > 30:
raise ValueError(f'illegal day {day} in {month}')
m: RabByungMonth = RabByungMonth.from_ym(year, month)
leap: bool = day < 0
d = abs(day)
if leap and d not in m.get_leap_days():
raise ValueError(f'illegal leap day {d} in {m}')
if not leap and d in m.get_miss_days():
raise ValueError(f'illegal day {d} in {m}')
@classmethod
def from_ymd(cls, year: int, month: int, day: int) -> RabByungDay:
return cls(year, month, day)
@classmethod
def from_solar_day(cls, solar_day: SolarDay) -> RabByungDay:
from tyme4py.solar import SolarDay
days: int = solar_day.subtract(SolarDay.from_ymd(1951, 1, 8))
m: RabByungMonth = RabByungMonth.from_ym(1950, 12)
count: int = m.get_day_count()
while days >= count:
days -= count
m = m.next(1)
count = m.get_day_count()
day: int = days + 1
for d in m.get_special_days():
if d < 0:
if day >= -d:
day += 1
elif d > 0:
if day == d + 1:
day = -d
break
elif day > d + 1:
day -= 1
return RabByungDay(m.get_year(), m.get_month_with_leap(), day)
def get_rab_byung_month(self) -> RabByungMonth:
return RabByungMonth.from_ym(self._year, self._month)
def is_leap(self) -> bool:
return self._leap
def get_day_with_leap(self) -> int:
return -self._day if self._leap else self._day
def get_name(self) -> str:
return ('闰' if self._leap else '') + self.NAMES[self._day - 1]
def subtract(self, target: RabByungDay) -> int:
return self.get_solar_day().subtract(target.get_solar_day())
def get_solar_day(self) -> SolarDay:
from tyme4py.solar import SolarDay
month: RabByungMonth = RabByungMonth.from_ym(1950, 12)
cm: RabByungMonth = self.get_rab_byung_month()
total_days: int = 0
# 计算从1950年12月到当前月的总天数
while month != cm:
total_days += month.get_day_count()
month = month.next(1)
day_num: int = self._day
for d in month.get_special_days():
if d < 0:
if day_num > -d:
day_num -= 1
elif d > 0:
if day_num > d:
day_num += 1
if self._leap:
day_num += 1
return SolarDay.from_ymd(1951, 1, 7).next(total_days + day_num)
def next(self, n: int) -> RabByungDay:
return self.get_solar_day().next(n).get_rab_byung_day()
def __str__(self) -> str:
return f'{self.get_rab_byung_month()}{self.get_name()}'
+919
View File
@@ -0,0 +1,919 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from math import floor, ceil
from typing import TYPE_CHECKING, Union, List
from tyme4py import LoopTyme, AbstractCulture, AbstractCultureDay, AbstractTyme
from tyme4py.culture import Element, Direction, Zodiac, Terrain, Sound, Ten, Twenty, Duty, God, Taboo
from tyme4py.culture.fetus import FetusDay
from tyme4py.culture.pengzu import PengZuEarthBranch, PengZuHeavenStem, PengZu
from tyme4py.culture.star.nine import NineStar
from tyme4py.culture.star.ten import TenStar
from tyme4py.culture.star.twelve import TwelveStar
from tyme4py.eightchar import EightChar
from tyme4py.enums import YinYang, HideHeavenStemType
if TYPE_CHECKING:
from tyme4py.solar import SolarDay, SolarTime
from tyme4py.culture.star.twentyeight import TwentyEightStar
class ThreePillars(AbstractCulture):
"""三柱"""
def __init__(self, year: Union[SixtyCycle, str], month: Union[SixtyCycle, str], day: Union[SixtyCycle, str]):
"""
:param year: 年干支
:param month: 月干支
:param day: 日干支
"""
self._year = year if isinstance(year, SixtyCycle) else SixtyCycle(year)
self._month = month if isinstance(month, SixtyCycle) else SixtyCycle(month)
self._day = day if isinstance(day, SixtyCycle) else SixtyCycle(day)
def get_year(self) -> SixtyCycle:
"""
年柱
:return: 干支 SixtyCycle
"""
return self._year
def get_month(self) -> SixtyCycle:
"""
月柱
:return: 干支 SixtyCycle
"""
return self._month
def get_day(self) -> SixtyCycle:
"""
日柱
:return: 干支 SixtyCycle
"""
return self._day
def get_name(self) -> str:
return f'{self._year} {self._month} {self._day}'
def get_solar_days(self, start_year: int, end_year: int) -> List[SolarDay]:
"""
三柱转公历日列表
:param start_year: 开始年份,支持1-9999年
:param end_year: 结束年份,支持1-9999年
:return: 公历日 SolarDay的列表
"""
from tyme4py.solar import SolarDay, SolarTerm
l: List[SolarDay] = []
# 月地支距寅月的偏移值
m: int = self._month.get_earth_branch().next(-2).get_index()
# 月天干要一致
if not HeavenStem((self._year.get_heaven_stem().get_index() + 1) * 2 + m) == self._month.get_heaven_stem():
return l
# 1年的立春是辛酉,序号57
y: int = self._year.next(-57).get_index() + 1
# 节令偏移值
m *= 2
base_year: int = start_year - 1
if base_year > y:
y += 60 * int(ceil((base_year - y) / 60.0))
while y <= end_year:
# 立春为寅月的开始
term: SolarTerm = SolarTerm(y, 3)
# 节令推移,年干支和月干支就都匹配上了
if m > 0:
term = term.next(m)
solar_day: SolarDay = term.get_solar_day()
if solar_day.get_year() >= start_year:
# 日干支和节令干支的偏移值
d: int = self._day.next(-solar_day.get_lunar_day().get_sixty_cycle().get_index()).get_index()
if d > 0:
# 从节令推移天数
solar_day = solar_day.next(d)
# 验证一下
if solar_day.get_sixty_cycle_day().get_three_pillars() == self:
l.append(solar_day)
y += 60
return l
class EarthBranch(LoopTyme):
"""地支(地元)"""
NAMES: List[str] = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> EarthBranch:
return cls(name)
@classmethod
def from_index(cls, index: int) -> EarthBranch:
return cls(index)
def next(self, n: int) -> EarthBranch:
return EarthBranch(self.next_index(n))
def get_element(self) -> Element:
"""
:return:五行
"""
return Element([4, 2, 0, 0, 2, 1, 1, 2, 3, 3, 2, 4][self.get_index()])
def get_yin_yang(self) -> YinYang:
"""
:return:阴阳
"""
return YinYang.YANG if self.get_index() % 2 == 0 else YinYang.YIN
def get_hide_heaven_stem_main(self) -> HeavenStem:
"""
藏干之本气(主气)
:return: 天干 HeavenStem
"""
return HeavenStem([9, 5, 0, 1, 4, 2, 3, 5, 6, 7, 4, 8][self.get_index()])
def get_hide_heaven_stem_middle(self) -> Union[HeavenStem, None]:
"""
藏干之中气,无中气的返回None
:return: 天干 HeavenStem
"""
n: int = [-1, 9, 2, -1, 1, 6, 5, 3, 8, -1, 7, 0][self.get_index()]
return None if n == -1 else HeavenStem(n)
def get_hide_heaven_stem_residual(self) -> Union[HeavenStem, None]:
"""
藏干之余气,无余气的返回None
:return: 天干 HeavenStem
"""
n: int = [-1, 7, 4, -1, 9, 4, -1, 1, 4, -1, 3, -1][self.get_index()]
return None if n == -1 else HeavenStem(n)
def get_hide_heaven_stems(self) -> List[HideHeavenStem]:
"""
:return: 藏干列表
"""
l: List[HideHeavenStem] = [HideHeavenStem(self.get_hide_heaven_stem_main(), HideHeavenStemType.MAIN)]
o: Union[HeavenStem, None] = self.get_hide_heaven_stem_middle()
if o:
l.append(HideHeavenStem(o, HideHeavenStemType.MIDDLE))
o = self.get_hide_heaven_stem_residual()
if o:
l.append(HideHeavenStem(o, HideHeavenStemType.RESIDUAL))
return l
def get_zodiac(self) -> Zodiac:
"""
生肖属相
:return:生肖 Zodiac
"""
return Zodiac(self.get_index())
def get_direction(self) -> Direction:
"""
:return: 方位 Direction
"""
return Direction([0, 4, 2, 2, 4, 8, 8, 4, 6, 6, 4, 0][self.get_index()])
def get_opposite(self) -> EarthBranch:
"""
六冲
子午冲,丑未冲,寅申冲,辰戌冲,卯酉冲,巳亥冲。
:return: 地支 EarthBranch
"""
return self.next(6)
def get_ominous(self) -> Direction:
"""
煞
逢巳日、酉日、丑日必煞东;
亥日、卯日、未日必煞西;
申日、子日、辰日必煞南;
寅日、午日、戌日必煞北。
:return: 方位 Direction
"""
return Direction([8, 2, 0, 6][self.get_index() % 4])
def get_peng_zu_earth_branch(self) -> PengZuEarthBranch:
"""
:return: 地支彭祖百忌 PengZuEarthBranch
"""
return PengZuEarthBranch(self.get_index())
def get_combine(self) -> EarthBranch:
"""
六合(子丑合,寅亥合,卯戌合,辰酉合,巳申合,午未合)
:return: 地支 EarthBranch
"""
return EarthBranch(1 - self.get_index())
def get_harm(self) -> EarthBranch:
"""
六害(子未害、丑午害、寅巳害、卯辰害、申亥害、酉戌害)
:return: 地支 EarthBranch
"""
return EarthBranch(19 - self.get_index())
def combine(self, target: EarthBranch) -> Union[Element, None]:
"""
合化
子丑合化土,寅亥合化木,卯戌合化火,辰酉合化金,巳申合化水,午未合化火
:param target: 地支 EarthBranch
:return: 能合化则返回五行属性,不能合化则返回None
"""
return Element([2, 2, 0, 1, 3, 4, 2, 2, 4, 3, 1, 0][self.get_index()]) if self.get_combine() == target else None
class HeavenStem(LoopTyme):
"""天干(天元)"""
NAMES: List[str] = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> HeavenStem:
return cls(name)
@classmethod
def from_index(cls, index: int) -> HeavenStem:
return cls(index)
def next(self, n: int) -> HeavenStem:
return HeavenStem(self.next_index(n))
def get_element(self) -> Element:
"""
五行
:return: 五行
"""
return Element(self.get_index() // 2)
def get_yin_yang(self) -> YinYang:
"""
:return: 阴阳
"""
return YinYang.YANG if self.get_index() % 2 == 0 else YinYang.YIN
def get_ten_star(self, target: HeavenStem) -> TenStar:
"""
十神(生我者,正印偏印。我生者,伤官食神。克我者,正官七杀。我克者,正财偏财。同我者,劫财比肩。)
:param target: 天干
:return:十神
"""
target_index: int = target.get_index()
offset: int = target_index - self.get_index()
if self.get_index() % 2 != 0 and target_index % 2 == 0:
offset += 2
return TenStar(offset)
def get_direction(self) -> Direction:
"""
:return: 方位
"""
return self.get_element().get_direction()
def get_joy_direction(self) -> Direction:
"""
喜神方位(《喜神方位歌》甲己在艮乙庚乾,丙辛坤位喜神安。丁壬只在离宫坐,戊癸原在在巽间。)
:return: 方位
"""
return Direction([7, 5, 1, 8, 3][self.get_index() % 5])
def get_yang_direction(self) -> Direction:
"""
阳贵神方位(《阳贵神歌》甲戊坤艮位,乙己是坤坎,庚辛居离艮,丙丁兑与乾,震巽属何日,壬癸贵神安。)
:return: 方位
"""
return Direction([1, 1, 6, 5, 7, 0, 8, 7, 2, 3][self.get_index()])
def get_yin_direction(self) -> Direction:
"""
阴贵神方位(《阴贵神歌》甲戊见牛羊,乙己鼠猴乡,丙丁猪鸡位,壬癸蛇兔藏,庚辛逢虎马,此是贵神方。)
:return: 方位
"""
return Direction([7, 0, 5, 6, 1, 1, 7, 8, 3, 2][self.get_index()])
def get_wealth_direction(self) -> Direction:
"""
财神方位(《财神方位歌》甲乙东北是财神,丙丁向在西南寻,戊己正北坐方位,庚辛正东去安身,壬癸原来正南坐,便是财神方位真。)
:return:方位
"""
return Direction([7, 1, 0, 2, 8][self.get_index() // 2])
def get_mascot_direction(self) -> Direction:
"""
福神方位(《福神方位歌》甲乙东南是福神,丙丁正东是堪宜,戊北己南庚辛坤,壬在乾方癸在西。)
:return:方位
"""
return Direction([3, 3, 2, 2, 0, 8, 1, 1, 5, 6][self.get_index()])
def get_peng_zu_heaven_stem(self) -> PengZuHeavenStem:
"""
:return:天干彭祖百忌
"""
return PengZuHeavenStem(self.get_index())
def get_terrain(self, earth_branch: EarthBranch) -> Terrain:
"""
长生十二神(地势)
长生十二神可通过不同的组合,得到自坐和星运
:param: 地支
:return:地势(长生十二神)
"""
earth_branch_index: int = earth_branch.get_index()
return Terrain([1, 6, 10, 9, 10, 9, 7, 0, 4, 3][self.get_index()] + (earth_branch_index if YinYang.YANG == self.get_yin_yang() else -earth_branch_index))
def get_combine(self) -> HeavenStem:
"""
天干五合(甲己合,乙庚合,丙辛合,丁壬合,戊癸合)
:return: 天干
"""
return self.next(5)
def combine(self, target: HeavenStem) -> Element:
"""
合化(甲己合化土 乙庚合化金 丙辛合化水 丁壬合化木 戊癸合化火)
:param target: 天干
:return: 能合化则返回五行属性,不能合化则返回None
"""
return Element(self.get_index() + 2) if self.get_combine() == target else None
class HideHeavenStem(AbstractCulture):
"""藏干(即人元,司令取天干,分野取天干的五行)"""
def __init__(self, heaven_stem: Union[HeavenStem, str, int], hide_heaven_stem_type: HideHeavenStemType):
if isinstance(heaven_stem, int) or isinstance(heaven_stem, str):
self._heaven_stem = HeavenStem(heaven_stem)
else:
self._heaven_stem = heaven_stem
self._type = hide_heaven_stem_type
def get_name(self) -> str:
return self._heaven_stem.get_name()
def get_heaven_stem(self) -> HeavenStem:
"""
天干
:return: 天干
"""
return self._heaven_stem
def get_type(self) -> HideHeavenStemType:
"""
藏干类型
:return: 藏干类型
"""
return self._type
class HideHeavenStemDay(AbstractCultureDay):
"""人元司令分野(地支藏干+天索引)"""
def __init__(self, hide_heaven_stem: HideHeavenStem, day_index: int):
super().__init__(hide_heaven_stem, day_index)
def get_hide_heaven_stem(self) -> HideHeavenStem:
"""
:return: 藏干
"""
return self.get_culture()
def get_name(self) -> str:
heaven_stem: HeavenStem = self.get_hide_heaven_stem().get_heaven_stem()
return f'{heaven_stem.get_name()}{heaven_stem.get_element().get_name()}'
class SixtyCycle(LoopTyme):
"""六十甲子(六十干支周)"""
_NAMES: List[str] = ['甲子', '乙丑', '丙寅', '丁卯', '戊辰', '己巳', '庚午', '辛未', '壬申', '癸酉', '甲戌', '乙亥', '丙子', '丁丑', '戊寅', '己卯', '庚辰', '辛巳', '壬午', '癸未', '甲申', '乙酉', '丙戌', '丁亥', '戊子', '己丑', '庚寅', '辛卯', '壬辰', '癸巳', '甲午', '乙未', '丙申', '丁酉', '戊戌', '己亥', '庚子', '辛丑', '壬寅', '癸卯', '甲辰', '乙巳', '丙午', '丁未', '戊申', '己酉', '庚戌', '辛亥', '壬子', '癸丑', '甲寅', '乙卯', '丙辰', '丁巳', '戊午', '己未', '庚申', '辛酉', '壬戌', '癸亥']
"""名称"""
def __init__(self, index_or_name: Union[int, str]):
super().__init__(self._NAMES, index_or_name)
@classmethod
def from_name(cls, name: str) -> SixtyCycle:
return cls(name)
@classmethod
def from_index(cls, index: int) -> SixtyCycle:
return cls(index)
def next(self, n: int) -> SixtyCycle:
return SixtyCycle(self.next_index(n))
def get_heaven_stem(self) -> HeavenStem:
"""
天干
:return: 天干
"""
return HeavenStem(self.get_index() % 10)
def get_earth_branch(self) -> EarthBranch:
"""
地支
:return: 地支
"""
return EarthBranch(self.get_index() % 12)
def get_sound(self) -> Sound:
"""
纳音
:return: 纳音
"""
return Sound(self.get_index() // 2)
def get_peng_zu(self) -> PengZu:
"""
彭祖百忌
:return: 彭祖百忌
"""
return PengZu(self)
def get_ten(self) -> Ten:
"""
旬
:return: 旬
"""
return Ten((self.get_heaven_stem().get_index() - self.get_earth_branch().get_index()) // 2)
def get_extra_earth_branches(self) -> List[EarthBranch]:
"""
旬空(空亡),因地支比天干多2个,旬空则为每一轮干支一一配对后多出来的2个地支
:return: 旬空(空亡)
"""
earth_branch: EarthBranch = EarthBranch(10 + self.get_earth_branch().get_index() - self.get_heaven_stem().get_index())
return [earth_branch, earth_branch.next(1)]
class SixtyCycleYear(AbstractTyme):
"""
干支年
"""
def __init__(self, year: int):
if year < -1 or year > 9999:
raise ValueError(f'illegal sixty cycle year: {year}')
self._year = year
@classmethod
def from_year(cls, year: int) -> SixtyCycleYear:
return cls(year)
def get_year(self) -> int:
"""
年
:return: 干支年数字,范围为-1到9999
"""
return self._year
def get_name(self) -> str:
"""
:return: {六十甲子}年
"""
return f'{self.get_sixty_cycle().get_name()}年'
def next(self, n: int) -> SixtyCycleYear:
return SixtyCycleYear(self._year + n)
def get_sixty_cycle(self) -> SixtyCycle:
"""
干支
:return: 干支 SixtyCycle
"""
return SixtyCycle(self._year - 4)
def get_twenty(self) -> Twenty:
"""
运
:return: 运 Twenty
"""
return Twenty(floor((self._year - 1864) / 20))
def get_nine_star(self) -> NineStar:
"""
九星
:return: 九星 NineStar
"""
return NineStar(63 + self.get_twenty().get_sixty().get_index() * 3 - self.get_sixty_cycle().get_index())
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
return Direction([0, 7, 7, 2, 3, 3, 8, 1, 1, 6, 0, 0][self.get_sixty_cycle().get_earth_branch().get_index()])
def get_first_month(self) -> SixtyCycleMonth:
"""
首月(依据五虎遁和正月起寅的规律)
:return: 干支月
"""
return SixtyCycleMonth(self, SixtyCycle.from_index(self._year * 12 - 46))
def get_months(self) -> List[SixtyCycleMonth]:
"""
干支月列表
:return: 干支月列表
"""
l: List[SixtyCycleMonth] = []
m: SixtyCycleMonth = self.get_first_month()
l.append(m)
for i in range(1, 12):
l.append(m.next(i))
return l
class SixtyCycleMonth(AbstractTyme):
"""干支月"""
def __init__(self, year: SixtyCycleYear, month: SixtyCycle):
"""
:param year: 干支年
:param month: 干支月
"""
self._year = year
self._month = month
@classmethod
def from_index(cls, year: int, index: int) -> SixtyCycleMonth:
return SixtyCycleYear.from_year(year).get_first_month().next(index)
def get_sixty_cycle_year(self) -> SixtyCycleYear:
"""
干支年
:return: 干支年
"""
return self._year
def get_year(self) -> SixtyCycle:
"""
年柱
:return: 干支
"""
return self._year.get_sixty_cycle()
def get_sixty_cycle(self) -> SixtyCycle:
"""
干支
:return: 干支
"""
return self._month
def get_index_in_year(self) -> int:
"""
位于当年的索引(0-11),寅月为0,依次类推
:return: 数字,范围0到11,寅月为0,依次类推
"""
return self._month.get_earth_branch().next(-2).get_index()
def get_name(self) -> str:
"""
名称
:return: 名称
"""
return f'{self._month}月'
def __str__(self) -> str:
return f'{self._year}{self.get_name()}'
def next(self, n: int) -> SixtyCycleMonth:
return SixtyCycleMonth(SixtyCycleYear.from_year((self._year.get_year()*12 + self.get_index_in_year() + n) // 12), self._month.next(n))
def get_first_day(self) -> SixtyCycleDay:
from tyme4py.solar import SolarTerm
return SixtyCycleDay.from_solar_day(SolarTerm.from_index(self._year.get_year(), 3+self.get_index_in_year()*2).get_solar_day())
def get_days(self) -> List[SixtyCycleDay]:
"""
本月的干支日列表
:return: 支日列表
"""
l: List[SixtyCycleDay] = []
d: SixtyCycleDay = self.get_first_day()
while d.get_sixty_cycle_month() == self:
l.append(d)
d = d.next(1)
return l
def get_nine_star(self) -> NineStar:
"""
:return: 九星 NineStar
"""
index = self._month.get_earth_branch().get_index()
if index < 2:
index += 3
return NineStar(27 - self.get_year().get_earth_branch().get_index() % 3 * 3 - index)
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
n: int = [7, -1, 1, 3][self._month.get_earth_branch().next(-2).get_index() % 4]
return self._month.get_heaven_stem().get_direction() if n == -1 else Direction(n)
class SixtyCycleDay(AbstractTyme):
"""干支日"""
def __init__(self, solar_day: SolarDay, month: SixtyCycleMonth, day: SixtyCycle):
"""
:param solar_day: 公历年
:param month: 干支月
:param day: 日柱
"""
self._solar_day = solar_day
self._month = month
self._day = day
@classmethod
def from_solar_day(cls, solar_day: SolarDay) -> SixtyCycleDay:
from tyme4py.solar import SolarTerm, SolarDay
term: SolarTerm = solar_day.get_term()
index: int = term.get_index()
offset: int = -1
if index < 3:
if index == 0:
offset = -2
else:
offset = (index - 3) // 2
return cls(solar_day, SixtyCycleYear.from_year(term.get_year()).get_first_month().next(offset), SixtyCycle.from_index(solar_day.subtract(SolarDay.from_ymd(2000, 1, 7))))
def get_solar_day(self) -> SolarDay:
"""
:return: 公历日
"""
return self._solar_day
def get_sixty_cycle_month(self) -> SixtyCycleMonth:
"""
:return: 干支月
"""
return self._month
def get_year(self) -> SixtyCycle:
"""
年柱
:return: 干支
"""
return self._month.get_year()
def get_month(self) -> SixtyCycle:
"""
月柱
:return: 干支
"""
return self._month.get_sixty_cycle()
def get_sixty_cycle(self) -> SixtyCycle:
"""
干支
:return: 干支
"""
return self._day
def get_name(self) -> str:
return f'{self._day}日'
def __str__(self) -> str:
return f'{self._month}{self.get_name()}'
def next(self, n: int) -> SixtyCycleDay:
return SixtyCycleDay.from_solar_day(self._solar_day.next(n))
def get_duty(self) -> Duty:
"""
建除十二值神
:return: 建除十二值神 Duty
"""
return Duty(self._day.get_earth_branch().get_index() - self.get_month().get_earth_branch().get_index())
def get_twelve_star(self) -> TwelveStar:
"""
黄道黑道十二神
:return: 黄道黑道十二神 TwelveStar
"""
return TwelveStar(self._day.get_earth_branch().get_index() + (8 - self.get_month().get_earth_branch().get_index() % 6) * 2)
def get_nine_star(self) -> NineStar:
"""
九星
:return: 九星 NineStar
"""
return self._solar_day.get_nine_star()
def get_jupiter_direction(self) -> Direction:
"""
太岁方位
:return: 方位 Direction
"""
index: int = self._day.get_index()
from tyme4py.culture import Element
return Element(index // 12).get_direction() if index % 12 < 6 else self._month.get_sixty_cycle_year().get_jupiter_direction()
def get_fetus_day(self) -> FetusDay:
"""
逐日胎神
:return:逐日胎神 FetusDay
"""
return FetusDay.from_sixty_cycle_day(self)
def get_twenty_eight_star(self) -> TwentyEightStar:
"""
二十八宿
:return: 二十八宿 TwentyEightStar
"""
from tyme4py.culture.star.twentyeight import TwentyEightStar
return TwentyEightStar(10 + 8 * self._solar_day.get_week().get_index()).next(-7 * self._day.get_earth_branch().get_index())
def get_gods(self) -> List[God]:
"""
神煞列表(吉神宜趋,凶神宜忌)
:return: 神煞列表
"""
return God.get_day_gods(self.get_month(), self._day)
def get_recommends(self) -> List[Taboo]:
"""
今日 宜
:return: 宜忌列表
"""
return Taboo.get_day_recommends(self.get_month(), self._day)
def get_avoids(self) -> List[Taboo]:
"""
今日 忌
:return: 宜忌列表
"""
return Taboo.get_day_avoids(self.get_month(), self._day)
def get_hours(self) -> List[SixtyCycleHour]:
"""
当天的干支时辰列表
:return: 干支时辰列表
"""
from tyme4py.solar import SolarDay, SolarTime
l: List[SixtyCycleHour] = []
d: SolarDay = self._solar_day.next(-1)
t: SolarTime = SolarTime.from_ymd_hms(d.get_year(), d.get_month(), d.get_day(), 23, 0, 0)
h: SixtyCycleHour = SixtyCycleHour.from_solar_time(t)
l.append(h)
for i in range(0, 11):
h = h.next(7200)
l.append(h)
return l
def get_three_pillars(self) -> ThreePillars:
return ThreePillars(self.get_year(), self.get_month(), self.get_sixty_cycle())
class SixtyCycleHour(AbstractTyme):
"""干支时辰"""
def __init__(self, solar_time: SolarTime):
from tyme4py.solar import SolarTerm, SolarTime
from tyme4py.lunar import LunarYear, LunarMonth, LunarDay, LunarHour
solar_year: int = solar_time.get_year()
spring_solar_time: SolarTime = SolarTerm.from_index(solar_year, 3).get_julian_day().get_solar_time()
lunar_hour: LunarHour = solar_time.get_lunar_hour()
lunar_day: LunarDay = lunar_hour.get_lunar_day()
lunar_year: LunarYear = lunar_day.get_lunar_month().get_lunar_year()
if lunar_year.get_year() == solar_year:
if solar_time.is_before(spring_solar_time):
lunar_year = lunar_year.next(-1)
elif lunar_year.get_year() < solar_year:
if not solar_time.is_before(spring_solar_time):
lunar_year = lunar_year.next(1)
term: SolarTerm = solar_time.get_term()
index: int = term.get_index() - 3
if index < 0 and term.get_julian_day().get_solar_time().is_after(SolarTerm.from_index(solar_year, 3).get_julian_day().get_solar_time()):
index += 24
d: SixtyCycle = lunar_day.get_sixty_cycle()
if solar_time.get_hour() == 23:
d = d.next(1)
y: SixtyCycleYear = SixtyCycleYear.from_year(lunar_year.get_year())
m: LunarMonth = LunarMonth.from_ym(solar_year, 1)
self._solar_time = solar_time
self._day = SixtyCycleDay(solar_time.get_solar_day(), SixtyCycleMonth(y, m.get_sixty_cycle().next(int(floor(index * 0.5)))), d)
self._hour = lunar_hour.get_sixty_cycle()
@classmethod
def from_solar_time(cls, solar_time: SolarTime) -> SixtyCycleHour:
return cls(solar_time)
def get_year(self) -> SixtyCycle:
"""
年柱
:return: 干支
"""
return self._day.get_year()
def get_month(self) -> SixtyCycle:
"""
月柱
:return: 干支
"""
return self._day.get_month()
def get_day(self) -> SixtyCycle:
"""
日柱
:return: 干支
"""
return self._day.get_sixty_cycle()
def get_sixty_cycle(self) -> SixtyCycle:
"""
干支
:return: 干支
"""
return self._hour
def get_sixty_cycle_day(self) -> SixtyCycleDay:
"""
干支日
:return: 干支日
"""
return self._day
def get_solar_time(self) -> SolarTime:
"""
公历时刻
:return: 公历时刻
"""
return self._solar_time
def get_name(self) -> str:
return f'{self._hour}时'
def __str__(self) -> str:
return f'{self._day}{self.get_name()}'
def get_index_in_day(self) -> int:
"""
位于当天的索引
:return: 位于当天的索引
"""
h: int = self._solar_time.get_hour()
if h == 23:
return 0
return (h + 1) // 2
def next(self, n: int) -> SixtyCycleHour:
return SixtyCycleHour.from_solar_time(self._solar_time.next(n))
def get_twelve_star(self) -> TwelveStar:
"""
黄道黑道十二神
:return: 黄道黑道十二神 TwelveStar
"""
return TwelveStar(self._hour.get_earth_branch().get_index() + (8 - self.get_day().get_earth_branch().get_index() % 6) * 2)
def get_nine_star(self) -> NineStar:
"""
九星(时家紫白星歌诀:三元时白最为佳,冬至阳生顺莫差,孟日七宫仲一白,季日四绿发萌芽,每把时辰起甲子,本时星耀照光华,时星移入中宫去,顺飞八方逐细查。夏至阴生逆回首,孟归三碧季加六,仲在九宫时起甲,依然掌中逆轮跨。)
:return: 九星 NineStar
"""
from tyme4py.solar import SolarTerm, SolarDay
solar: SolarDay = self._solar_time.get_solar_day()
dong_zhi: SolarTerm = SolarTerm(solar.get_year(), 0)
earth_branch_index: int = self.get_index_in_day() % 12
index: int = 8 - 3 * (self.get_day().get_earth_branch().get_index() % 3)
if (not solar.is_before(dong_zhi.get_julian_day().get_solar_day())) and solar.is_before(dong_zhi.next(12).get_julian_day().get_solar_day()):
index = 8 + earth_branch_index - index
else:
index -= earth_branch_index
return NineStar(index)
def get_eight_char(self) -> EightChar:
"""
八字
:return: 八字
"""
return EightChar(self.get_year(), self.get_month(), self.get_day(), self._hour)
def get_recommends(self) -> List[Taboo]:
"""
时辰 宜
:return: 宜忌列表
"""
return Taboo.get_hour_recommends(self.get_day(), self._hour)
def get_avoids(self) -> List[Taboo]:
"""
时辰 忌
:return: 宜忌列表
"""
return Taboo.get_hour_avoids(self.get_day(), self._hour)
+918
View File
@@ -0,0 +1,918 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from math import floor, ceil
from typing import TYPE_CHECKING, Union, List
from tyme4py import LoopTyme, AbstractCultureDay
from tyme4py.culture import Week, Constellation, PhaseDay, Phase
from tyme4py.culture.dog import DogDay, Dog
from tyme4py.culture.nine import NineDay, Nine
from tyme4py.culture.phenology import PhenologyDay, Phenology
from tyme4py.culture.plumrain import PlumRainDay, PlumRain
from tyme4py.culture.star.nine import NineStar
from tyme4py.enums import HideHeavenStemType
from tyme4py.event import Event
from tyme4py.unit import YearUnit, MonthUnit, WeekUnit, DayUnit, SecondUnit
from tyme4py.util import ShouXingUtil
from tyme4py.jd import JulianDay
from tyme4py.festival import SolarFestival
from tyme4py.holiday import LegalHoliday
if TYPE_CHECKING:
from tyme4py.lunar import LunarDay, LunarMonth, LunarHour
from tyme4py.sixtycycle import HideHeavenStemDay, SixtyCycleDay, SixtyCycleHour
from tyme4py.rabbyung import RabByungYear, RabByungDay
from tyme4py.hijri import HijriDay
class SolarTerm(LoopTyme):
"""节气"""
NAMES: List[str] = ['冬至', '小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪']
"""名称"""
def __init__(self, year: int, index_or_name: Union[int, str]):
super().__init__(self.NAMES, index_or_name)
y = year
if isinstance(index_or_name, int):
size = self.NAMES.__len__()
y = (year * size + index_or_name) // size
jd = floor((y - 2000) * 365.2422 + 180)
# 355对应2000.12冬至,计算粗略估计值
w = floor((jd - 355 + 183) / 365.2422) * 365.2422 + 355
if ShouXingUtil.calc_qi(w) > jd:
w -= 365.2422
self._year = y
self._cursory_julian_day = ShouXingUtil.calc_qi(w + 15.2184 * self.get_index())
@classmethod
def from_index(cls, year: int, index: int) -> SolarTerm:
return cls(year, index)
@classmethod
def from_name(cls, year: int, name: str) -> SolarTerm:
return cls(year, name)
def next(self, n: int) -> SolarTerm:
size = self.get_size()
i = self.get_index() + n
return SolarTerm((self._year * size + i) // size, self._index_of_by(i))
def is_jie(self) -> bool:
"""是否节令"""
return self._index % 2 == 1
def is_qi(self) -> bool:
"""是否气令"""
return self._index % 2 == 0
def get_julian_day(self) -> JulianDay:
"""
儒略日(精确到秒)
:return : 儒略日
"""
return JulianDay.from_julian_day(ShouXingUtil.qi_accurate2(self._cursory_julian_day) + JulianDay.J2000)
def get_solar_day(self) -> SolarDay:
"""
公历日(用于日历)
@return: 公历日
"""
return JulianDay.from_julian_day(self._cursory_julian_day + JulianDay.J2000).get_solar_day()
def get_year(self) -> int:
return self._year
def get_cursory_julian_day(self) -> float:
"""
儒略日(用于日历,只精确到日中午12:00)
@return: 儒略日
"""
return self._cursory_julian_day
class SolarTermDay(AbstractCultureDay):
"""节气第几天"""
def __init__(self, solar_term: SolarTerm, day_index: int):
super().__init__(solar_term, day_index)
def get_solar_term(self) -> SolarTerm:
"""
:return: 节气
"""
return self.get_culture()
class SolarYear(YearUnit):
"""公历年"""
def __init__(self, year: int):
SolarYear.validate(year)
super().__init__(year)
@staticmethod
def validate(year: int) -> None:
if year < 1 or year > 9999:
raise ValueError(f'illegal solar year: {year}')
@classmethod
def from_year(cls, year: int) -> SolarYear:
return cls(year)
def get_day_count(self) -> int:
if self._year == 1582:
return 355
return 366 if self.is_leap() else 365
def is_leap(self) -> bool:
if self._year < 1600:
return self._year % 4 == 0
return (self._year % 4 == 0 and self._year % 100 != 0) or (self._year % 400 == 0)
def get_name(self) -> str:
return f"{self._year}年"
def next(self, n: int) -> SolarYear:
return SolarYear.from_year(self._year + n)
def get_months(self) -> List[SolarMonth]:
return [SolarMonth.from_ym(self._year, month) for month in range(1, 13)]
def get_seasons(self) -> List[SolarSeason]:
return [SolarSeason.from_index(self._year, i) for i in range(4)]
def get_half_years(self) -> List[SolarHalfYear]:
return [SolarHalfYear.from_index(self._year, i) for i in range(2)]
def get_rab_byung_year(self) -> RabByungYear:
from tyme4py.rabbyung import RabByungYear
return RabByungYear.from_year(self._year)
class SolarHalfYear(YearUnit):
"""公历半年"""
NAMES: List[str] = ['上半年', '下半年']
@staticmethod
def validate(year: int, index: int) -> None:
if index < 0 or index > 1:
raise ValueError(f'illegal solar half year index: {index}')
SolarYear.validate(year)
def __init__(self, year: int, index: int):
SolarHalfYear.validate(year, index)
super().__init__(year)
self._index = index
@classmethod
def from_index(cls, year: int, index: int) -> SolarHalfYear:
return cls(year, index)
def get_solar_year(self) -> SolarYear:
return SolarYear.from_year(self._year)
def get_index(self) -> int:
return self._index
def get_name(self) -> str:
return self.NAMES[self._index]
def __str__(self) -> str:
return f'{self.get_solar_year()}{self.get_name()}'
def next(self, n: int) -> SolarHalfYear:
i = self._index + n
return SolarHalfYear.from_index((self.get_year() * 2 + i) // 2, self.index_of(i, 2))
def get_months(self) -> List[SolarMonth]:
y = self.get_year()
return [SolarMonth.from_ym(y, self._index * 6 + i) for i in range(1, 7)]
def get_seasons(self) -> List[SolarSeason]:
y = self.get_year()
return [SolarSeason.from_index(y, self._index * 2 + i) for i in range(2)]
class SolarSeason(YearUnit):
"""公历季度"""
NAMES: List[str] = ['一季度', '二季度', '三季度', '四季度']
@staticmethod
def validate(year: int, index: int) -> None:
if index < 0 or index > 3:
raise ValueError(f'illegal solar season index: {index}')
SolarYear.validate(year)
def __init__(self, year: int, index: int):
SolarSeason.validate(year, index)
super().__init__(year)
self._index = index
@classmethod
def from_index(cls, year: int, index: int) -> SolarSeason:
return cls(year, index)
def get_solar_year(self) -> SolarYear:
return SolarYear.from_year(self._year)
def get_index(self) -> int:
return self._index
def get_name(self) -> str:
return self.NAMES[self._index]
def __str__(self) -> str:
return f'{self.get_solar_year()}{self.get_name()}'
def next(self, n: int) -> SolarSeason:
i = self._index + n
return SolarSeason.from_index((self.get_year() * 4 + i) // 4, self.index_of(i, 4))
def get_months(self) -> List[SolarMonth]:
y = self.get_year()
return [SolarMonth.from_ym(y, self._index * 3 + i) for i in range(1, 4)]
class SolarMonth(MonthUnit):
"""公历月"""
NAMES: List[str] = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
_DAYS: List[int] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
"""每月天数"""
@staticmethod
def validate(year: int, month: int) -> None:
if month < 1 or month > 12:
raise ValueError(f'illegal solar month: {month}')
SolarYear.validate(year)
def __init__(self, year: int, month: int):
"""
:param year: 年
:param month: 月
"""
SolarMonth.validate(year, month)
super().__init__(year, month)
@classmethod
def from_ym(cls, year: int, month: int) -> SolarMonth:
return cls(year, month)
def get_solar_year(self) -> SolarYear:
"""
:return: 公历年
"""
return SolarYear.from_year(self._year)
def get_day_count(self) -> int:
"""
当月的总天数
:return: 天数(1582年10月只有21天)
"""
if 1582 == self._year and 10 == self._month:
return 21
d: int = self._DAYS[self.get_index_in_year()]
# 公历闰年2月多一天
if 2 == self._month and self.get_solar_year().is_leap():
d += 1
return d
def get_index_in_year(self) -> int:
"""
位于当年的月索引
:return: 位于当年的索引(0-11)
"""
return self._month - 1
def get_season(self) -> SolarSeason:
"""
:return: 公历季度 SolarSeason
"""
return SolarSeason(self._year, int(self.get_index_in_year() / 3))
def get_week_count(self, start: int) -> int:
"""
当月有几周
:param start:起始星期,1234560分别代表星期一至星期天
:return:周数
"""
return ceil((self.index_of(SolarDay(self._year, self._month, 1).get_week().get_index() - start, 7) + self.get_day_count()) / 7)
def get_name(self) -> str:
return self.NAMES[self.get_index_in_year()]
def __str__(self) -> str:
return f'{self.get_solar_year()}{self.get_name()}'
def next(self, n: int) -> SolarMonth:
i: int = self._month - 1 + n
return SolarMonth((self._year * 12 + i) // 12, self.index_of(i, 12) + 1)
def get_weeks(self, start: int) -> List[SolarWeek]:
"""
本月的公历周列表
:param start: 星期几作为一周的开始,1234560分别代表星期一至星期天
:return: 周列表
"""
l: List[SolarWeek] = []
for i in range(0, self.get_week_count(start)):
l.append(SolarWeek(self._year, self._month, i, start))
return l
def get_days(self) -> List[SolarDay]:
"""
本月的公历日列表
:return: 公历日 SolarDay 的列表,从1日开始
"""
l: List[SolarDay] = []
for i in range(1, self.get_day_count()):
l.append(SolarDay(self._year, self._month, i))
return l
def get_first_day(self) -> SolarDay:
"""
本月第一天
:return: 公历日 SolarDay
"""
return SolarDay.from_ymd(self._year, self._month, 1)
class SolarWeek(WeekUnit):
"""公历周"""
@staticmethod
def validate(year: int, month: int, index: int, start: int) -> None:
WeekUnit.validate(year, month, index, start)
m: SolarMonth = SolarMonth(year, month)
if index >= m.get_week_count(start):
raise ValueError(f'illegal solar week index: {index} in month: {m}')
def __init__(self, year: int, month: int, index: int, start: int):
"""
:param year: 年
:param month: 月
:param index: 索引,0-5
:param start: 起始星期,1234560分别代表星期一至星期天
"""
SolarWeek.validate(year, month, index, start)
super().__init__(year, month, index, start)
@classmethod
def from_ym(cls, year: int, month: int, index: int, start: int) -> SolarWeek:
return cls(year, month, index, start)
def get_solar_month(self) -> SolarMonth:
"""
:return: 公历月
"""
return SolarMonth.from_ym(self._year, self._month)
def get_index_in_year(self) -> int:
"""
位于当年的索引
:return: 索引 注意:索引值是从0开始,即0代表第一周
"""
i: int = 0
# 本周第1天
first_day: SolarDay = self.get_first_day()
# 今年第1周
w: SolarWeek = SolarWeek(self._year, 1, 0, self._start)
while not w.get_first_day() == first_day:
w = w.next(1)
i += 1
return i
def get_name(self) -> str:
return self.NAMES[self._index]
def __str__(self) -> str:
return f'{self.get_solar_month()}{self.get_name()}'
def next(self, n: int) -> SolarWeek:
d: int = self._index + n
m: SolarMonth = self.get_solar_month()
if n > 0:
week_count: int = m.get_week_count(self._start)
while d >= week_count:
d -= week_count
m = m.next(1)
if m.get_first_day().get_week().get_index() != self._start:
d += 1
week_count = m.get_week_count(self._start)
elif n < 0:
while d < 0:
if m.get_first_day().get_week().get_index() != self._start:
d -= 1
m = m.next(-1)
d += m.get_week_count(self._start)
return SolarWeek(m.get_year(), m.get_month(), d, self._start)
def get_first_day(self) -> SolarDay:
"""
本周第1天
:return: 公历日
"""
first_day: SolarDay = SolarDay(self._year, self._month, 1)
return first_day.next(self._index * 7 - self.index_of(first_day.get_week().get_index() - self._start, 7))
def get_days(self) -> List[SolarDay]:
"""
本周公历日列表
:return: 公历日列表
"""
l: List[SolarDay] = []
d: SolarDay = self.get_first_day()
l.append(d)
for i in range(1, 7):
l.append(d.next(i))
return l
def __eq__(self, o: SolarWeek) -> bool:
return o and o.get_first_day() == self.get_first_day()
class SolarDay(DayUnit):
"""
公历日
"""
NAMES: List[str] = ['1日', '2日', '3日', '4日', '5日', '6日', '7日', '8日', '9日', '10日', '11日', '12日', '13日', '14日', '15日', '16日', '17日', '18日', '19日', '20日', '21日', '22日', '23日', '24日', '25日', '26日', '27日', '28日', '29日', '30日', '31日']
@staticmethod
def validate(year: int, month: int, day: int) -> None:
if day < 1:
raise ValueError(f'illegal solar day: {year}-{month}-{day}')
if 1582 == year and 10 == month:
if (4 < day < 15) or day > 31:
raise ValueError(f'illegal solar day: {year}-{month}-{day}')
elif day > SolarMonth.from_ym(year, month).get_day_count():
raise ValueError(f'illegal solar day: {year}-{month}-{day}')
def __init__(self, year: int, month: int, day: int):
SolarDay.validate(year, month, day)
super().__init__(year, month, day)
@classmethod
def from_ymd(cls, year: int, month: int, day: int) -> SolarDay:
return cls(year, month, day)
def get_solar_month(self) -> SolarMonth:
"""
:return: 公历月
"""
return SolarMonth.from_ym(self._year, self._month)
def get_week(self) -> Week:
"""
:return: 星期
"""
return self.get_julian_day().get_week()
def get_constellation(self) -> Constellation:
"""
:return: 星座 Constellation
"""
m: int = self._month - 1
offset: int = 1 if self._day > [19, 18, 20, 19, 20, 21, 22, 22, 22, 23, 22, 21][m] else 0
return Constellation.from_index(9 + m + offset)
def get_name(self) -> str:
return self.NAMES[self._day - 1]
def __str__(self) -> str:
return f'{self.get_solar_month()}{self.get_name()}'
def next(self, n: int) -> SolarDay:
return self.get_julian_day().next(n).get_solar_day()
def is_before(self, target: SolarDay) -> bool:
"""
是否在指定公历日之前
:param target: 公历日
:return: true/false
"""
y: int = target.get_year()
if self._year != y:
return self._year < y
m: int = target.get_month()
return self._month < m if self._month != m else self._day < target.get_day()
def is_after(self, target: SolarDay) -> bool:
"""
是否在指定公历日之后
:param target: 公历日
:return: true/false
"""
y: int = target.get_year()
if self._year != y:
return self._year > y
m: int = target.get_month()
return self._month > m if self._month != m else self._day > target.get_day()
def get_term(self) -> SolarTerm:
"""
:return: 当天所在的节气 SolarTerm
"""
return self.get_term_day().get_solar_term()
def get_term_day(self) -> SolarTermDay:
"""
:return: 节气第几天
"""
y: int = self._year
i: int = self._month * 2
if i == 24:
y += 1
i = 0
term: SolarTerm = SolarTerm(y, i + 1)
day: SolarDay = term.get_solar_day()
while self.is_before(day):
term = term.next(-1)
day = term.get_solar_day()
return SolarTermDay(term, self.subtract(day))
def get_solar_week(self, start: int) -> SolarWeek:
"""
公历周
:param start: 起始星期,1234560分别代表星期一至星期天
:return: 公历周
"""
return SolarWeek(self._year, self._month, ceil((self._day + SolarDay(self._year, self._month, 1).get_week().next(-start).get_index()) / 7.0) - 1, start)
def get_phenology_day(self) -> PhenologyDay:
"""
当天所在的七十二候
:return: 七十二候 PhenologyDay
"""
d: SolarTermDay = self.get_term_day()
day_index: int = d.get_day_index()
index: int = day_index // 5
if index > 2:
index = 2
term: SolarTerm = d.get_solar_term()
return PhenologyDay(Phenology(term.get_year(), term.get_index() * 3 + index), day_index - index * 5)
def get_phenology(self) -> Phenology:
"""
当天所在的候
:return: 候 Phenology
"""
return self.get_phenology_day().get_phenology()
def get_dog_day(self) -> Union[DogDay, None]:
"""
当天所在的三伏天
:return: 三伏天 DogDay
"""
# 初伏,夏至后第3个庚日
d0: SolarDay = Event.builder().term_heaven_stem(12, 6, 20).build().get_solar_day(self._year)
# 中伏,夏至后第4个庚日
d1: SolarDay = Event.builder().term_heaven_stem(12, 6, 30).build().get_solar_day(self._year)
# 末伏,立秋后第1个庚日
d2: SolarDay = Event.builder().term_heaven_stem(15, 6, 0).build().get_solar_day(self._year)
if self.is_before(d0) or self.is_after(d2.next(9)):
return None
if not self.is_before(d2):
return DogDay(Dog.from_index(2), self.subtract(d2))
return DogDay(Dog.from_index(0), self.subtract(d0)) if self.is_before(d1) else DogDay(Dog.from_index(1), self.subtract(d1))
def get_plum_rain_day(self) -> Union[PlumRainDay, None]:
"""
当天所在的梅雨天(芒种后的第1个丙日入梅,小暑后的第1个未日出梅)
:return: 梅雨天
"""
# 入梅,芒种后第1个丙日
start: SolarDay = Event.builder().term_heaven_stem(11, 2, 0).build().get_solar_day(self._year)
# 出梅,小暑后第1个未日
end: SolarDay = Event.builder().term_earth_branch(13, 7, 0).build().get_solar_day(self._year)
if self.is_before(start) or self.is_after(end):
return None
return PlumRainDay(PlumRain(1), 0) if self == end else PlumRainDay(PlumRain(0), self.subtract(start))
def get_hide_heaven_stem_day(self) -> HideHeavenStemDay:
"""
:return: 人元司令分野
"""
from tyme4py.sixtycycle import HideHeavenStemDay, HideHeavenStem
day_counts: List[int] = [3, 5, 7, 9, 10, 30]
term: SolarTerm = self.get_term()
if term.is_qi():
term = term.next(-1)
day_index: int = self.subtract(term.get_solar_day())
start_index: int = (term.get_index() - 1) * 3
data: str = '93705542220504xx1513904541632524533533105544806564xx7573304542018584xx95'[start_index: start_index + 6]
days: int = 0
heaven_stem_index: int = 0
type_index: int = 0
while type_index < 3:
i: int = type_index * 2
d: str = data[i: i + 1]
count: int = 0
if d != 'x':
heaven_stem_index = int(d, 10)
count = day_counts[int(data[i + 1: i + 2], 10)]
days += count
if day_index <= days:
day_index -= days - count
break
type_index += 1
hide_type: HideHeavenStemType
if type_index == 0:
hide_type = HideHeavenStemType.RESIDUAL
elif type_index == 1:
hide_type = HideHeavenStemType.MIDDLE
else:
hide_type = HideHeavenStemType.MAIN
return HideHeavenStemDay(HideHeavenStem(heaven_stem_index, hide_type), day_index)
def get_nine_day(self) -> Union[NineDay, None]:
"""
当天所在的数九天
:return: 数九天 NineDay
"""
start: SolarDay = SolarTerm(self._year + 1, 0).get_solar_day()
if self.is_before(start):
start = SolarTerm(self._year, 0).get_solar_day()
end: SolarDay = start.next(81)
if self.is_before(start) or (not self.is_before(end)):
return None
days: int = self.subtract(start)
return NineDay(Nine(int(days / 9)), days % 9)
def get_index_in_year(self) -> int:
"""
位于当年的索引
:return: 索引
"""
return self.subtract(SolarDay(self._year, 1, 1))
def subtract(self, target: SolarDay) -> int:
"""
公历日期相减,获得相差天数
:param target: 公历
:return: 两个公历日之间相差的天数
"""
return int(self.get_julian_day().subtract(target.get_julian_day()))
def get_julian_day(self) -> JulianDay:
"""
公历日转儒略日
:return: 儒略日
"""
return JulianDay.from_ymd_hms(self._year, self._month, self._day, 0, 0, 0)
def get_lunar_day(self) -> LunarDay:
"""
:return: 农历日
"""
from tyme4py.lunar import LunarMonth, LunarDay
m: LunarMonth = LunarMonth.from_ym(self._year, self._month)
days: int = self.subtract(m.get_first_julian_day().get_solar_day())
while days < 0:
m = m.next(-1)
days += m.get_day_count()
return LunarDay(m.get_year(), m.get_month_with_leap(), days + 1)
def get_sixty_cycle_day(self) -> SixtyCycleDay:
from tyme4py.sixtycycle import SixtyCycleDay
return SixtyCycleDay.from_solar_day(self)
def get_rab_byung_day(self) -> RabByungDay:
from tyme4py.rabbyung import RabByungDay
return RabByungDay.from_solar_day(self)
def get_legal_holiday(self) -> Union[LegalHoliday, None]:
"""
法定假日,如果当天不是法定假日,返回None
:return: 法定假日
"""
return LegalHoliday.from_ymd(self._year, self._month, self._day)
def get_festival(self) -> Union[SolarFestival, None]:
"""
公历现代节日,如果当天不是公历现代节日,返回None
:return: 公历现代节日
"""
return SolarFestival.from_ymd(self._year, self._month, self._day)
def get_phase_day(self) -> PhaseDay:
"""
月相第几天
:return: 月相第几天
"""
month = self.get_lunar_day().get_lunar_month().next(1)
p = Phase.from_index(month.get_year(), month.get_month_with_leap(), 0)
d = p.get_solar_day()
while d.is_after(self):
p = p.next(-1)
d = p.get_solar_day()
return PhaseDay(p, self.subtract(d))
def get_phase(self) -> Phase:
"""
月相
:return: 月相 Phase
"""
return self.get_phase_day().get_phase()
def get_nine_star(self) -> NineStar:
"""
:return: 九星 NineStar
"""
y: int = self.get_year()
winter_solstice: SolarDay = SolarTerm.from_index(y, 0).get_solar_day()
summer_solstice: SolarDay = SolarTerm.from_index(y, 12).get_solar_day()
next_winter_solstice: SolarDay = SolarTerm.from_index(y + 1, 0).get_solar_day()
w: SolarDay = winter_solstice.next(winter_solstice.get_lunar_day().get_sixty_cycle().steps_close_to(0))
s: SolarDay = summer_solstice.next(summer_solstice.get_lunar_day().get_sixty_cycle().steps_close_to(0))
n: SolarDay = next_winter_solstice.next(next_winter_solstice.get_lunar_day().get_sixty_cycle().steps_close_to(0))
if self.is_before(w):
return NineStar.from_index(w.subtract(self) - 1)
if self.is_before(s):
return NineStar.from_index(self.subtract(w))
return NineStar.from_index(n.subtract(self) - 1 if self.is_before(n) else self.subtract(n))
def get_hijri_day(self) -> HijriDay:
"""
:return: 回历 HijriDay
"""
d: int = self.subtract(SolarDay(622, 7, 16))
z = d // 10631
d -= z * 10631
y = int(floor((d + 0.5) / 354.366))
d -= int(floor(y * 354.366 + 0.5))
m = int(floor((d + 0.11) / 29.51))
d -= int(floor(m * 29.5 + 0.5))
from tyme4py.hijri import HijriDay
return HijriDay(z * 30 + y + 1, m + 1, d + 1)
class SolarTime(SecondUnit):
@staticmethod
def validate(year: int, month: int, day: int, hour: int, minute: int, second: int) -> None:
SecondUnit.validate(year, month, day, hour, minute, second)
SolarDay.validate(year, month, day)
def __init__(self, year: int, month: int, day: int, hour: int, minute: int, second: int):
SolarTime.validate(year, month, day, hour, minute, second)
super().__init__(year, month, day, hour, minute, second)
@classmethod
def from_ymd_hms(cls, year: int, month: int, day: int, hour: int, minute: int, second: int) -> SolarTime:
"""
:param year: 年
:param month: 月
:param day: 日
:param hour: 时
:param minute: 分
:param second: 秒
:return: 公历时刻
"""
return cls(year, month, day, hour, minute, second)
def get_solar_day(self) -> SolarDay:
"""
:return: 公历日
"""
return SolarDay.from_ymd(self._year, self._month, self._day)
def get_name(self) -> str:
return f'{self._hour:02d}:{self._minute:02d}:{self._second:02d}'
def __str__(self) -> str:
return f'{self.get_solar_day()} {self.get_name()}'
def next(self, n: int) -> SolarTime:
"""
推移
:param n: 推移秒数
:return: 公历时刻
"""
if n == 0:
return SolarTime(self._year, self._month, self._day, self._hour, self._minute, self._second)
ts: int = self._second + n
tm: int = self._minute + floor(ts / 60)
ts %= 60
if ts < 0:
ts += 60
tm -= 1
th: int = self._hour + int(tm / 60)
tm %= 60
if tm < 0:
tm += 60
th -= 1
td: int = int(th / 24)
th %= 24
if th < 0:
th += 24
td -= 1
d: SolarDay = self.get_solar_day().next(td)
return SolarTime(d.get_year(), d.get_month(), d.get_day(), th, tm, ts)
def is_before(self, target: SolarTime) -> bool:
"""
是否在指定公历时刻之前
:param target: 公历时刻
:return: true/false
"""
a_day: SolarDay = self.get_solar_day()
b_day: SolarDay = target.get_solar_day()
if a_day != b_day:
return a_day.is_before(b_day)
h: int = target.get_hour()
if self._hour != h:
return self._hour < h
m: int = target.get_minute()
return self._minute < m if self._minute != m else self._second < target.get_second()
def is_after(self, target: SolarTime) -> bool:
"""
是否在指定公历时刻之后
:param target: 公历时刻
:return: true/false
"""
a_day: SolarDay = self.get_solar_day()
b_day: SolarDay = target.get_solar_day()
if a_day != b_day:
return a_day.is_after(b_day)
h: int = target.get_hour()
if self._hour != h:
return self._hour > h
m: int = target.get_minute()
return self._minute > m if self._minute != m else self._second > target.get_second()
def get_term(self) -> SolarTerm:
"""
当时所在的节气
:return: 节气 SolarTerm
"""
term: SolarTerm = self.get_solar_day().get_term()
if self.is_before(term.get_julian_day().get_solar_time()):
term = term.next(-1)
return term
def get_phenology(self) -> Phenology:
"""
当时所在的候
:return: 候 Phenology
"""
p: Phenology = self.get_solar_day().get_phenology()
if self.is_before(p.get_julian_day().get_solar_time()):
p = p.next(-1)
return p
def get_julian_day(self) -> JulianDay:
"""
公历时刻转儒略日
:return: 儒略日
"""
return JulianDay.from_ymd_hms(self._year, self._month, self._day, self._hour, self._minute, self._second)
def subtract(self, target: SolarTime) -> int:
"""
公历时刻相减,获得相差秒数
:param target: 公历时刻
:return: 秒数
"""
days: int = self.get_solar_day().subtract(target.get_solar_day())
cs: int = self._hour * 3600 + self._minute * 60 + self._second
ts: int = target.get_hour() * 3600 + target.get_minute() * 60 + target.get_second()
seconds: int = cs - ts
if seconds < 0:
seconds += 86400
days -= 1
seconds += days * 86400
return seconds
def get_lunar_hour(self) -> LunarHour:
"""
农历时辰
:return: 农历时辰
"""
from tyme4py.lunar import LunarDay, LunarHour
d: LunarDay = self.get_solar_day().get_lunar_day()
return LunarHour(d.get_year(), d.get_month(), d.get_day(), self._hour, self._minute, self._second)
def get_sixty_cycle_hour(self) -> SixtyCycleHour:
"""
干支时辰
:return: 干支时辰
"""
from tyme4py.sixtycycle import SixtyCycleHour
return SixtyCycleHour.from_solar_time(self)
def get_phase(self) -> Phase:
"""
月相
:return: 月相 Phase
"""
month = self.get_lunar_hour().get_lunar_day().get_lunar_month().next(1)
p = Phase.from_index(month.get_year(), month.get_month_with_leap(), 0)
while p.get_solar_time().is_after(self):
p = p.next(-1)
return p
+92
View File
@@ -0,0 +1,92 @@
# -*- coding:utf-8 -*-
from __future__ import annotations
from abc import ABC
from typing import List
from tyme4py import AbstractTyme
class YearUnit(AbstractTyme, ABC):
"""年"""
def __init__(self, year: int):
self._year = year
def get_year(self) -> int:
return self._year
class MonthUnit(YearUnit, ABC):
"""月"""
def __init__(self, year: int, month: int):
super().__init__(year)
self._month = month
def get_month(self) -> int:
return self._month
class DayUnit(MonthUnit, ABC):
"""日"""
def __init__(self, year: int, month: int, day: int):
super().__init__(year, month)
self._day = day
def get_day(self) -> int:
return self._day
class SecondUnit(DayUnit, ABC):
"""秒"""
def __init__(self, year: int, month: int, day: int, hour: int, minute: int, second: int):
super().__init__(year, month, day)
self._hour = hour
self._minute = minute
self._second = second
def get_hour(self) -> int:
return self._hour
def get_minute(self) -> int:
return self._minute
def get_second(self) -> int:
return self._second
@staticmethod
def validate(year: int, month: int, day: int, hour: int, minute: int, second: int) -> None:
if hour < 0 or hour > 23:
raise ValueError(f'illegal hour: {hour}')
if minute < 0 or minute > 59:
raise ValueError(f'illegal minute: {minute}')
if second < 0 or second > 59:
raise ValueError(f'illegal second: {second}')
class WeekUnit(MonthUnit, ABC):
"""周"""
NAMES: List[str] = ['第一周', '第二周', '第三周', '第四周', '第五周', '第六周']
"""名称"""
def __init__(self, year: int, month: int, index: int, start: int):
super().__init__(year, month)
self._index = index
self._start = start
def get_index(self) -> int:
return self._index
def get_start(self) -> int:
return self._start
@staticmethod
def validate(year: int, month: int, index: int, start: int) -> None:
if index < 0 or index > 5:
raise ValueError(f'illegal week index: {index}')
if start < 0 or start > 6:
raise ValueError(f'illegal week start: {start}')
+842
View File
@@ -0,0 +1,842 @@
# -*- coding:utf-8 -*-
from math import floor, cos, sin
class ShouXingUtil:
# 2000年儒略日数(2000-1-1 12:00:00 UTC)
J2000 = 2451545
PI: float = 3.141592653589793
PI_2: float = 2 * PI
ONE_THIRD: float = 1.0 / 3
# 1天对应的秒数
SECOND_PER_DAY: int = 86400
# 1弧度对应的角秒
SECOND_PER_RAD: float = 648000 / PI
# 中精度章动计算表
__NUT_B = (
2.1824, -33.75705, 36e-6, -1720, 920,
3.5069, 1256.66393, 11e-6, -132, 57,
1.3375, 16799.4182, -51e-6, -23, 10,
4.3649, -67.5141, 72e-6, 21, -9,
0.04, -628.302, 0, -14, 0,
2.36, 8328.691, 0, 7, 0,
3.46, 1884.966, 0, -5, 2,
5.44, 16833.175, 0, -4, 2,
3.69, 25128.110, 0, -3, 0,
3.55, 628.362, 0, 2, 0
)
# TD - UT1 计算表
__DT_AT = (
-4000, 108371.7, -13036.80, 392.000, 0.0000,
-500, 17201.0, -627.82, 16.170, -0.3413,
-150, 12200.6, -346.41, 5.403, -0.1593,
150, 9113.8, -328.13, -1.647, 0.0377,
500, 5707.5, -391.41, 0.915, 0.3145,
900, 2203.4, -283.45, 13.034, -0.1778,
1300, 490.1, -57.35, 2.085, -0.0072,
1600, 120.0, -9.81, -1.532, 0.1403,
1700, 10.2, -0.91, 0.510, -0.0370,
1800, 13.4, -0.72, 0.202, -0.0193,
1830, 7.8, -1.81, 0.416, -0.0247,
1860, 8.3, -0.13, -0.406, 0.0292,
1880, -5.4, 0.32, -0.183, 0.0173,
1900, -2.3, 2.06, 0.169, -0.0135,
1920, 21.2, 1.69, -0.304, 0.0167,
1940, 24.2, 1.22, -0.064, 0.0031,
1960, 33.2, 0.51, 0.231, -0.0109,
1980, 51.0, 1.29, -0.026, 0.0032,
2000, 63.87, 0.1, 0, 0,
2005, 64.7, 0.21, 0, 0,
2012, 66.8, 0.22, 0, 0,
2016, 68.1024, 0.5456, -0.0542, -0.001172,
2020, 69.3612, 0.0422, -0.0502, 0.006216,
2024, 69.1752, -0.0335, -0.0048, 0.000811,
2028, 69.0206, -0.0275, 0.0055, -0.000014,
2032, 68.9981, 0.0163, 0.0054, 0.000006,
2036, 69.1498, 0.0599, 0.0053, 0.000026,
2040, 69.4751, 0.1035, 0.0051, 0.000046,
2044, 69.9737, 0.1469, 0.0050, 0.000066,
2048, 70.6451, 0.1903, 0.0049, 0.000085,
2050, 71.0457
)
__XL0 = (
10000000000,
20, 578, 920, 1100, 1124, 1136, 1148, 1217, 1226, 1229, 1229, 1229, 1229, 1937, 2363, 2618, 2633, 2660, 2666,
17534704567, 0.00000000000, 0.00000000000, 334165646, 4.669256804, 6283.075849991, 3489428, 4.6261024,
12566.1517000, 349706, 2.744118, 5753.384885, 341757, 2.828866, 3.523118, 313590, 3.627670, 77713.771468,
267622, 4.418084, 7860.419392, 234269, 6.135162, 3930.209696, 132429, 0.742464, 11506.769770, 127317, 2.037097,
529.690965, 119917, 1.109629, 1577.343542, 99025, 5.23268, 5884.92685, 90186, 2.04505, 26.29832, 85722, 3.50849,
398.14900, 77979, 1.17883, 5223.69392, 75314, 2.53339, 5507.55324, 50526, 4.58293, 18849.22755, 49238, 4.20507,
775.52261, 35666, 2.91954, 0.06731, 31709, 5.84902, 11790.62909, 28413, 1.89869, 796.29801, 27104, 0.31489,
10977.07880, 24281, 0.34481, 5486.77784, 20616, 4.80647, 2544.31442, 20539, 1.86948, 5573.14280, 20226, 2.45768,
6069.77675, 15552, 0.83306, 213.29910, 13221, 3.41118, 2942.46342, 12618, 1.08303, 20.77540, 11513, 0.64545,
0.98032, 10285, 0.63600, 4694.00295, 10190, 0.97569, 15720.83878, 10172, 4.26680, 7.11355, 9921, 6.2099,
2146.1654, 9761, 0.6810, 155.4204, 8580, 5.9832, 161000.6857, 8513, 1.2987, 6275.9623, 8471, 3.6708, 71430.6956,
7964, 1.8079, 17260.1547, 7876, 3.0370, 12036.4607, 7465, 1.7551, 5088.6288, 7387, 3.5032, 3154.6871, 7355,
4.6793, 801.8209, 6963, 0.8330, 9437.7629, 6245, 3.9776, 8827.3903, 6115, 1.8184, 7084.8968, 5696, 2.7843,
6286.5990, 5612, 4.3869, 14143.4952, 5558, 3.4701, 6279.5527, 5199, 0.1891, 12139.5535, 5161, 1.3328, 1748.0164,
5115, 0.2831, 5856.4777, 4900, 0.4874, 1194.4470, 4104, 5.3682, 8429.2413, 4094, 2.3985, 19651.0485, 3920,
6.1683, 10447.3878, 3677, 6.0413, 10213.2855, 3660, 2.5696, 1059.3819, 3595, 1.7088, 2352.8662, 3557, 1.7760,
6812.7668, 3329, 0.5931, 17789.8456, 3041, 0.4429, 83996.8473, 3005, 2.7398, 1349.8674, 2535, 3.1647, 4690.4798,
2474, 0.2148, 3.5904, 2366, 0.4847, 8031.0923, 2357, 2.0653, 3340.6124, 2282, 5.2220, 4705.7323, 2189, 5.5559,
553.5694, 2142, 1.4256, 16730.4637, 2109, 4.1483, 951.7184, 2030, 0.3713, 283.8593, 1992, 5.2221, 12168.0027,
1986, 5.7747, 6309.3742, 1912, 3.8222, 23581.2582, 1889, 5.3863, 149854.4001, 1790, 2.2149, 13367.9726, 1748,
4.5605, 135.0651, 1622, 5.9884, 11769.8537, 1508, 4.1957, 6256.7775, 1442, 4.1932, 242.7286, 1435, 3.7236,
38.0277, 1397, 4.4014, 6681.2249, 1362, 1.8893, 7632.9433, 1250, 1.1305, 5.5229, 1205, 2.6223, 955.5997, 1200,
1.0035, 632.7837, 1129, 0.1774, 4164.3120, 1083, 0.3273, 103.0928, 1052, 0.9387, 11926.2544, 1050, 5.3591,
1592.5960, 1033, 6.1998, 6438.4962, 1001, 6.0291, 5746.2713, 980, 0.999, 11371.705, 980, 5.244, 27511.468, 938,
2.624, 5760.498, 923, 0.483, 522.577, 922, 4.571, 4292.331, 905, 5.337, 6386.169, 862, 4.165, 7058.598, 841,
3.299, 7234.794, 836, 4.539, 25132.303, 813, 6.112, 4732.031, 812, 6.271, 426.598, 801, 5.821, 28.449, 787,
0.996, 5643.179, 776, 2.957, 23013.540, 769, 3.121, 7238.676, 758, 3.974, 11499.656, 735, 4.386, 316.392, 731,
0.607, 11513.883, 719, 3.998, 74.782, 706, 0.323, 263.084, 676, 5.911, 90955.552, 663, 3.665, 17298.182, 653,
5.791, 18073.705, 630, 4.717, 6836.645, 615, 1.458, 233141.314, 612, 1.075, 19804.827, 596, 3.321, 6283.009,
596, 2.876, 6283.143, 555, 2.452, 12352.853, 541, 5.392, 419.485, 531, 0.382, 31441.678, 519, 4.065, 6208.294,
513, 2.361, 10973.556, 494, 5.737, 9917.697, 450, 3.272, 11015.106, 449, 3.653, 206.186, 447, 2.064, 7079.374,
435, 4.423, 5216.580, 421, 1.906, 245.832, 413, 0.921, 3738.761, 402, 0.840, 20.355, 387, 1.826, 11856.219, 379,
2.344, 3.881, 374, 2.954, 3128.389, 370, 5.031, 536.805, 365, 1.018, 16200.773, 365, 1.083, 88860.057, 352,
5.978, 3894.182, 352, 2.056, 244287.600, 351, 3.713, 6290.189, 340, 1.106, 14712.317, 339, 0.978, 8635.942, 339,
3.202, 5120.601, 333, 0.837, 6496.375, 325, 3.479, 6133.513, 316, 5.089, 21228.392, 316, 1.328, 10873.986, 309,
3.646, 10.637, 303, 1.802, 35371.887, 296, 3.397, 9225.539, 288, 6.026, 154717.610, 281, 2.585, 14314.168, 262,
3.856, 266.607, 262, 2.579, 22483.849, 257, 1.561, 23543.231, 255, 3.949, 1990.745, 251, 3.744, 10575.407, 240,
1.161, 10984.192, 238, 0.106, 7.046, 236, 4.272, 6040.347, 234, 3.577, 10969.965, 211, 3.714, 65147.620, 210,
0.754, 13521.751, 207, 4.228, 5650.292, 202, 0.814, 170.673, 201, 4.629, 6037.244, 200, 0.381, 6172.870, 199,
3.933, 6206.810, 199, 5.197, 6262.300, 197, 1.046, 18209.330, 195, 1.070, 5230.807, 195, 4.869, 36.028, 194,
4.313, 6244.943, 192, 1.229, 709.933, 192, 5.595, 6282.096, 192, 0.602, 6284.056, 189, 3.744, 23.878, 188,
1.904, 15.252, 188, 0.867, 22003.915, 182, 3.681, 15110.466, 181, 0.491, 1.484, 179, 3.222, 39302.097, 179,
1.259, 12559.038,
62833196674749, 0.000000000000, 0.000000000000, 20605886, 2.67823456, 6283.07584999, 430343, 2.635127,
12566.151700, 42526, 1.59047, 3.52312, 11926, 5.79557, 26.29832, 10898, 2.96618, 1577.34354, 9348, 2.5921,
18849.2275, 7212, 1.1385, 529.6910, 6777, 1.8747, 398.1490, 6733, 4.4092, 5507.5532, 5903, 2.8880, 5223.6939,
5598, 2.1747, 155.4204, 4541, 0.3980, 796.2980, 3637, 0.4662, 775.5226, 2896, 2.6471, 7.1135, 2084, 5.3414,
0.9803, 1910, 1.8463, 5486.7778, 1851, 4.9686, 213.2991, 1729, 2.9912, 6275.9623, 1623, 0.0322, 2544.3144, 1583,
1.4305, 2146.1654, 1462, 1.2053, 10977.0788, 1246, 2.8343, 1748.0164, 1188, 3.2580, 5088.6288, 1181, 5.2738,
1194.4470, 1151, 2.0750, 4694.0030, 1064, 0.7661, 553.5694, 997, 1.303, 6286.599, 972, 4.239, 1349.867, 945,
2.700, 242.729, 858, 5.645, 951.718, 758, 5.301, 2352.866, 639, 2.650, 9437.763, 610, 4.666, 4690.480, 583,
1.766, 1059.382, 531, 0.909, 3154.687, 522, 5.661, 71430.696, 520, 1.854, 801.821, 504, 1.425, 6438.496, 433,
0.241, 6812.767, 426, 0.774, 10447.388, 413, 5.240, 7084.897, 374, 2.001, 8031.092, 356, 2.429, 14143.495, 350,
4.800, 6279.553, 337, 0.888, 12036.461, 337, 3.862, 1592.596, 325, 3.400, 7632.943, 322, 0.616, 8429.241, 318,
3.188, 4705.732, 297, 6.070, 4292.331, 295, 1.431, 5746.271, 290, 2.325, 20.355, 275, 0.935, 5760.498, 270,
4.804, 7234.794, 253, 6.223, 6836.645, 228, 5.003, 17789.846, 225, 5.672, 11499.656, 215, 5.202, 11513.883, 208,
3.955, 10213.286, 208, 2.268, 522.577, 206, 2.224, 5856.478, 206, 2.550, 25132.303, 203, 0.910, 6256.778, 189,
0.532, 3340.612, 188, 4.735, 83996.847, 179, 1.474, 4164.312, 178, 3.025, 5.523, 177, 3.026, 5753.385, 159,
4.637, 3.286, 157, 6.124, 5216.580, 155, 3.077, 6681.225, 154, 4.200, 13367.973, 143, 1.191, 3894.182, 138,
3.093, 135.065, 136, 4.245, 426.598, 134, 5.765, 6040.347, 128, 3.085, 5643.179, 127, 2.092, 6290.189, 125,
3.077, 11926.254, 125, 3.445, 536.805, 114, 3.244, 12168.003, 112, 2.318, 16730.464, 111, 3.901, 11506.770, 111,
5.320, 23.878, 105, 3.750, 7860.419, 103, 2.447, 1990.745, 96, 0.82, 3.88, 96, 4.08, 6127.66, 91, 5.42, 206.19,
91, 0.42, 7079.37, 88, 5.17, 11790.63, 81, 0.34, 9917.70, 80, 3.89, 10973.56, 78, 2.40, 1589.07, 78, 2.58,
11371.70, 77, 3.98, 955.60, 77, 3.36, 36.03, 76, 1.30, 103.09, 75, 5.18, 10969.97, 75, 4.96, 6496.37, 73, 5.21,
38.03, 72, 2.65, 6309.37, 70, 5.61, 3738.76, 69, 2.60, 3496.03, 69, 0.39, 15.25, 69, 2.78, 20.78, 65, 1.13,
7058.60, 64, 4.28, 28.45, 61, 5.63, 10984.19, 60, 0.73, 419.48, 60, 5.28, 10575.41, 58, 5.55, 17298.18, 58,
3.19, 4732.03,
5291887, 0.0000000, 0.0000000, 871984, 1.072097, 6283.075850, 30913, 0.86729, 12566.15170, 2734, 0.0530, 3.5231,
1633, 5.1883, 26.2983, 1575, 3.6846, 155.4204, 954, 0.757, 18849.228, 894, 2.057, 77713.771, 695, 0.827,
775.523, 506, 4.663, 1577.344, 406, 1.031, 7.114, 381, 3.441, 5573.143, 346, 5.141, 796.298, 317, 6.053,
5507.553, 302, 1.192, 242.729, 289, 6.117, 529.691, 271, 0.306, 398.149, 254, 2.280, 553.569, 237, 4.381,
5223.694, 208, 3.754, 0.980, 168, 0.902, 951.718, 153, 5.759, 1349.867, 145, 4.364, 1748.016, 134, 3.721,
1194.447, 125, 2.948, 6438.496, 122, 2.973, 2146.165, 110, 1.271, 161000.686, 104, 0.604, 3154.687, 100, 5.986,
6286.599, 92, 4.80, 5088.63, 89, 5.23, 7084.90, 83, 3.31, 213.30, 76, 3.42, 5486.78, 71, 6.19, 4690.48, 68,
3.43, 4694.00, 65, 1.60, 2544.31, 64, 1.98, 801.82, 61, 2.48, 10977.08, 50, 1.44, 6836.65, 49, 2.34, 1592.60,
46, 1.31, 4292.33, 46, 3.81, 149854.40, 43, 0.04, 7234.79, 40, 4.94, 7632.94, 39, 1.57, 71430.70, 38, 3.17,
6309.37, 35, 0.99, 6040.35, 35, 0.67, 1059.38, 31, 3.18, 2352.87, 31, 3.55, 8031.09, 30, 1.92, 10447.39, 30,
2.52, 6127.66, 28, 4.42, 9437.76, 28, 2.71, 3894.18, 27, 0.67, 25132.30, 26, 5.27, 6812.77, 25, 0.55, 6279.55,
23, 1.38, 4705.73, 22, 0.64, 6256.78, 20, 6.07, 640.88,
28923, 5.84384, 6283.07585, 3496, 0.0000, 0.0000, 1682, 5.4877, 12566.1517, 296, 5.196, 155.420, 129, 4.722,
3.523, 71, 5.30, 18849.23, 64, 5.97, 242.73, 40, 3.79, 553.57,
11408, 3.14159, 0.00000, 772, 4.134, 6283.076, 77, 3.84, 12566.15, 42, 0.42, 155.42,
88, 3.14, 0.00, 17, 2.77, 6283.08, 5, 2.01, 155.42, 3, 2.21, 12566.15,
27962, 3.19870, 84334.66158, 10164, 5.42249, 5507.55324, 8045, 3.8801, 5223.6939, 4381, 3.7044, 2352.8662, 3193,
4.0003, 1577.3435, 2272, 3.9847, 1047.7473, 1814, 4.9837, 6283.0758, 1639, 3.5646, 5856.4777, 1444, 3.7028,
9437.7629, 1430, 3.4112, 10213.2855, 1125, 4.8282, 14143.4952, 1090, 2.0857, 6812.7668, 1037, 4.0566,
71092.8814, 971, 3.473, 4694.003, 915, 1.142, 6620.890, 878, 4.440, 5753.385, 837, 4.993, 7084.897, 770, 5.554,
167621.576, 719, 3.602, 529.691, 692, 4.326, 6275.962, 558, 4.410, 7860.419, 529, 2.484, 4705.732, 521, 6.250,
18073.705,
903, 3.897, 5507.553, 618, 1.730, 5223.694, 380, 5.244, 2352.866,
166, 1.627, 84334.662,
10001398880, 0.00000000000, 0.00000000000, 167069963, 3.098463508, 6283.075849991, 1395602, 3.0552461,
12566.1517000, 308372, 5.198467, 77713.771468, 162846, 1.173877, 5753.384885, 157557, 2.846852, 7860.419392,
92480, 5.45292, 11506.76977, 54244, 4.56409, 3930.20970, 47211, 3.66100, 5884.92685, 34598, 0.96369, 5507.55324,
32878, 5.89984, 5223.69392, 30678, 0.29867, 5573.14280, 24319, 4.27350, 11790.62909, 21183, 5.84715, 1577.34354,
18575, 5.02194, 10977.07880, 17484, 3.01194, 18849.22755, 10984, 5.05511, 5486.77784, 9832, 0.8868, 6069.7768,
8650, 5.6896, 15720.8388, 8583, 1.2708, 161000.6857, 6490, 0.2725, 17260.1547, 6292, 0.9218, 529.6910, 5706,
2.0137, 83996.8473, 5574, 5.2416, 71430.6956, 4938, 3.2450, 2544.3144, 4696, 2.5781, 775.5226, 4466, 5.5372,
9437.7629, 4252, 6.0111, 6275.9623, 3897, 5.3607, 4694.0030, 3825, 2.3926, 8827.3903, 3749, 0.8295, 19651.0485,
3696, 4.9011, 12139.5535, 3566, 1.6747, 12036.4607, 3454, 1.8427, 2942.4634, 3319, 0.2437, 7084.8968, 3192,
0.1837, 5088.6288, 3185, 1.7778, 398.1490, 2846, 1.2134, 6286.5990, 2779, 1.8993, 6279.5527, 2628, 4.5890,
10447.3878, 2460, 3.7866, 8429.2413, 2393, 4.9960, 5856.4777, 2359, 0.2687, 796.2980, 2329, 2.8078, 14143.4952,
2210, 1.9500, 3154.6871, 2035, 4.6527, 2146.1654, 1951, 5.3823, 2352.8662, 1883, 0.6731, 149854.4001, 1833,
2.2535, 23581.2582, 1796, 0.1987, 6812.7668, 1731, 6.1520, 16730.4637, 1717, 4.4332, 10213.2855, 1619, 5.2316,
17789.8456, 1381, 5.1896, 8031.0923, 1364, 3.6852, 4705.7323, 1314, 0.6529, 13367.9726, 1041, 4.3329,
11769.8537, 1017, 1.5939, 4690.4798, 998, 4.201, 6309.374, 966, 3.676, 27511.468, 874, 6.064, 1748.016, 779,
3.674, 12168.003, 771, 0.312, 7632.943, 756, 2.626, 6256.778, 746, 5.648, 11926.254, 693, 2.924, 6681.225, 680,
1.423, 23013.540, 674, 0.563, 3340.612, 663, 5.661, 11371.705, 659, 3.136, 801.821, 648, 2.650, 19804.827, 615,
3.029, 233141.314, 612, 5.134, 1194.447, 563, 4.341, 90955.552, 552, 2.091, 17298.182, 534, 5.100, 31441.678,
531, 2.407, 11499.656, 523, 4.624, 6438.496, 513, 5.324, 11513.883, 477, 0.256, 11856.219, 461, 1.722, 7234.794,
458, 3.766, 6386.169, 458, 4.466, 5746.271, 423, 1.055, 5760.498, 422, 1.557, 7238.676, 415, 2.599, 7058.598,
401, 3.030, 1059.382, 397, 1.201, 1349.867, 379, 4.907, 4164.312, 360, 5.707, 5643.179, 352, 3.626, 244287.600,
348, 0.761, 10973.556, 342, 3.001, 4292.331, 336, 4.546, 4732.031, 334, 3.138, 6836.645, 324, 4.164, 9917.697,
316, 1.691, 11015.106, 307, 0.238, 35371.887, 298, 1.306, 6283.143, 298, 1.750, 6283.009, 293, 5.738, 16200.773,
286, 5.928, 14712.317, 281, 3.515, 21228.392, 280, 5.663, 8635.942, 277, 0.513, 26.298, 268, 4.207, 18073.705,
266, 0.900, 12352.853, 260, 2.962, 25132.303, 255, 2.477, 6208.294, 242, 2.800, 709.933, 231, 1.054, 22483.849,
229, 1.070, 14314.168, 216, 1.314, 154717.610, 215, 6.038, 10873.986, 200, 0.561, 7079.374, 198, 2.614, 951.718,
197, 4.369, 167283.762, 186, 2.861, 5216.580, 183, 1.660, 39302.097, 183, 5.912, 3738.761, 175, 2.145, 6290.189,
173, 2.168, 10575.407, 171, 3.702, 1592.596, 171, 1.343, 3128.389, 164, 5.550, 6496.375, 164, 5.856, 10984.192,
161, 1.998, 10969.965, 161, 1.909, 6133.513, 157, 4.955, 25158.602, 154, 6.216, 23543.231, 153, 5.357,
13521.751, 150, 5.770, 18209.330, 150, 5.439, 155.420, 139, 1.778, 9225.539, 139, 1.626, 5120.601, 128, 2.460,
13916.019, 123, 0.717, 143571.324, 122, 2.654, 88860.057, 121, 4.414, 3894.182, 121, 1.192, 3.523, 120, 4.030,
553.569, 119, 1.513, 17654.781, 117, 3.117, 14945.316, 113, 2.698, 6040.347, 110, 3.085, 43232.307, 109, 0.998,
955.600, 108, 2.939, 17256.632, 107, 5.285, 65147.620, 103, 0.139, 11712.955, 103, 5.850, 213.299, 102, 3.046,
6037.244, 101, 2.842, 8662.240, 100, 3.626, 6262.300, 98, 2.36, 6206.81, 98, 5.11, 6172.87, 98, 2.00, 15110.47,
97, 2.67, 5650.29, 97, 2.75, 6244.94, 96, 4.02, 6282.10, 96, 5.31, 6284.06, 92, 0.10, 29088.81, 85, 3.26,
20426.57, 84, 2.60, 28766.92, 81, 3.58, 10177.26, 80, 5.81, 5230.81, 78, 2.53, 16496.36, 77, 4.06, 6127.66, 73,
0.04, 5481.25, 72, 5.96, 12559.04, 72, 5.92, 4136.91, 71, 5.49, 22003.91, 70, 3.41, 7.11, 69, 0.62, 11403.68,
69, 3.90, 1589.07, 69, 1.96, 12416.59, 69, 4.51, 426.60, 67, 1.61, 11087.29, 66, 4.50, 47162.52, 66, 5.08,
283.86, 66, 4.32, 16858.48, 65, 1.04, 6062.66, 64, 1.59, 18319.54, 63, 5.70, 45892.73, 63, 4.60, 66567.49, 63,
3.82, 13517.87, 62, 2.62, 11190.38, 61, 1.54, 33019.02, 60, 5.58, 10344.30, 60, 5.38, 316428.23, 60, 5.78,
632.78, 59, 6.12, 9623.69, 57, 0.16, 17267.27, 57, 3.86, 6076.89, 57, 1.98, 7668.64, 56, 4.78, 20199.09, 55,
4.56, 18875.53, 55, 3.51, 17253.04, 54, 3.07, 226858.24, 54, 4.83, 18422.63, 53, 5.02, 12132.44, 52, 3.63,
5333.90, 52, 0.97, 155427.54, 51, 3.36, 20597.24, 50, 0.99, 11609.86, 50, 2.21, 1990.75, 48, 1.62, 12146.67, 48,
1.17, 12569.67, 47, 4.62, 5436.99, 47, 1.81, 12562.63, 47, 0.59, 21954.16, 47, 0.76, 7342.46, 46, 0.27, 4590.91,
46, 3.77, 156137.48, 45, 5.66, 10454.50, 44, 5.84, 3496.03, 43, 0.24, 17996.03, 41, 5.93, 51092.73, 41, 4.21,
12592.45, 40, 5.14, 1551.05, 40, 5.28, 15671.08, 39, 3.69, 18052.93, 39, 4.94, 24356.78, 38, 2.72, 11933.37, 38,
5.23, 7477.52, 38, 4.99, 9779.11, 37, 3.70, 9388.01, 37, 4.44, 4535.06, 36, 2.16, 28237.23, 36, 2.54, 242.73,
36, 0.22, 5429.88, 35, 6.15, 19800.95, 35, 2.92, 36949.23, 34, 5.63, 2379.16, 34, 5.73, 16460.33, 34, 5.11,
5849.36, 33, 6.19, 6268.85,
10301861, 1.10748970, 6283.07584999, 172124, 1.064423, 12566.151700, 70222, 3.14159, 0.00000, 3235, 1.0217,
18849.2275, 3080, 2.8435, 5507.5532, 2497, 1.3191, 5223.6939, 1849, 1.4243, 1577.3435, 1008, 5.9138, 10977.0788,
865, 1.420, 6275.962, 863, 0.271, 5486.778, 507, 1.686, 5088.629, 499, 6.014, 6286.599, 467, 5.987, 529.691,
440, 0.518, 4694.003, 410, 1.084, 9437.763, 387, 4.750, 2544.314, 375, 5.071, 796.298, 352, 0.023, 83996.847,
344, 0.949, 71430.696, 341, 5.412, 775.523, 322, 6.156, 2146.165, 286, 5.484, 10447.388, 284, 3.420, 2352.866,
255, 6.132, 6438.496, 252, 0.243, 398.149, 243, 3.092, 4690.480, 225, 3.689, 7084.897, 220, 4.952, 6812.767,
219, 0.420, 8031.092, 209, 1.282, 1748.016, 193, 5.314, 8429.241, 185, 1.820, 7632.943, 175, 3.229, 6279.553,
173, 1.537, 4705.732, 158, 4.097, 11499.656, 158, 5.539, 3154.687, 150, 3.633, 11513.883, 148, 3.222, 7234.794,
147, 3.653, 1194.447, 144, 0.817, 14143.495, 135, 6.151, 5746.271, 134, 4.644, 6836.645, 128, 2.693, 1349.867,
123, 5.650, 5760.498, 118, 2.577, 13367.973, 113, 3.357, 17789.846, 110, 4.497, 4292.331, 108, 5.828, 12036.461,
102, 5.621, 6256.778, 99, 1.14, 1059.38, 98, 0.66, 5856.48, 93, 2.32, 10213.29, 92, 0.77, 16730.46, 88, 1.50,
11926.25, 86, 1.42, 5753.38, 85, 0.66, 155.42, 81, 1.64, 6681.22, 80, 4.11, 951.72, 66, 4.55, 5216.58, 65, 0.98,
25132.30, 64, 4.19, 6040.35, 64, 0.52, 6290.19, 63, 1.51, 5643.18, 59, 6.18, 4164.31, 57, 2.30, 10973.56, 55,
2.32, 11506.77, 55, 2.20, 1592.60, 55, 5.27, 3340.61, 54, 5.54, 553.57, 53, 5.04, 9917.70, 53, 0.92, 11371.70,
52, 3.98, 17298.18, 52, 3.60, 10969.97, 49, 5.91, 3894.18, 49, 2.51, 6127.66, 48, 1.67, 12168.00, 46, 0.31,
801.82, 42, 3.70, 10575.41, 42, 4.05, 10984.19, 40, 2.17, 7860.42, 40, 4.17, 26.30, 38, 5.82, 7058.60, 37, 3.39,
6496.37, 36, 1.08, 6309.37, 36, 5.34, 7079.37, 34, 3.62, 11790.63, 32, 0.32, 16200.77, 31, 4.24, 3738.76, 29,
4.55, 11856.22, 29, 1.26, 8635.94, 27, 3.45, 5884.93, 26, 5.08, 10177.26, 26, 5.38, 21228.39, 24, 2.26,
11712.96, 24, 1.05, 242.73, 24, 5.59, 6069.78, 23, 3.63, 6284.06, 23, 1.64, 4732.03, 22, 3.46, 213.30, 21, 1.05,
3496.03, 21, 3.92, 13916.02, 21, 4.01, 5230.81, 20, 5.16, 12352.85, 20, 0.69, 1990.75, 19, 2.73, 6062.66, 19,
5.01, 11015.11, 18, 6.04, 6283.01, 18, 2.85, 7238.68, 18, 5.60, 6283.14, 18, 5.16, 17253.04, 18, 2.54, 14314.17,
17, 1.58, 7.11, 17, 0.98, 3930.21, 17, 4.75, 17267.27, 16, 2.19, 6076.89, 16, 2.19, 18073.70, 16, 6.12, 3.52,
16, 4.61, 9623.69, 16, 3.40, 16496.36, 15, 0.19, 9779.11, 15, 5.30, 13517.87, 15, 4.26, 3128.39, 15, 0.81,
709.93, 14, 0.50, 25158.60, 14, 4.38, 4136.91, 13, 0.98, 65147.62, 13, 3.31, 154717.61, 13, 2.11, 1589.07, 13,
1.92, 22483.85, 12, 6.03, 9225.54, 12, 1.53, 12559.04, 12, 5.82, 6282.10, 12, 5.61, 5642.20, 12, 2.38,
167283.76, 12, 0.39, 12132.44, 12, 3.98, 4686.89, 12, 5.81, 12569.67, 12, 0.56, 5849.36, 11, 0.45, 6172.87, 11,
5.80, 16858.48, 11, 6.22, 12146.67, 11, 2.27, 5429.88,
435939, 5.784551, 6283.075850, 12363, 5.57935, 12566.15170, 1234, 3.1416, 0.0000, 879, 3.628, 77713.771, 569,
1.870, 5573.143, 330, 5.470, 18849.228, 147, 4.480, 5507.553, 110, 2.842, 161000.686, 101, 2.815, 5223.694, 85,
3.11, 1577.34, 65, 5.47, 775.52, 61, 1.38, 6438.50, 50, 4.42, 6286.60, 47, 3.66, 7084.90, 46, 5.39, 149854.40,
42, 0.90, 10977.08, 40, 3.20, 5088.63, 35, 1.81, 5486.78, 32, 5.35, 3154.69, 30, 3.52, 796.30, 29, 4.62,
4690.48, 28, 1.84, 4694.00, 27, 3.14, 71430.70, 27, 6.17, 6836.65, 26, 1.42, 2146.17, 25, 2.81, 1748.02, 24,
2.18, 155.42, 23, 4.76, 7234.79, 21, 3.38, 7632.94, 21, 0.22, 4705.73, 20, 4.22, 1349.87, 20, 2.01, 1194.45, 20,
4.58, 529.69, 19, 1.59, 6309.37, 18, 5.70, 6040.35, 18, 6.03, 4292.33, 17, 2.90, 9437.76, 17, 2.00, 8031.09, 17,
5.78, 83996.85, 16, 0.05, 2544.31, 15, 0.95, 6127.66, 14, 0.36, 10447.39, 14, 1.48, 2352.87, 13, 0.77, 553.57,
13, 5.48, 951.72, 13, 5.27, 6279.55, 13, 3.76, 6812.77, 11, 5.41, 6256.78, 10, 0.68, 1592.60, 10, 4.95, 398.15,
10, 1.15, 3894.18, 10, 5.20, 244287.60, 10, 1.94, 11856.22, 9, 5.39, 25132.30, 8, 6.18, 1059.38, 8, 0.69,
8429.24, 8, 5.85, 242.73, 7, 5.26, 14143.50, 7, 0.52, 801.82, 6, 2.24, 8635.94, 6, 4.00, 13367.97, 6, 2.77,
90955.55, 6, 5.17, 7058.60, 5, 1.46, 233141.31, 5, 4.13, 7860.42, 5, 3.91, 26.30, 5, 3.89, 12036.46, 5, 5.58,
6290.19, 5, 5.54, 1990.75, 5, 0.83, 11506.77, 5, 6.22, 6681.22, 4, 5.26, 10575.41, 4, 1.91, 7477.52, 4, 0.43,
10213.29, 4, 1.09, 709.93, 4, 5.09, 11015.11, 4, 4.22, 88860.06, 4, 3.57, 7079.37, 4, 1.98, 6284.06, 4, 3.93,
10973.56, 4, 6.18, 9917.70, 4, 0.36, 10177.26, 4, 2.75, 3738.76, 4, 3.33, 5643.18, 4, 5.36, 25158.60,
14459, 4.27319, 6283.07585, 673, 3.917, 12566.152, 77, 0.00, 0.00, 25, 3.73, 18849.23, 4, 2.80, 6286.60,
386, 2.564, 6283.076, 31, 2.27, 12566.15, 5, 3.44, 5573.14, 2, 2.05, 18849.23, 1, 2.06, 77713.77, 1, 4.41,
161000.69, 1, 3.82, 149854.40, 1, 4.08, 6127.66, 1, 5.26, 6438.50,
9, 1.22, 6283.08, 1, 0.66, 12566.15
)
__XL1 = (
(22639.586, 0.78475822, 8328.691424623, 1.5229241, 25.0719, -0.123598, 4586.438, 0.1873974, 7214.06286536,
-2.184756, -18.860, 0.08280, 2369.914, 2.5429520, 15542.75428998, -0.661832, 6.212, -0.04080, 769.026,
3.140313, 16657.38284925, 3.04585, 50.144, -0.2472, 666.418, 1.527671, 628.30195521, -0.02664, 0.062, -0.0054,
411.596, 4.826607, 16866.9323150, -1.28012, -1.07, -0.0059, 211.656, 4.115028, -1114.6285593, -3.70768, -43.93,
0.2064, 205.436, 0.230523, 6585.7609101, -2.15812, -18.92, 0.0882, 191.956, 4.898507, 23871.4457146, 0.86109,
31.28, -0.164, 164.729, 2.586078, 14914.4523348, -0.6352, 6.15, -0.035, 147.321, 5.45530, -7700.3894694,
-1.5496, -25.01, 0.118, 124.988, 0.48608, 7771.3771450, -0.3309, 3.11, -0.020, 109.380, 3.88323, 8956.9933798,
1.4963, 25.13, -0.129, 55.177, 5.57033, -1324.1780250, 0.6183, 7.3, -0.035, 45.100, 0.89898, 25195.623740,
0.2428, 24.0, -0.129, 39.533, 3.81213, -8538.240890, 2.8030, 26.1, -0.118, 38.430, 4.30115, 22756.817155,
-2.8466, -12.6, 0.042, 36.124, 5.49587, 24986.074274, 4.5688, 75.2, -0.371, 30.773, 1.94559, 14428.125731,
-4.3695, -37.7, 0.166, 28.397, 3.28586, 7842.364821, -2.2114, -18.8, 0.077, 24.358, 5.64142, 16171.056245,
-0.6885, 6.3, -0.046, 18.585, 4.41371, -557.314280, -1.8538, -22.0, 0.10, 17.954, 3.58454, 8399.679100,
-0.3576, 3.2, -0.03, 14.530, 4.9416, 23243.143759, 0.888, 31.2, -0.16, 14.380, 0.9709, 32200.137139, 2.384,
56.4, -0.29, 14.251, 5.7641, -2.301200, 1.523, 25.1, -0.12, 13.899, 0.3735, 31085.508580, -1.324, 12.4, -0.08,
13.194, 1.7595, -9443.319984, -5.231, -69.0, 0.33, 9.679, 3.0997, -16029.080894, -3.072, -50.1, 0.24, 9.366,
0.3016, 24080.995180, -3.465, -19.9, 0.08, 8.606, 4.1582, -1742.930514, -3.681, -44.0, 0.21, 8.453, 2.8416,
16100.068570, 1.192, 28.2, -0.14, 8.050, 2.6292, 14286.150380, -0.609, 6.1, -0.03, 7.630, 6.2388, 17285.684804,
3.019, 50.2, -0.25, 7.447, 1.4845, 1256.603910, -0.053, 0.1, -0.01, 7.371, 0.2736, 5957.458955, -2.131, -19.0,
0.09, 7.063, 5.6715, 33.757047, -0.308, -3.6, 0.02, 6.383, 4.7843, 7004.513400, 2.141, 32.4, -0.16, 5.742,
2.6572, 32409.686605, -1.942, 5, -0.05, 4.374, 4.3443, 22128.51520, -2.820, -13, 0.05, 3.998, 3.2545,
33524.31516, 1.766, 49, -0.25, 3.210, 2.2443, 14985.44001, -2.516, -16, 0.06, 2.915, 1.7138, 24499.74767,
0.834, 31, -0.17, 2.732, 1.9887, 13799.82378, -4.343, -38, 0.17, 2.568, 5.4122, -7072.08751, -1.576, -25, 0.11,
2.521, 3.2427, 8470.66678, -2.238, -19, 0.07, 2.489, 4.0719, -486.32660, -3.734, -44, 0.20, 2.146, 5.6135,
-1952.47998, 0.645, 7, -0.03, 1.978, 2.7291, 39414.20000, 0.199, 37, -0.21, 1.934, 1.5682, 33314.76570, 6.092,
100, -0.5, 1.871, 0.4166, 30457.20662, -1.297, 12, -0.1, 1.753, 2.0582, -8886.00570, -3.38, -47, 0.2, 1.437,
2.386, -695.87607, 0.59, 7, 0, 1.373, 3.026, -209.54947, 4.33, 51, -0.2, 1.262, 5.940, 16728.37052, 1.17, 28,
-0.1, 1.224, 6.172, 6656.74859, -4.04, -41, 0.2, 1.187, 5.873, 6099.43431, -5.89, -63, 0.3, 1.177, 1.014,
31571.83518, 2.41, 56, -0.3, 1.162, 3.840, 9585.29534, 1.47, 25, -0.1, 1.143, 5.639, 8364.73984, -2.18, -19,
0.1, 1.078, 1.229, 70.98768, -1.88, -22, 0.1, 1.059, 3.326, 40528.82856, 3.91, 81, -0.4, 0.990, 5.013,
40738.37803, -0.42, 30, -0.2, 0.948, 5.687, -17772.01141, -6.75, -94, 0.5, 0.876, 0.298, -0.35232, 0, 0, 0,
0.822, 2.994, 393.02097, 0, 0, 0, 0.788, 1.836, 8326.39022, 3.05, 50, -0.2, 0.752, 4.985, 22614.84180, 0.91,
31, -0.2, 0.740, 2.875, 8330.99262, 0, 0, 0, 0.669, 0.744, -24357.77232, -4.60, -75, 0.4, 0.644, 1.314,
8393.12577, -2.18, -19, 0.1, 0.639, 5.888, 575.33849, 0, 0, 0, 0.635, 1.116, 23385.11911, -2.87, -13, 0, 0.584,
5.197, 24428.75999, 2.71, 53, -0.3, 0.583, 3.513, -9095.55517, 0.95, 4, 0, 0.572, 6.059, 29970.88002, -5.03,
-32, 0.1, 0.565, 2.960, 0.32863, 1.52, 25, -0.1, 0.561, 4.001, -17981.56087, -2.43, -43, 0.2, 0.557, 0.529,
7143.07519, -0.30, 3, 0, 0.546, 2.311, 25614.37623, 4.54, 75, -0.4, 0.536, 4.229, 15752.30376, -4.99, -45, 0.2,
0.493, 3.316, -8294.9344, -1.83, -29, 0.1, 0.491, 1.744, 8362.4485, 1.21, 21, -0.1, 0.478, 1.803, -10071.6219,
-5.20, -69, 0.3, 0.454, 0.857, 15333.2048, 3.66, 57, -0.3, 0.445, 2.071, 8311.7707, -2.18, -19, 0.1, 0.426,
0.345, 23452.6932, -3.44, -20, 0.1, 0.420, 4.941, 33733.8646, -2.56, -2, 0, 0.413, 1.642, 17495.2343, -1.31,
-1, 0, 0.404, 1.458, 23314.1314, -0.99, 9, -0.1, 0.395, 2.132, 38299.5714, -3.51, -6, 0, 0.382, 2.700,
31781.3846, -1.92, 5, 0, 0.375, 4.827, 6376.2114, 2.17, 32, -0.2, 0.361, 3.867, 16833.1753, -0.97, 3, 0, 0.358,
5.044, 15056.4277, -4.40, -38, 0.2, 0.350, 5.157, -8257.7037, -3.40, -47, 0.2, 0.344, 4.233, 157.7344, 0, 0, 0,
0.340, 2.672, 13657.8484, -0.58, 6, 0, 0.329, 5.610, 41853.0066, 3.29, 74, -0.4, 0.325, 5.895, -39.8149, 0, 0,
0, 0.309, 4.387, 21500.2132, -2.79, -13, 0.1, 0.302, 1.278, 786.0419, 0, 0, 0, 0.302, 5.341, -24567.3218,
-0.27, -24, 0.1, 0.301, 1.045, 5889.8848, -1.57, -12, 0, 0.294, 4.201, -2371.2325, -3.65, -44, 0.2, 0.293,
3.704, 21642.1886, -6.55, -57, 0.2, 0.290, 4.069, 32828.4391, 2.36, 56, -0.3, 0.289, 3.472, 31713.8105, -1.35,
12, -0.1, 0.285, 5.407, -33.7814, 0.31, 4, 0, 0.283, 5.998, -16.9207, -3.71, -44, 0.2, 0.283, 2.772,
38785.8980, 0.23, 37, -0.2, 0.274, 5.343, 15613.7420, -2.54, -16, 0.1, 0.263, 3.997, 25823.9257, 0.22, 24,
-0.1, 0.254, 0.600, 24638.3095, -1.61, 2, 0, 0.253, 1.344, 6447.1991, 0.29, 10, -0.1, 0.250, 0.887, 141.9754,
-3.76, -44, 0.2, 0.247, 0.317, 5329.1570, -2.10, -19, 0.1, 0.245, 0.141, 36.0484, -3.71, -44, 0.2, 0.231,
2.287, 14357.1381, -2.49, -16, 0.1, 0.227, 5.158, 2.6298, 0, 0, 0, 0.219, 5.085, 47742.8914, 1.72, 63, -0.3,
0.211, 2.145, 6638.7244, -2.18, -19, 0.1, 0.201, 4.415, 39623.7495, -4.13, -14, 0, 0.194, 2.091, 588.4927, 0,
0, 0, 0.193, 3.057, -15400.7789, -3.10, -50, 0, 0.186, 5.598, 16799.3582, -0.72, 6, 0, 0.185, 3.886, 1150.6770,
0, 0, 0, 0.183, 1.619, 7178.0144, 1.52, 25, 0, 0.181, 2.635, 8328.3391, 1.52, 25, 0, 0.181, 2.077, 8329.0437,
1.52, 25, 0, 0.179, 3.215, -9652.8694, -0.90, -18, 0, 0.176, 1.716, -8815.0180, -5.26, -69, 0, 0.175, 5.673,
550.7553, 0, 0, 0, 0.170, 2.060, 31295.0580, -5.6, -39, 0, 0.167, 1.239, 7211.7617, -0.7, 6, 0, 0.165, 4.499,
14967.4158, -0.7, 6, 0, 0.164, 3.595, 15540.4531, 0.9, 31, 0, 0.164, 4.237, 522.3694, 0, 0, 0, 0.163, 4.633,
15545.0555, -2.2, -19, 0, 0.161, 0.478, 6428.0209, -2.2, -19, 0, 0.158, 2.03, 13171.5218, -4.3, -38, 0, 0.157,
2.28, 7216.3641, -3.7, -44, 0, 0.154, 5.65, 7935.6705, 1.5, 25, 0, 0.152, 0.46, 29828.9047, -1.3, 12, 0, 0.151,
1.19, -0.7113, 0, 0, 0, 0.150, 1.42, 23942.4334, -1.0, 9, 0, 0.144, 2.75, 7753.3529, 1.5, 25, 0, 0.137, 2.08,
7213.7105, -2.2, -19, 0, 0.137, 1.44, 7214.4152, -2.2, -19, 0, 0.136, 4.46, -1185.6162, -1.8, -22, 0, 0.136,
3.03, 8000.1048, -2.2, -19, 0, 0.134, 2.83, 14756.7124, -0.7, 6, 0, 0.131, 5.05, 6821.0419, -2.2, -19, 0,
0.128, 5.99, -17214.6971, -4.9, -72, 0, 0.127, 5.35, 8721.7124, 1.5, 25, 0, 0.126, 4.49, 46628.2629, -2.0, 19,
0, 0.125, 5.94, 7149.6285, 1.5, 25, 0, 0.124, 1.09, 49067.0695, 1.1, 55, 0, 0.121, 2.88, 15471.7666, 1.2, 28,
0, 0.111, 3.92, 41643.4571, 7.6, 125, -1, 0.110, 1.96, 8904.0299, 1.5, 25, 0, 0.106, 3.30, -18.0489, -2.2, -19,
0, 0.105, 2.30, -4.9310, 1.5, 25, 0, 0.104, 2.22, -6.5590, -1.9, -22, 0, 0.101, 1.44, 1884.9059, -0.1, 0, 0,
0.100, 5.92, 5471.1324, -5.9, -63, 0, 0.099, 1.12, 15149.7333, -0.7, 6, 0, 0.096, 4.73, 15508.9972, -0.4, 10,
0, 0.095, 5.18, 7230.9835, 1.5, 25, 0, 0.093, 3.37, 39900.5266, 3.9, 81, 0, 0.092, 2.01, 25057.0619, 2.7, 53,
0, 0.092, 1.21, -79.6298, 0, 0, 0, 0.092, 1.65, -26310.2523, -4.0, -68, 0, 0.091, 1.01, 42062.5561, -1.0, 23,
0, 0.090, 6.10, 29342.5781, -5.0, -32, 0, 0.090, 4.43, 15542.4020, -0.7, 6, 0, 0.090, 3.80, 15543.1066, -0.7,
6, 0, 0.089, 4.15, 6063.3859, -2.2, -19, 0, 0.086, 4.03, 52.9691, 0, 0, 0, 0.085, 0.49, 47952.4409, -2.6, 11,
0, 0.085, 1.60, 7632.8154, 2.1, 32, 0, 0.084, 0.22, 14392.0773, -0.7, 6, 0, 0.083, 6.22, 6028.4466, -4.0, -41,
0, 0.083, 0.63, -7909.9389, 2.8, 26, 0, 0.083, 5.20, -77.5523, 0, 0, 0, 0.082, 2.74, 8786.1467, -2.2, -19, 0,
0.080, 2.43, 9166.5428, -2.8, -26, 0, 0.080, 3.70, -25405.1732, 4.1, 27, 0, 0.078, 5.68, 48857.5200, 5.4, 106,
-1, 0.077, 1.85, 8315.5735, -2.2, -19, 0, 0.075, 5.46, -18191.1103, 1.9, 8, 0, 0.075, 1.41, -16238.6304, 1.3,
1, 0, 0.074, 5.06, 40110.0761, -0.4, 30, 0, 0.072, 2.10, 64.4343, -3.7, -44, 0, 0.071, 2.17, 37671.2695, -3.5,
-6, 0, 0.069, 1.71, 16693.4313, -0.7, 6, 0, 0.069, 3.33, -26100.7028, -8.3, -119, 1, 0.068, 1.09, 8329.4028,
1.5, 25, 0, 0.068, 3.62, 8327.9801, 1.5, 25, 0, 0.068, 2.41, 16833.1509, -1.0, 3, 0, 0.067, 3.40, 24709.2971,
-3.5, -20, 0, 0.067, 1.65, 8346.7156, -0.3, 3, 0, 0.066, 2.61, 22547.2677, 1.5, 39, 0, 0.066, 3.50, 15576.5113,
-1.0, 3, 0, 0.065, 5.76, 33037.9886, -2.0, 5, 0, 0.065, 4.58, 8322.1325, -0.3, 3, 0, 0.065, 6.20, 17913.9868,
3.0, 50, 0, 0.065, 1.50, 22685.8295, -1.0, 9, 0, 0.065, 2.37, 7180.3058, -1.9, -15, 0, 0.064, 1.06, 30943.5332,
2.4, 56, 0, 0.064, 1.89, 8288.8765, 1.5, 25, 0, 0.064, 4.70, 6.0335, 0.3, 4, 0, 0.063, 2.83, 8368.5063, 1.5,
25, 0, 0.063, 5.66, -2580.7819, 0.7, 7, 0, 0.062, 3.78, 7056.3285, -2.2, -19, 0, 0.061, 1.49, 8294.9100, 1.8,
29, 0, 0.061, 0.12, -10281.1714, -0.9, -18, 0, 0.061, 3.06, -8362.4729, -1.2, -21, 0, 0.061, 4.43, 8170.9571,
1.5, 25, 0, 0.059, 5.78, -13.1179, -3.7, -44, 0, 0.059, 5.97, 6625.5702, -2.2, -19, 0, 0.058, 5.01, -0.5080,
-0.3, 0, 0, 0.058, 2.73, 7161.0938, -2.2, -19, 0, 0.057, 0.19, 7214.0629, -2.2, -19, 0, 0.057, 4.00,
22199.5029, -4.7, -35, 0, 0.057, 5.38, 8119.1420, 5.8, 76, 0, 0.056, 1.07, 7542.6495, 1.5, 25, 0, 0.056, 0.28,
8486.4258, 1.5, 25, 0, 0.054, 4.19, 16655.0816, 4.6, 75, 0, 0.053, 0.72, 7267.0320, -2.2, -19, 0, 0.053, 3.12,
12.6192, 0.6, 7, 0, 0.052, 2.99, -32896.013, -1.8, -49, 0, 0.052, 3.46, 1097.708, 0, 0, 0, 0.051, 5.37,
-6443.786, -1.6, -25, 0, 0.051, 1.35, 7789.401, -2.2, -19, 0, 0.051, 5.83, 40042.502, 0.2, 38, 0, 0.051, 3.63,
9114.733, 1.5, 25, 0, 0.050, 1.51, 8504.484, -2.5, -22, 0, 0.050, 5.23, 16659.684, 1.5, 25, 0, 0.050, 1.15,
7247.820, -2.5, -23, 0, 0.047, 0.25, -1290.421, 0.3, 0, 0, 0.047, 4.67, -32686.464, -6.1, -100, 0, 0.047, 3.49,
548.678, 0, 0, 0, 0.047, 2.37, 6663.308, -2.2, -19, 0, 0.046, 0.98, 1572.084, 0, 0, 0, 0.046, 2.04, 14954.262,
-0.7, 6, 0, 0.046, 3.72, 6691.693, -2.2, -19, 0, 0.045, 6.19, -235.287, 0, 0, 0, 0.044, 2.96, 32967.001, -0.1,
27, 0, 0.044, 3.82, -1671.943, -5.6, -66, 0, 0.043, 5.82, 1179.063, 0, 0, 0, 0.043, 0.07, 34152.617, 1.7, 49,
0, 0.043, 3.71, 6514.773, -0.3, 0, 0, 0.043, 5.62, 15.732, -2.5, -23, 0, 0.043, 5.80, 8351.233, -2.2, -19, 0,
0.042, 0.27, 7740.199, 1.5, 25, 0, 0.042, 6.14, 15385.020, -0.7, 6, 0, 0.042, 6.13, 7285.051, -4.1, -41, 0,
0.041, 1.27, 32757.451, 4.2, 78, 0, 0.041, 4.46, 8275.722, 1.5, 25, 0, 0.040, 0.23, 8381.661, 1.5, 25, 0,
0.040, 5.87, -766.864, 2.5, 29, 0, 0.040, 1.66, 254.431, 0, 0, 0, 0.040, 0.40, 9027.981, -0.4, 0, 0, 0.040,
2.96, 7777.936, 1.5, 25, 0, 0.039, 4.67, 33943.068, 6.1, 100, 0, 0.039, 3.52, 8326.062, 1.5, 25, 0, 0.039,
3.75, 21013.887, -6.5, -57, 0, 0.039, 5.60, 606.978, 0, 0, 0, 0.039, 1.19, 8331.321, 1.5, 25, 0, 0.039, 2.84,
7211.433, -2.2, -19, 0, 0.038, 0.67, 7216.693, -2.2, -19, 0, 0.038, 6.22, 25161.867, 0.6, 28, 0, 0.038, 4.40,
7806.322, 1.5, 25, 0, 0.038, 4.16, 9179.168, -2.2, -19, 0, 0.037, 4.73, 14991.999, -0.7, 6, 0, 0.036, 0.35,
67.514, -0.6, -7, 0, 0.036, 3.70, 25266.611, -1.6, 0, 0, 0.036, 5.39, 16328.796, -0.7, 6, 0, 0.035, 1.44,
7174.248, -2.2, -19, 0, 0.035, 5.00, 15684.730, -4.4, -38, 0, 0.035, 0.39, -15.419, -2.2, -19, 0, 0.035, 6.07,
15020.385, -0.7, 6, 0, 0.034, 6.01, 7371.797, -2.2, -19, 0, 0.034, 0.96, -16623.626, -3.4, -54, 0, 0.033, 6.24,
9479.368, 1.5, 25, 0, 0.033, 3.21, 23661.896, 5.2, 82, 0, 0.033, 4.06, 8311.418, -2.2, -19, 0, 0.033, 2.40,
1965.105, 0, 0, 0, 0.033, 5.17, 15489.785, -0.7, 6, 0, 0.033, 5.03, 21986.540, 0.9, 31, 0, 0.033, 4.10,
16691.140, 2.7, 46, 0, 0.033, 5.13, 47114.589, 1.7, 63, 0, 0.033, 4.45, 8917.184, 1.5, 25, 0, 0.033, 4.23,
2.078, 0, 0, 0, 0.032, 2.33, 75.251, 1.5, 25, 0, 0.032, 2.10, 7253.878, -2.2, -19, 0, 0.032, 3.11, -0.224, 1.5,
25, 0, 0.032, 4.43, 16640.462, -0.7, 6, 0, 0.032, 5.68, 8328.363, 0, 0, 0, 0.031, 5.32, 8329.020, 3.0, 50, 0,
0.031, 3.70, 16118.093, -0.7, 6, 0, 0.030, 3.67, 16721.817, -0.7, 6, 0, 0.030, 5.27, -1881.492, -1.2, -15, 0,
0.030, 5.72, 8157.839, -2.2, -19, 0, 0.029, 5.73, -18400.313, -6.7, -94, 0, 0.029, 2.76, 16.000, -2.2, -19, 0,
0.029, 1.75, 8879.447, 1.5, 25, 0, 0.029, 0.32, 8851.061, 1.5, 25, 0, 0.029, 0.90, 14704.903, 3.7, 57, 0,
0.028, 2.90, 15595.723, -0.7, 6, 0, 0.028, 5.88, 16864.631, 0.2, 24, 0, 0.028, 0.63, 16869.234, -2.8, -26, 0,
0.028, 4.04, -18609.863, -2.4, -43, 0, 0.027, 5.83, 6727.736, -5.9, -63, 0, 0.027, 6.12, 418.752, 4.3, 51, 0,
0.027, 0.14, 41157.131, 3.9, 81, 0, 0.026, 3.80, 15.542, 0, 0, 0, 0.026, 1.68, 50181.698, 4.8, 99, -1, 0.026,
0.32, 315.469, 0, 0, 0, 0.025, 5.67, 19.188, 0.3, 0, 0, 0.025, 3.16, 62.133, -2.2, -19, 0, 0.025, 3.76,
15502.939, -0.7, 6, 0, 0.025, 4.53, 45999.961, -2.0, 19, 0, 0.024, 3.21, 837.851, -4.4, -51, 0, 0.024, 2.82,
38157.596, 0.3, 37, 0, 0.024, 5.21, 15540.124, -0.7, 6, 0, 0.024, 0.26, 14218.576, 0, 13, 0, 0.024, 3.01,
15545.384, -0.7, 6, 0, 0.024, 1.16, -17424.247, -0.6, -21, 0, 0.023, 2.34, -67.574, 0.6, 7, 0, 0.023, 2.44,
18.024, -1.9, -22, 0, 0.023, 3.70, 469.400, 0, 0, 0, 0.023, 0.72, 7136.511, -2.2, -19, 0, 0.023, 4.50,
15582.569, -0.7, 6, 0, 0.023, 2.80, -16586.395, -4.9, -72, 0, 0.023, 1.51, 80.182, 0, 0, 0, 0.023, 1.09,
5261.583, -1.5, -12, 0, 0.023, 0.56, 54956.954, -0.5, 44, 0, 0.023, 4.01, 8550.860, -2.2, -19, 0, 0.023, 4.46,
38995.448, -4.1, -14, 0, 0.023, 3.82, 2358.126, 0, 0, 0, 0.022, 3.77, 32271.125, 0.5, 34, 0, 0.022, 0.82,
15935.775, -0.7, 6, 0, 0.022, 1.07, 24013.421, -2.9, -13, 0, 0.022, 0.40, 8940.078, -2.2, -19, 0, 0.022, 2.06,
15700.489, -0.7, 6, 0, 0.022, 4.27, 15124.002, -5.0, -45, 0, 0.021, 1.16, 56071.583, 3.2, 88, 0, 0.021, 5.58,
9572.189, -2.2, -19, 0, 0.020, 1.70, -17.273, -3.7, -44, 0, 0.020, 3.05, 214.617, 0, 0, 0, 0.020, 4.41,
8391.048, -2.2, -19, 0, 0.020, 5.95, 23869.145, 2.4, 56, 0, 0.020, 0.42, 40947.927, -4.7, -21, 0, 0.019, 1.39,
5818.897, 0.3, 10, 0, 0.019, 0.71, 23873.747, -0.7, 6, 0, 0.019, 2.81, 7291.615, -2.2, -19, 0, 0.019, 5.09,
8428.018, -2.2, -19, 0, 0.019, 4.14, 6518.187, -1.6, -12, 0, 0.019, 3.85, 21.330, 0, 0, 0, 0.018, 0.66,
14445.046, -0.7, 6, 0, 0.018, 1.65, 0.966, -4.0, -48, 0, 0.018, 5.64, -17143.709, -6.8, -94, 0, 0.018, 6.01,
7736.432, -2.2, -19, 0, 0.018, 2.74, 31153.083, -1.9, 5, 0, 0.018, 4.58, 6116.355, -2.2, -19, 0, 0.018, 2.28,
46.401, 0.3, 0, 0, 0.018, 3.80, 10213.597, 1.4, 25, 0, 0.018, 2.84, 56281.132, -1.1, 36, 0, 0.018, 3.53,
8249.062, 1.5, 25, 0, 0.017, 4.43, 20871.911, -3, -13, 0, 0.017, 4.44, 627.596, 0, 0, 0, 0.017, 1.85, 628.308,
0, 0, 0, 0.017, 1.19, 8408.321, 2, 25, 0, 0.017, 1.95, 7214.056, -2, -19, 0, 0.017, 1.57, 7214.070, -2, -19, 0,
0.017, 1.65, 13870.811, -6, -60, 0, 0.017, 0.30, 22.542, -4, -44, 0, 0.017, 2.62, -119.445, 0, 0, 0, 0.016,
4.87, 5747.909, 2, 32, 0, 0.016, 4.45, 14339.108, -1, 6, 0, 0.016, 1.83, 41366.680, 0, 30, 0, 0.016, 4.53,
16309.618, -3, -23, 0, 0.016, 2.54, 15542.754, -1, 6, 0, 0.016, 6.05, 1203.646, 0, 0, 0, 0.015, 5.2, 2751.147,
0, 0, 0, 0.015, 1.8, -10699.924, -5, -69, 0, 0.015, 0.4, 22824.391, -3, -20, 0, 0.015, 2.1, 30666.756, -6, -39,
0, 0.015, 2.1, 6010.417, -2, -19, 0, 0.015, 0.7, -23729.470, -5, -75, 0, 0.015, 1.4, 14363.691, -1, 6, 0,
0.015, 5.8, 16900.689, -2, 0, 0, 0.015, 5.2, 23800.458, 3, 53, 0, 0.015, 5.3, 6035.000, -2, -19, 0, 0.015, 1.2,
8251.139, 2, 25, 0, 0.015, 3.6, -8.860, 0, 0, 0, 0.015, 0.8, 882.739, 0, 0, 0, 0.015, 3.0, 1021.329, 0, 0, 0,
0.015, 0.6, 23296.107, 1, 31, 0, 0.014, 5.4, 7227.181, 2, 25, 0, 0.014, 0.1, 7213.352, -2, -19, 0, 0.014, 4.0,
15506.706, 3, 50, 0, 0.014, 3.4, 7214.774, -2, -19, 0, 0.014, 4.6, 6665.385, -2, -19, 0, 0.014, 0.1, -8.636,
-2, -22, 0, 0.014, 3.1, 15465.202, -1, 6, 0, 0.014, 4.9, 508.863, 0, 0, 0, 0.014, 3.5, 8406.244, 2, 25, 0,
0.014, 1.3, 13313.497, -8, -82, 0, 0.014, 2.8, 49276.619, -3, 0, 0, 0.014, 0.1, 30528.194, -3, -10, 0, 0.013,
1.7, 25128.050, 1, 31, 0, 0.013, 2.9, 14128.405, -1, 6, 0, 0.013, 3.4, 57395.761, 3, 80, 0, 0.013, 2.7,
13029.546, -1, 6, 0, 0.013, 3.9, 7802.556, -2, -19, 0, 0.013, 1.6, 8258.802, -2, -19, 0, 0.013, 2.2, 8417.709,
-2, -19, 0, 0.013, 0.7, 9965.210, -2, -19, 0, 0.013, 3.4, 50391.247, 0, 48, 0, 0.013, 3.0, 7134.433, -2, -19,
0, 0.013, 2.9, 30599.182, -5, -31, 0, 0.013, 3.6, -9723.857, 1, 0, 0, 0.013, 4.8, 7607.084, -2, -19, 0, 0.012,
0.8, 23837.689, 1, 35, 0, 0.012, 3.6, 4.409, -4, -44, 0, 0.012, 5.0, 16657.031, 3, 50, 0, 0.012, 4.4,
16657.735, 3, 50, 0, 0.012, 1.1, 15578.803, -4, -38, 0, 0.012, 6.0, -11.490, 0, 0, 0, 0.012, 1.9, 8164.398, 0,
0, 0, 0.012, 2.4, 31852.372, -4, -17, 0, 0.012, 2.4, 6607.085, -2, -19, 0, 0.012, 4.2, 8359.870, 0, 0, 0,
0.012, 0.5, 5799.713, -2, -19, 0, 0.012, 2.7, 7220.622, 0, 0, 0, 0.012, 4.3, -139.720, 0, 0, 0, 0.012, 2.3,
13728.836, -2, -16, 0, 0.011, 3.6, 14912.146, 1, 31, 0, 0.011, 4.7, 14916.748, -2, -19, 0),
(1.67680, 4.66926, 628.301955, -0.0266, 0.1, -0.005, 0.51642, 3.3721, 6585.760910, -2.158, -18.9, 0.09, 0.41383,
5.7277, 14914.452335, -0.635, 6.2, -0.04, 0.37115, 3.9695, 7700.389469, 1.550, 25.0, -0.12, 0.27560, 0.7416,
8956.993380, 1.496, 25.1, -0.13, 0.24599, 4.2253, -2.301200, 1.523, 25.1, -0.12, 0.07118, 0.1443, 7842.36482,
-2.211, -19, 0.08, 0.06128, 2.4998, 16171.05625, -0.688, 6, 0, 0.04516, 0.443, 8399.67910, -0.36, 3, 0,
0.04048, 5.771, 14286.15038, -0.61, 6, 0, 0.03747, 4.626, 1256.60391, -0.05, 0, 0, 0.03707, 3.415, 5957.45895,
-2.13, -19, 0.1, 0.03649, 1.800, 23243.14376, 0.89, 31, -0.2, 0.02438, 0.042, 16029.08089, 3.07, 50, -0.2,
0.02165, 1.017, -1742.93051, -3.68, -44, 0.2, 0.01923, 3.097, 17285.68480, 3.02, 50, -0.3, 0.01692, 1.280,
0.3286, 1.52, 25, -0.1, 0.01361, 0.298, 8326.3902, 3.05, 50, -0.2, 0.01293, 4.013, 7072.0875, 1.58, 25, -0.1,
0.01276, 4.413, 8330.9926, 0, 0, 0, 0.01270, 0.101, 8470.6668, -2.24, -19, 0.1, 0.01097, 1.203, 22128.5152,
-2.82, -13, 0, 0.01088, 2.545, 15542.7543, -0.66, 6, 0, 0.00835, 0.190, 7214.0629, -2.18, -19, 0.1, 0.00734,
4.855, 24499.7477, 0.83, 31, -0.2, 0.00686, 5.130, 13799.8238, -4.34, -38, 0.2, 0.00631, 0.930, -486.3266,
-3.73, -44, 0, 0.00585, 0.699, 9585.2953, 1.5, 25, 0, 0.00566, 4.073, 8328.3391, 1.5, 25, 0, 0.00566, 0.638,
8329.0437, 1.5, 25, 0, 0.00539, 2.472, -1952.4800, 0.6, 7, 0, 0.00509, 2.88, -0.7113, 0, 0, 0, 0.00469, 3.56,
30457.2066, -1.3, 12, 0, 0.00387, 0.78, -0.3523, 0, 0, 0, 0.00378, 1.84, 22614.8418, 0.9, 31, 0, 0.00362, 5.53,
-695.8761, 0.6, 7, 0, 0.00317, 2.80, 16728.3705, 1.2, 28, 0, 0.00303, 6.07, 157.7344, 0, 0, 0, 0.00300, 2.53,
33.7570, -0.3, -4, 0, 0.00295, 4.16, 31571.8352, 2.4, 56, 0, 0.00289, 5.98, 7211.7617, -0.7, 6, 0, 0.00285,
2.06, 15540.4531, 0.9, 31, 0, 0.00283, 2.65, 2.6298, 0, 0, 0, 0.00282, 6.17, 15545.0555, -2.2, -19, 0, 0.00278,
1.23, -39.8149, 0, 0, 0, 0.00272, 3.82, 7216.3641, -3.7, -44, 0, 0.00270, 4.37, 70.9877, -1.9, -22, 0, 0.00256,
5.81, 13657.8484, -0.6, 6, 0, 0.00244, 5.64, -0.2237, 1.5, 25, 0, 0.00240, 2.96, 8311.7707, -2.2, -19, 0,
0.00239, 0.87, -33.7814, 0.3, 4, 0, 0.00216, 2.31, 15.9995, -2.2, -19, 0, 0.00186, 3.46, 5329.1570, -2.1, -19,
0, 0.00169, 2.40, 24357.772, 4.6, 75, 0, 0.00161, 5.80, 8329.403, 1.5, 25, 0, 0.00161, 5.20, 8327.980, 1.5, 25,
0, 0.00160, 4.26, 23385.119, -2.9, -13, 0, 0.00156, 1.26, 550.755, 0, 0, 0, 0.00155, 1.25, 21500.213, -2.8,
-13, 0, 0.00152, 0.60, -16.921, -3.7, -44, 0, 0.00150, 2.71, -79.630, 0, 0, 0, 0.00150, 5.29, 15.542, 0, 0, 0,
0.00148, 1.06, -2371.232, -3.7, -44, 0, 0.00141, 0.77, 8328.691, 1.5, 25, 0, 0.00141, 3.67, 7143.075, -0.3, 0,
0, 0.00138, 5.45, 25614.376, 4.5, 75, 0, 0.00129, 4.90, 23871.446, 0.9, 31, 0, 0.00126, 4.03, 141.975, -3.8,
-44, 0, 0.00124, 6.01, 522.369, 0, 0, 0, 0.00120, 4.94, -10071.622, -5.2, -69, 0, 0.00118, 5.07, -15.419, -2.2,
-19, 0, 0.00107, 3.49, 23452.693, -3.4, -20, 0, 0.00104, 4.78, 17495.234, -1.3, 0, 0, 0.00103, 1.44, -18.049,
-2.2, -19, 0, 0.00102, 5.63, 15542.402, -0.7, 6, 0, 0.00102, 2.59, 15543.107, -0.7, 6, 0, 0.00100, 4.11,
-6.559, -1.9, -22, 0, 0.00097, 0.08, 15400.779, 3.1, 50, 0, 0.00096, 5.84, 31781.385, -1.9, 5, 0, 0.00094,
1.08, 8328.363, 0, 0, 0, 0.00094, 2.46, 16799.358, -0.7, 6, 0, 0.00094, 1.69, 6376.211, 2.2, 32, 0, 0.00093,
3.64, 8329.020, 3.0, 50, 0, 0.00093, 2.65, 16655.082, 4.6, 75, 0, 0.00090, 1.90, 15056.428, -4.4, -38, 0,
0.00089, 1.59, 52.969, 0, 0, 0, 0.00088, 2.02, -8257.704, -3.4, -47, 0, 0.00088, 3.02, 7213.711, -2.2, -19, 0,
0.00087, 0.50, 7214.415, -2.2, -19, 0, 0.00087, 0.49, 16659.684, 1.5, 25, 0, 0.00082, 5.64, -4.931, 1.5, 25, 0,
0.00079, 5.17, 13171.522, -4.3, -38, 0, 0.00076, 3.60, 29828.905, -1.3, 12, 0, 0.00076, 4.08, 24567.322, 0.3,
24, 0, 0.00076, 4.58, 1884.906, -0.1, 0, 0, 0.00073, 0.33, 31713.811, -1.4, 12, 0, 0.00073, 0.93, 32828.439,
2.4, 56, 0, 0.00071, 5.91, 38785.898, 0.2, 37, 0, 0.00069, 2.20, 15613.742, -2.5, -16, 0, 0.00066, 3.87,
15.732, -2.5, -23, 0, 0.00066, 0.86, 25823.926, 0.2, 24, 0, 0.00065, 2.52, 8170.957, 1.5, 25, 0, 0.00063, 0.18,
8322.132, -0.3, 0, 0, 0.00060, 5.84, 8326.062, 1.5, 25, 0, 0.00060, 5.15, 8331.321, 1.5, 25, 0, 0.00060, 2.18,
8486.426, 1.5, 25, 0, 0.00058, 2.30, -1.731, -4, -44, 0, 0.00058, 5.43, 14357.138, -2, -16, 0, 0.00057, 3.09,
8294.910, 2, 29, 0, 0.00057, 4.67, -8362.473, -1, -21, 0, 0.00056, 4.15, 16833.151, -1, 0, 0, 0.00054, 1.93,
7056.329, -2, -19, 0, 0.00054, 5.27, 8315.574, -2, -19, 0, 0.00052, 5.6, 8311.418, -2, -19, 0, 0.00052, 2.7,
-77.552, 0, 0, 0, 0.00051, 4.3, 7230.984, 2, 25, 0, 0.00050, 0.4, -0.508, 0, 0, 0, 0.00049, 5.4, 7211.433, -2,
-19, 0, 0.00049, 4.4, 7216.693, -2, -19, 0, 0.00049, 4.3, 16864.631, 0, 24, 0, 0.00049, 2.2, 16869.234, -3,
-26, 0, 0.00047, 6.1, 627.596, 0, 0, 0, 0.00047, 5.0, 12.619, 1, 7, 0, 0.00045, 4.9, -8815.018, -5, -69, 0,
0.00044, 1.6, 62.133, -2, -19, 0, 0.00042, 2.9, -13.118, -4, -44, 0, 0.00042, 4.1, -119.445, 0, 0, 0, 0.00041,
4.3, 22756.817, -3, -13, 0, 0.00041, 3.6, 8288.877, 2, 25, 0, 0.00040, 0.5, 6663.308, -2, -19, 0, 0.00040, 1.1,
8368.506, 2, 25, 0, 0.00039, 4.1, 6443.786, 2, 25, 0, 0.00039, 3.1, 16657.383, 3, 50, 0, 0.00038, 0.1,
16657.031, 3, 50, 0, 0.00038, 3.0, 16657.735, 3, 50, 0, 0.00038, 4.6, 23942.433, -1, 9, 0, 0.00037, 4.3,
15385.020, -1, 6, 0, 0.00037, 5.0, 548.678, 0, 0, 0, 0.00036, 1.8, 7213.352, -2, -19, 0, 0.00036, 1.7,
7214.774, -2, -19, 0, 0.00035, 1.1, 7777.936, 2, 25, 0, 0.00035, 1.6, -8.860, 0, 0, 0, 0.00035, 4.4, 23869.145,
2, 56, 0, 0.00035, 2.0, 6691.693, -2, -19, 0, 0.00034, 1.3, -1185.616, -2, -22, 0, 0.00034, 2.2, 23873.747, -1,
6, 0, 0.00033, 2.0, -235.287, 0, 0, 0, 0.00033, 3.1, 17913.987, 3, 50, 0, 0.00033, 1.0, 8351.233, -2, -19, 0),
(0.004870, 4.6693, 628.30196, -0.027, 0, -0.01, 0.002280, 2.6746, -2.30120, 1.523, 25, -0.12, 0.001500, 3.372,
6585.76091, -2.16, -19, 0.1, 0.001200, 5.728, 14914.45233, -0.64, 6, 0, 0.001080, 3.969, 7700.38947, 1.55, 25,
-0.1, 0.000800, 0.742, 8956.99338, 1.50, 25, -0.1, 0.000254, 6.002, 0.3286, 1.52, 25, -0.1, 0.000210, 0.144,
7842.3648, -2.21, -19, 0, 0.000180, 2.500, 16171.0562, -0.7, 6, 0, 0.000130, 0.44, 8399.6791, -0.4, 3, 0,
0.000126, 5.03, 8326.3902, 3.0, 50, 0, 0.000120, 5.77, 14286.1504, -0.6, 6, 0, 0.000118, 5.96, 8330.9926, 0, 0,
0, 0.000110, 1.80, 23243.1438, 0.9, 31, 0, 0.000110, 3.42, 5957.4590, -2.1, -19, 0, 0.000110, 4.63, 1256.6039,
-0.1, 0, 0, 0.000099, 4.70, -0.7113, 0, 0, 0, 0.000070, 0.04, 16029.0809, 3.1, 50, 0, 0.000070, 5.14,
8328.3391, 1.5, 25, 0, 0.000070, 5.85, 8329.0437, 1.5, 25, 0, 0.000060, 1.02, -1742.9305, -3.7, -44, 0,
0.000060, 3.10, 17285.6848, 3.0, 50, 0, 0.000054, 5.69, -0.352, 0, 0, 0, 0.000043, 0.52, 15.542, 0, 0, 0,
0.000041, 2.03, 2.630, 0, 0, 0, 0.000040, 0.10, 8470.667, -2.2, -19, 0, 0.000040, 4.01, 7072.088, 1.6, 25, 0,
0.000036, 2.93, -8.860, -0.3, 0, 0, 0.000030, 1.20, 22128.515, -2.8, -13, 0, 0.000030, 2.54, 15542.754, -0.7,
6, 0, 0.000027, 4.43, 7211.762, -0.7, 6, 0, 0.000026, 0.51, 15540.453, 0.9, 31, 0, 0.000026, 1.44, 15545.055,
-2.2, -19, 0, 0.000025, 5.37, 7216.364, -3.7, -44, 0),
(0.00001200, 1.041, -2.3012, 1.52, 25, -0.1, 0.00000170, 0.31, -0.711, 0, 0, 0)
)
__QI_KB = (
1640650.479938, 15.21842500, # -221-11-09 h=0.01709 古历·秦汉
1642476.703182, 15.21874996, # -216-11-09 h=0.01557 古历·秦汉
1683430.515601, 15.218750011, # -104-12-25 h=0.01560 汉书·律历志(太初历)平气平朔 回归年=365.25000
1752157.640664, 15.218749978, # 85-02-23 h=0.01559 后汉书·律历志(四分历) 回归年=365.25000
1807675.003759, 15.218620279, # 237-02-22 h=0.00010 晋书·律历志(景初历) 回归年=365.24689
1883627.765182, 15.218612292, # 445-02-03 h=0.00026 宋书·律历志(何承天元嘉历) 回归年=365.24670
1907369.128100, 15.218449176, # 510-02-03 h=0.00027 宋书·律历志(祖冲之大明历) 回归年=365.24278
1936603.140413, 15.218425000, # 590-02-17 h=0.00149 随书·律历志(开皇历) 回归年=365.24220
1939145.524180, 15.218466998, # 597-02-03 h=0.00121 随书·律历志(大业历) 回归年=365.24321
1947180.798300, 15.218524844, # 619-02-03 h=0.00052 新唐书·历志(戊寅元历)平气定朔 回归年=365.24460
1964362.041824, 15.218533526, # 666-02-17 h=0.00059 新唐书·历志(麟德历) 回归年=365.24480
1987372.340971, 15.218513908, # 729-02-16 h=0.00096 新唐书·历志(大衍历,至德历) 回归年=365.24433
1999653.819126, 15.218530782, # 762-10-03 h=0.00093 新唐书·历志(五纪历) 回归年=365.24474
2007445.469786, 15.218535181, # 784-02-01 h=0.00059 新唐书·历志(正元历,观象历) 回归年=365.24484
2021324.917146, 15.218526248, # 822-02-01 h=0.00022 新唐书·历志(宣明历) 回归年=365.24463
2047257.232342, 15.218519654, # 893-01-31 h=0.00015 新唐书·历志(崇玄历) 回归年=365.24447
2070282.898213, 15.218425000, # 956-02-16 h=0.00149 旧五代·历志(钦天历) 回归年=365.24220
2073204.872850, 15.218515221, # 964-02-16 h=0.00166 宋史·律历志(应天历) 回归年=365.24437
2080144.500926, 15.218530782, # 983-02-16 h=0.00093 宋史·律历志(乾元历) 回归年=365.24474
2086703.688963, 15.218523776, # 1001-01-31 h=0.00067 宋史·律历志(仪天历,崇天历) 回归年=365.24457
2110033.182763, 15.218425000, # 1064-12-15 h=0.00669 宋史·律历志(明天历) 回归年=365.24220
2111190.300888, 15.218425000, # 1068-02-15 h=0.00149 宋史·律历志(崇天历) 回归年=365.24220
2113731.271005, 15.218515671, # 1075-01-30 h=0.00038 李锐补修(奉元历) 回归年=365.24438
2120670.840263, 15.218425000, # 1094-01-30 h=0.00149 宋史·律历志 回归年=365.24220
2123973.309063, 15.218425000, # 1103-02-14 h=0.00669 李锐补修(占天历) 回归年=365.24220
2125068.997336, 15.218477932, # 1106-02-14 h=0.00056 宋史·律历志(纪元历) 回归年=365.24347
2136026.312633, 15.218472436, # 1136-02-14 h=0.00088 宋史·律历志(统元历,乾道历,淳熙历) 回归年=365.24334
2156099.495538, 15.218425000, # 1191-01-29 h=0.00149 宋史·律历志(会元历) 回归年=365.24220
2159021.324663, 15.218425000, # 1199-01-29 h=0.00149 宋史·律历志(统天历) 回归年=365.24220
2162308.575254, 15.218461742, # 1208-01-30 h=0.00146 宋史·律历志(开禧历) 回归年=365.24308
2178485.706538, 15.218425000, # 1252-05-15 h=0.04606 淳祐历 回归年=365.24220
2178759.662849, 15.218445786, # 1253-02-13 h=0.00231 会天历 回归年=365.24270
2185334.020800, 15.218425000, # 1271-02-13 h=0.00520 宋史·律历志(成天历) 回归年=365.24220
2187525.481425, 15.218425000, # 1277-02-12 h=0.00520 本天历 回归年=365.24220
2188621.191481, 15.218437494, # 1280-02-13 h=0.00015 元史·历志(郭守敬授时历) 回归年=365.24250
2322147.76 # 1645-09-21
)
# 1645-09-23开始7567个节气修正表
__QB = ''
__SHUO_KB = (
1457698.231017, 29.53067166, 1546082.512234, 29.53085106, 1640640.735300, 29.53060000, 1642472.151543,
29.53085439,
1683430.509300, 29.53086148, 1752148.041079, 29.53085097, 1807665.420323, 29.53059851, 1883618.114100,
29.53060000,
1907360.704700, 29.53060000, 1936596.224900, 29.53060000, 1939135.675300, 29.53060000, 1947168.00)
# 619-01-21开始16598个朔日修正表 d0=1947168
__SB = ''
@staticmethod
def __decode(s: str) -> str:
o = '0000000000'
o2 = o + o
s = s.replace('J', '00')
s = s.replace('I', '000')
s = s.replace('H', '0000')
s = s.replace('G', '00000')
s = s.replace('t', '02')
s = s.replace('s', '002')
s = s.replace('r', '0002')
s = s.replace('q', '00002')
s = s.replace('p', '000002')
s = s.replace('o', '0000002')
s = s.replace('n', '00000002')
s = s.replace('m', '000000002')
s = s.replace('l', '0000000002')
s = s.replace('k', '01')
s = s.replace('j', '0101')
s = s.replace('i', '001')
s = s.replace('h', '001001')
s = s.replace('g', '0001')
s = s.replace('f', '00001')
s = s.replace('e', '000001')
s = s.replace('d', '0000001')
s = s.replace('c', '00000001')
s = s.replace('b', '000000001')
s = s.replace('a', '0000000001')
s = s.replace('A', o2 + o2 + o2)
s = s.replace('B', o2 + o2 + o)
s = s.replace('C', o2 + o2)
s = s.replace('D', o2 + o)
s = s.replace('E', o2)
s = s.replace('F', o)
return s
@staticmethod
def nutation_lon2(t: float) -> float:
a: float = -1.742 * t
t2: float = t * t
dl: float = 0
for i in range(0, ShouXingUtil.__NUT_B.__len__(), 5):
dl += (ShouXingUtil.__NUT_B[i + 3] + a) * sin(
ShouXingUtil.__NUT_B[i] + ShouXingUtil.__NUT_B[i + 1] * t + ShouXingUtil.__NUT_B[i + 2] * t2)
a = 0
return dl / 100 / ShouXingUtil.SECOND_PER_RAD
@staticmethod
def e_lon(t: float, n: int) -> float:
t /= 10
v: float = 0
tn: float = 1
pn: int = 1
m0: float = ShouXingUtil.__XL0[pn + 1] - ShouXingUtil.__XL0[pn]
for i in range(0, 6):
n1 = int(ShouXingUtil.__XL0[pn + i])
n2 = int(ShouXingUtil.__XL0[pn + 1 + i])
n0 = n2 - n1
if n0 == 0:
continue
if n < 0:
m = n2
else:
m = int((3 * n * n0 / m0 + 0.5) + n1)
if i != 0:
m += 3
if m > n2:
m = n2
c = 0
for j in range(n1, m, 3):
c += ShouXingUtil.__XL0[j] * cos(ShouXingUtil.__XL0[j + 1] + t * ShouXingUtil.__XL0[j + 2])
v += c * tn
tn *= t
v /= ShouXingUtil.__XL0[0]
t2 = t * t
t3 = t2 * t
return v + (-0.0728 - 2.7702 * t - 1.1019 * t2 - 0.0996 * t3) / ShouXingUtil.SECOND_PER_RAD
@staticmethod
def m_lon(t: float, n: int) -> float:
ob = ShouXingUtil.__XL1
obl = len(ob[0])
tn = 1
v = 0
t2 = t * t
t3 = t2 * t
t4 = t3 * t
t5 = t4 * t
tx = t - 10
v += (3.81034409 + 8399.684730072 * t - 3.319e-05 * t2 + 3.11e-08 * t3 - 2.033e-10 * t4) * ShouXingUtil.SECOND_PER_RAD
v += 5028.792262 * t + 1.1124406 * t2 + 0.00007699 * t3 - 0.000023479 * t4 - 0.0000000178 * t5
if tx > 0:
v += -0.866 + 1.43 * tx + 0.054 * tx * tx
t2 /= 1e4
t3 /= 1e8
t4 /= 1e8
n *= 6
if n < 0:
n = obl
for i in range(len(ob)):
f = ob[i]
size = len(f)
m = int(n * size / obl + 0.5)
if i > 0:
m += 6
if m >= size:
m = size
c = 0
for j in range(0, m, 6):
c += f[j] * cos(f[j + 1] + t * f[j + 2] + t2 * f[j + 3] + t3 * f[j + 4] + t4 * f[j + 5])
v += c * tn
tn *= t
return v / ShouXingUtil.SECOND_PER_RAD
@staticmethod
def gxc_sun_lon(t: float) -> float:
return -20.49552 * (1 + (0.016708634 - 0.000042037 * t - 0.0000001267 * t * t) * cos(-0.043126 + 628.301955 * t - 0.000002732 * t * t)) / ShouXingUtil.SECOND_PER_RAD
@staticmethod
def ev(t: float) -> float:
f = 628.307585 * t
return 628.332 + 21 * sin(1.527 + f) + 0.44 * sin(1.48 + f * 2) + 0.129 * sin(5.82 + f) * t + 0.00055 * sin(4.21 + f) * t * t
@staticmethod
def mv(t: float) -> float:
v = 8399.71 - 914 * sin(0.7848 + 8328.691425 * t + 0.0001523 * t * t)
return v - (179 * sin(2.543 + 15542.7543 * t) + 160 * sin(0.1874 + 7214.0629 * t) + 62 * sin(3.14 + 16657.3828 * t) + 34 * sin(4.827 + 16866.9323 * t) + 22 * sin(4.9 + 23871.4457 * t) + 12 * sin(2.59 + 14914.4523 * t) + 7 * sin(0.23 + 6585.7609 * t) + 5 * sin(0.9 + 25195.624 * t) + 5 * sin(2.32 - 7700.3895 * t) + 5 * sin(3.88 + 8956.9934 * t) + 5 * sin(0.49 + 7771.3771 * t))
@staticmethod
def sa_lon(t: float, n: int) -> float:
return ShouXingUtil.e_lon(t, n) + ShouXingUtil.nutation_lon2(t) + ShouXingUtil.gxc_sun_lon(t) + ShouXingUtil.PI
@staticmethod
def dt_ext(y: float, jsd: int) -> float:
dy = (y - 1820) * 1.0 / 100
return - 20 + jsd * dy * dy
@staticmethod
def dt_calc(y: float) -> float:
size = len(ShouXingUtil.__DT_AT)
y0 = ShouXingUtil.__DT_AT[size - 2]
t0 = ShouXingUtil.__DT_AT[size - 1]
if y >= y0:
jsd: int = 31
if y > y0 + 100:
return ShouXingUtil.dt_ext(y, jsd)
v = ShouXingUtil.dt_ext(y, jsd)
dv = ShouXingUtil.dt_ext(y0, jsd) - t0
return v - dv * (y0 + 100 - y) / 100
i = 0
for i in range(0, size, 5):
if y < ShouXingUtil.__DT_AT[i + 5]:
break
t1 = (y - ShouXingUtil.__DT_AT[i]) / (ShouXingUtil.__DT_AT[i + 5] - ShouXingUtil.__DT_AT[i]) * 10
t2 = t1 * t1
t3 = t2 * t1
return ShouXingUtil.__DT_AT[i + 1] + ShouXingUtil.__DT_AT[i + 2] * t1 + ShouXingUtil.__DT_AT[i + 3] * t2 + ShouXingUtil.__DT_AT[i + 4] * t3
@staticmethod
def dt_t(t: float) -> float:
return ShouXingUtil.dt_calc(t / 365.2425 + 2000) / ShouXingUtil.SECOND_PER_DAY
@staticmethod
def sa_lon_t(w: float) -> float:
v = 628.3319653318
t = (w - 1.75347 - ShouXingUtil.PI) / v
v = ShouXingUtil.ev(t)
t += (w - ShouXingUtil.sa_lon(t, 10)) / v
v = ShouXingUtil.ev(t)
return t + (w - ShouXingUtil.sa_lon(t, -1)) / v
@staticmethod
def msa_lon(t: float, mn: int, sn: int) -> float:
return ShouXingUtil.m_lon(t, mn) + (-3.4E-6) - (ShouXingUtil.e_lon(t, sn) + ShouXingUtil.gxc_sun_lon(t) + ShouXingUtil.PI)
@staticmethod
def msa_lon_t(w: float) -> float:
v = 7771.37714500204
t = (w + 1.08472) / v
t += (w - ShouXingUtil.msa_lon(t, 3, 3)) / v
v = ShouXingUtil.mv(t) - ShouXingUtil.ev(t)
t += (w - ShouXingUtil.msa_lon(t, 20, 10)) / v
return t + (w - ShouXingUtil.msa_lon(t, -1, 60)) / v
@staticmethod
def sa_lon_t2(w: float) -> float:
v = 628.3319653318
t = (w - 1.75347 - ShouXingUtil.PI) / v
t -= (0.000005297 * t * t + 0.0334166 * cos(4.669257 + 628.307585 * t) + 0.0002061 * cos(2.67823 + 628.307585 * t) * t) / v
return t + (w - ShouXingUtil.e_lon(t, 8) - ShouXingUtil.PI + (20.5 + 17.2 * sin(2.1824 - 33.75705 * t)) / ShouXingUtil.SECOND_PER_RAD) / v
@staticmethod
def msa_lon_t2(w: float) -> float:
v = 7771.37714500204
t = (w + 1.08472) / v
t2 = t * t
t -= (-0.00003309 * t2 + 0.10976 * cos(0.784758 + 8328.6914246 * t + 0.000152292 * t2) + 0.02224 * cos(0.18740 + 7214.0628654 * t - 0.00021848 * t2) - 0.03342 * cos(4.669257 + 628.307585 * t)) / v
t2 = t * t
n = ShouXingUtil.m_lon(t, 20) - (4.8950632 + 628.3319653318 * t + 0.000005297 * t2 + 0.0334166 * cos(4.669257 + 628.307585 * t) + 0.0002061 * cos(2.67823 + 628.307585 * t) * t + 0.000349 * cos(4.6261 + 1256.61517 * t) - 20.5 / ShouXingUtil.SECOND_PER_RAD)
return t + (w - n) / (7771.38 - 914 * sin(0.7848 + 8328.691425 * t + 0.0001523 * t2) - 179 * sin(2.543 + 15542.7543 * t) - 160 * sin(0.1874 + 7214.0629 * t))
@staticmethod
def qi_high(w: float) -> float:
t = ShouXingUtil.sa_lon_t2(w) * 36525
t = t - ShouXingUtil.dt_t(t) + ShouXingUtil.ONE_THIRD
v = ((t + 0.5) % 1) * ShouXingUtil.SECOND_PER_DAY
if v < 1200 or v > ShouXingUtil.SECOND_PER_DAY - 1200:
t = ShouXingUtil.sa_lon_t(w) * 36525 - ShouXingUtil.dt_t(t) + ShouXingUtil.ONE_THIRD
return t
@staticmethod
def qi_low(w: float) -> float:
v = 628.3319653318
t = (w - 4.895062166) / v
t -= (53 * t * t + 334116 * cos(4.67 + 628.307585 * t) + 2061 * cos(2.678 + 628.3076 * t) * t) / v / 10000000
n = 48950621.66 + 6283319653.318 * t + 53 * t * t + 334166 * cos(4.669257 + 628.307585 * t) + 3489 * cos(4.6261 + 1256.61517 * t) + 2060.6 * cos(2.67823 + 628.307585 * t) * t - 994 - 834 * sin(2.1824 - 33.75705 * t)
t -= (n / 10000000 - w) / 628.332 + (32 * (t + 1.8) * (t + 1.8) - 20) / ShouXingUtil.SECOND_PER_DAY / 36525
return t * 36525 + ShouXingUtil.ONE_THIRD
@staticmethod
def shuo_high(w: float) -> float:
t = ShouXingUtil.msa_lon_t2(w) * 36525
t = t - ShouXingUtil.dt_t(t) + ShouXingUtil.ONE_THIRD
v = ((t + 0.5) % 1) * ShouXingUtil.SECOND_PER_DAY
if v < 1800 or v > ShouXingUtil.SECOND_PER_DAY - 1800:
t = ShouXingUtil.msa_lon_t(w) * 36525 - ShouXingUtil.dt_t(t) + ShouXingUtil.ONE_THIRD
return t
@staticmethod
def shuo_low(w: float) -> float:
v = 7771.37714500204
t = (w + 1.08472) / v
t -= (-0.0000331 * t * t + 0.10976 * cos(0.785 + 8328.6914 * t) + 0.02224 * cos(0.187 + 7214.0629 * t) - 0.03342 * cos(4.669 + 628.3076 * t)) / v + (32 * (t + 1.8) * (t + 1.8) - 20) / ShouXingUtil.SECOND_PER_DAY / 36525
return t * 36525 + ShouXingUtil.ONE_THIRD
@staticmethod
def calc_shuo(jd: float) -> int:
if len(ShouXingUtil.__SB) < 1:
ShouXingUtil.__SB = ShouXingUtil.__decode('EqoFscDcrFpmEsF2DfFideFelFpFfFfFiaipqti1ksttikptikqckstekqttgkqttgkqteksttikptikq2fjstgjqttjkqttgkqtekstfkptikq2tijstgjiFkirFsAeACoFsiDaDiADc1AFbBfgdfikijFifegF1FhaikgFag1E2btaieeibggiffdeigFfqDfaiBkF1kEaikhkigeidhhdiegcFfakF1ggkidbiaedksaFffckekidhhdhdikcikiakicjF1deedFhFccgicdekgiFbiaikcfi1kbFibefgEgFdcFkFeFkdcfkF1kfkcickEiFkDacFiEfbiaejcFfffkhkdgkaiei1ehigikhdFikfckF1dhhdikcfgjikhfjicjicgiehdikcikggcifgiejF1jkieFhegikggcikFegiegkfjebhigikggcikdgkaFkijcfkcikfkcifikiggkaeeigefkcdfcfkhkdgkegieidhijcFfakhfgeidieidiegikhfkfckfcjbdehdikggikgkfkicjicjF1dbidikFiggcifgiejkiegkigcdiegfggcikdbgfgefjF1kfegikggcikdgFkeeijcfkcikfkekcikdgkabhkFikaffcfkhkdgkegbiaekfkiakicjhfgqdq2fkiakgkfkhfkfcjiekgFebicggbedF1jikejbbbiakgbgkacgiejkijjgigfiakggfggcibFifjefjF1kfekdgjcibFeFkijcfkfhkfkeaieigekgbhkfikidfcjeaibgekgdkiffiffkiakF1jhbakgdki1dj1ikfkicjicjieeFkgdkicggkighdF1jfgkgfgbdkicggfggkidFkiekgijkeigfiskiggfaidheigF1jekijcikickiggkidhhdbgcfkFikikhkigeidieFikggikhkffaffijhidhhakgdkhkijF1kiakF1kfheakgdkifiggkigicjiejkieedikgdfcggkigieeiejfgkgkigbgikicggkiaideeijkefjeijikhkiggkiaidheigcikaikffikijgkiahi1hhdikgjfifaakekighie1hiaikggikhkffakicjhiahaikggikhkijF1kfejfeFhidikggiffiggkigicjiekgieeigikggiffiggkidheigkgfjkeigiegikifiggkidhedeijcfkFikikhkiggkidhh1ehigcikaffkhkiggkidhh1hhigikekfiFkFikcidhh1hitcikggikhkfkicjicghiediaikggikhkijbjfejfeFhaikggifikiggkigiejkikgkgieeigikggiffiggkigieeigekijcijikggifikiggkideedeijkefkfckikhkiggkidhh1ehijcikaffkhkiggkidhh1hhigikhkikFikfckcidhh1hiaikgjikhfjicjicgiehdikcikggifikigiejfejkieFhegikggifikiggfghigkfjeijkhigikggifikiggkigieeijcijcikfksikifikiggkidehdeijcfdckikhkiggkhghh1ehijikifffffkhsFngErD1pAfBoDd1BlEtFqA2AqoEpDqElAEsEeB2BmADlDkqBtC1FnEpDqnEmFsFsAFnllBbFmDsDiCtDmAB2BmtCgpEplCpAEiBiEoFqFtEqsDcCnFtADnFlEgdkEgmEtEsCtDmADqFtAFrAtEcCqAE1BoFqC1F1DrFtBmFtAC2ACnFaoCgADcADcCcFfoFtDlAFgmFqBq2bpEoAEmkqnEeCtAE1bAEqgDfFfCrgEcBrACfAAABqAAB1AAClEnFeCtCgAADqDoBmtAAACbFiAAADsEtBqAB2FsDqpFqEmFsCeDtFlCeDtoEpClEqAAFrAFoCgFmFsFqEnAEcCqFeCtFtEnAEeFtAAEkFnErAABbFkADnAAeCtFeAfBoAEpFtAABtFqAApDcCGJ')
size = len(ShouXingUtil.__SHUO_KB)
d = 0
pc = 14
i = 0
jd += ShouXingUtil.J2000
f1 = ShouXingUtil.__SHUO_KB[0] - pc
f2 = ShouXingUtil.__SHUO_KB[size - 1] - pc
f3 = 2436935
if jd < f1 or jd >= f3:
d = floor(ShouXingUtil.shuo_high(floor((jd + pc - 2451551) / 29.5306) * ShouXingUtil.PI * 2) + 0.5)
elif f1 <= jd < f2:
for i in range(0, size, 2):
if jd + pc < ShouXingUtil.__SHUO_KB[i + 2]:
break
d = ShouXingUtil.__SHUO_KB[i] + ShouXingUtil.__SHUO_KB[i + 1] * floor((jd + pc - ShouXingUtil.__SHUO_KB[i]) / ShouXingUtil.__SHUO_KB[i + 1])
d = floor(d + 0.5)
if d == 1683460:
d += 1
d -= ShouXingUtil.J2000
elif f2 <= jd < f3:
d = floor(ShouXingUtil.shuo_low(floor((jd + pc - 2451551) / 29.5306) * ShouXingUtil.PI * 2) + 0.5)
index = floor((jd - f2) / 29.5306)
n = ShouXingUtil.__SB[index:index + 1]
if '1' == n:
d += 1
elif '2' == n:
d -= 1
return d
@staticmethod
def calc_qi(jd: float) -> int:
if len(ShouXingUtil.__QB) < 1:
ShouXingUtil.__QB = ShouXingUtil.__decode('FrcFs22AFsckF2tsDtFqEtF1posFdFgiFseFtmelpsEfhkF2anmelpFlF1ikrotcnEqEq2FfqmcDsrFor22FgFrcgDscFs22FgEeFtE2sfFs22sCoEsaF2tsD1FpeE2eFsssEciFsFnmelpFcFhkF2tcnEqEpFgkrotcnEqrEtFermcDsrE222FgBmcmr22DaEfnaF222sD1FpeForeF2tssEfiFpEoeFssD1iFstEqFppDgFstcnEqEpFg11FscnEqrAoAF2ClAEsDmDtCtBaDlAFbAEpAAAAAD2FgBiBqoBbnBaBoAAAAAAAEgDqAdBqAFrBaBoACdAAf1AACgAAAeBbCamDgEifAE2AABa1C1BgFdiAAACoCeE1ADiEifDaAEqAAFe1AcFbcAAAAAF1iFaAAACpACmFmAAAAAAAACrDaAAADG0')
size = len(ShouXingUtil.__QI_KB)
d = 0
pc = 7
i = 0
jd += ShouXingUtil.J2000
f1 = ShouXingUtil.__QI_KB[0] - pc
f2 = ShouXingUtil.__QI_KB[size - 1] - pc
f3 = 2436935
if jd < f1 or jd >= f3:
# 2451259是1999.3.21,太阳视黄经为0,春分 定气计算
d = floor(ShouXingUtil.qi_high(floor((jd + pc - 2451259) / 365.2422 * 24) * ShouXingUtil.PI / 12) + 0.5)
elif f1 <= jd < f2:
for i in range(0, size, 2):
if jd + pc < ShouXingUtil.__QI_KB[i + 2]:
break
d = ShouXingUtil.__QI_KB[i] + ShouXingUtil.__QI_KB[i + 1] * floor((jd + pc - ShouXingUtil.__QI_KB[i]) / ShouXingUtil.__QI_KB[i + 1])
d = floor(d + 0.5)
if d == 1683460:
d += 1
d -= ShouXingUtil.J2000
elif f2 <= jd < f3:
d = floor(ShouXingUtil.qi_low(floor((jd + pc - 2451259) / 365.2422 * 24) * ShouXingUtil.PI / 12) + 0.5)
# 找定气修正值
index = floor((jd - f2) / 365.2422 * 24)
n = ShouXingUtil.__QB[index:index + 1]
if '1' == n:
d += 1
elif '2' == n:
d -= 1
return d
@staticmethod
def qi_accurate(w: float) -> float:
t = ShouXingUtil.sa_lon_t(w) * 36525
return t - ShouXingUtil.dt_t(t) + ShouXingUtil.ONE_THIRD
@staticmethod
def qi_accurate2(jd: float) -> float:
d: float = ShouXingUtil.PI / 12
w: float = floor((jd + 293) / 365.2422 * 24) * d
a: float = ShouXingUtil.qi_accurate(w)
if a - jd > 5:
return ShouXingUtil.qi_accurate(w - d)
if a - jd < -5:
return ShouXingUtil.qi_accurate(w + d)
return a
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+6
View File
@@ -0,0 +1,6 @@
# IANA versions like 2020a are not valid PEP 440 identifiers; the recommended
# way to translate the version is to use YYYY.n where `n` is a 0-based index.
__version__ = "2026.5"
# This exposes the original IANA version number.
IANA_VERSION = "2026e"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More