jtyoui.plunar.SC_ 源代码

#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time  : 2019/5/9 11:48
# @Author: Jtyoui@qq.com

"""
SC (solar calendar):阳历
阳历转农历
"""

import time
from jtyoui.data import holiday, week_to_chinese, chinese_mon


[文档]class Lunar: """阳历转农历 返回年月日星期和节日 >>> lun = Lunar(year=2018, month=1, day=2) >>> print(lun) # 二零一九年 七月 十四 星期四 无 >>> print(lun.y) # 农历的年,中文字符 二零一九 >>> print(lun.year) # 农历的年,阿拉伯数字 2019 >>> print(lun.m) # 农历的月份 中文字符 七 >>> print(lun.month) # 农历的月份 阿拉伯字符 7 >>> print(lun.d) # 农历的日期 中文字符 十四 >>> print(lun.day) # 阳历的日期 阿拉伯数字 15 ,注意。和农历不一样 >>> print(lun.w) # 星期几 中文字符 >>> print(lun.week) # 星期几、英文字符 >>> print(lun.h) # 节日 >>> print(lun) # 二零一九年 七月 十四 星期四 无 """ def __init__(self, year, month, day): """ 1980年的数据是: 0x095b0 二进制:0000 1001 0101 1011 0000 1-4: 表示当年有无闰年,有的话,为闰月的月份,没有的话,为0。 5-16:为除了闰月外的正常月份是大月还是小月,1为30天,0为29天。 注意:从1月到12月对应的是第16位到第5位。 17-20:表示闰月是大月还是小月,仅当存在闰月的情况下有意义。 """ self.date = '{0}-{1:0>2}-{2:0>2}'.format(year, month, day) if year > 2050 or year < 1990: raise ValueError('输入的范围在1990-2050年之间') self.year = 0 self.month = 0 self.day = 0 self.week = 0 self.leap = False self.chinese_week = week_to_chinese self.chinese_number = chinese_mon self.lunar_info = [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 ] self.lunar()
[文档] def lunar(self): date_time = time.strptime(self.date, '%Y-%m-%d') # 25538是1900-01-01到1970-01-01的天数,86400是一年的秒数 total_day = int(time.mktime(date_time) / 86400) + 25538 # 计算当天是农历第几天 lunar_year, year_day = 0, 0 while lunar_year < 2050 - 1900 and total_day > 0: year_day = self.year_days(lunar_year) total_day -= year_day lunar_year += 1 if total_day < 0: total_day += year_day lunar_year -= 1 # 农历年份 self.year = lunar_year + 1900 leap_month = self.leap_months(lunar_year) # 闰哪个月, 1 - 12 # 用当年的天数offset, 逐个减去每月(农历)的天数,求出当天是本月的第几天 lunar_month, month_day = 1, 0 while lunar_month < 13 and total_day > 0: # 闰月 if leap_month > 0 and lunar_month == (leap_month + 1) and (not self.leap): lunar_month -= 1 self.leap = True month_day = self.leap_days(lunar_year) else: month_day = self.month_days(lunar_year, lunar_month) total_day -= month_day # 解除闰月 if self.leap and lunar_month == (leap_month + 1): self.leap = False lunar_month += 1 # offset为0时,并且刚才计算的月份是闰月,要校正 if total_day == 0 and leap_month > 0 and lunar_month == leap_month + 1: leap = False if self.leap else True if leap: lunar_month -= 1 # offset小于0时,也要校正 if total_day < 0: total_day += month_day lunar_month -= 1 self.month = lunar_month self.day = total_day + 1 self.week = time.strftime('%a', date_time)
[文档] def year_days(self, lunar_year): i, sum_day = 0x8000, 348 while i > 0x8: if (self.lunar_info[lunar_year] & i) != 0: sum_day += 1 i >>= 1 return sum_day + self.leap_days(lunar_year)
[文档] def leap_months(self, lunar_year): return int(self.lunar_info[lunar_year] & 0xf)
[文档] def leap_days(self, lunar_year): if self.leap_months(lunar_year) != 0: return 30 if (self.lunar_info[lunar_year] & 0x10000) != 0 else 29 return 0
[文档] def month_days(self, lunar_year, lunar_month): return 29 if (self.lunar_info[lunar_year] & (0x10000 >> lunar_month)) == 0 else 30
[文档] def get_china_day(self, d): chinese_ten = ['初', '十', '廿', '卅'] n = 9 if d % 10 == 0 else (d % 10 - 1) if d == 10: return '初十' elif n == 0: return chinese_ten[d // 10] + '一' else: return chinese_ten[d // 10] + self.chinese_number[n + 1]
[文档] def get_holiday(self, date): x = holiday.get(date[5:]) if x: return x else: z = holiday.get(self.chinese_number[self.month - 1] + '月' + self.get_china_day(self.day)) return z if z else '无'
def __str__(self): """返回字符串数据 :return: 年 月 日 星期 节日(没有是无) """ if self.leap: return self.y + '年 闰' + self.m + '月 ' + self.d + ' ' + self.w + ' 节日:' + self.h else: return self.y + '年 ' + self.m + '月 ' + self.d + ' ' + self.w + ' 节日:' + self.h def __getattr__(self, item): if item == 'y': y = '' for i in range(3, -1, -1): y += self.chinese_number[self.year // (10 ** i) % 10] return y.replace('正', '一') elif item == 'm': return self.chinese_number[self.month] elif item == 'd': return self.get_china_day(self.day) elif item == 'w': return self.chinese_week.get(self.week) elif item == 'h': return self.get_holiday(self.date)
[文档] def to_sc(self): """年 月 日 """ if self.leap: return str(self.year) + '年闰' + str(self.month) + '月' + str(self.day) + '日' else: return str(self.year) + '年' + str(self.month) + '月' + str(self.day) + '日'
def __repr__(self): return self.__str__()
SC = Lunar if __name__ == '__main__': lun = Lunar(year=2019, month=12, day=27) print(lun.y) # 农历的年,中文字符 二零一九 print(lun.year) # 农历的年,阿拉伯数字 2019 print(lun.m) # 农历的月份 中文字符 七 print(lun.month) # 农历的月份 阿拉伯字符 7 print(lun.d) # 农历的日期 中文字符 十四 print(lun.day) # 阳历的日期 阿拉伯数字 15 ,注意。和农历不一样 print(lun.w) # 星期几 中文字符 print(lun.week) # 星期几、英文字符 print(lun.h) # 节日 print(lun) # 二零一九年 七月 十四 星期四 无