|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +""" |
| 4 | +@author: 闲欢 |
| 5 | +""" |
| 6 | + |
| 7 | +g_lunar_month_day = [ |
| 8 | + 0x00752, 0x00ea5, 0x0ab2a, 0x0064b, 0x00a9b, 0x09aa6, 0x0056a, 0x00b59, 0x04baa, 0x00752, # 1901 ~ 1910 |
| 9 | + 0x0cda5, 0x00b25, 0x00a4b, 0x0ba4b, 0x002ad, 0x0056b, 0x045b5, 0x00da9, 0x0fe92, 0x00e92, # 1911 ~ 1920 |
| 10 | + 0x00d25, 0x0ad2d, 0x00a56, 0x002b6, 0x09ad5, 0x006d4, 0x00ea9, 0x04f4a, 0x00e92, 0x0c6a6, # 1921 ~ 1930 |
| 11 | + 0x0052b, 0x00a57, 0x0b956, 0x00b5a, 0x006d4, 0x07761, 0x00749, 0x0fb13, 0x00a93, 0x0052b, # 1931 ~ 1940 |
| 12 | + 0x0d51b, 0x00aad, 0x0056a, 0x09da5, 0x00ba4, 0x00b49, 0x04d4b, 0x00a95, 0x0eaad, 0x00536, # 1941 ~ 1950 |
| 13 | + 0x00aad, 0x0baca, 0x005b2, 0x00da5, 0x07ea2, 0x00d4a, 0x10595, 0x00a97, 0x00556, 0x0c575, # 1951 ~ 1960 |
| 14 | + 0x00ad5, 0x006d2, 0x08755, 0x00ea5, 0x0064a, 0x0664f, 0x00a9b, 0x0eada, 0x0056a, 0x00b69, # 1961 ~ 1970 |
| 15 | + 0x0abb2, 0x00b52, 0x00b25, 0x08b2b, 0x00a4b, 0x10aab, 0x002ad, 0x0056d, 0x0d5a9, 0x00da9, # 1971 ~ 1980 |
| 16 | + 0x00d92, 0x08e95, 0x00d25, 0x14e4d, 0x00a56, 0x002b6, 0x0c2f5, 0x006d5, 0x00ea9, 0x0af52, # 1981 ~ 1990 |
| 17 | + 0x00e92, 0x00d26, 0x0652e, 0x00a57, 0x10ad6, 0x0035a, 0x006d5, 0x0ab69, 0x00749, 0x00693, # 1991 ~ 2000 |
| 18 | + 0x08a9b, 0x0052b, 0x00a5b, 0x04aae, 0x0056a, 0x0edd5, 0x00ba4, 0x00b49, 0x0ad53, 0x00a95, # 2001 ~ 2010 |
| 19 | + 0x0052d, 0x0855d, 0x00ab5, 0x12baa, 0x005d2, 0x00da5, 0x0de8a, 0x00d4a, 0x00c95, 0x08a9e, # 2011 ~ 2020 |
| 20 | + 0x00556, 0x00ab5, 0x04ada, 0x006d2, 0x0c765, 0x00725, 0x0064b, 0x0a657, 0x00cab, 0x0055a, # 2021 ~ 2030 |
| 21 | + 0x0656e, 0x00b69, 0x16f52, 0x00b52, 0x00b25, 0x0dd0b, 0x00a4b, 0x004ab, 0x0a2bb, 0x005ad, # 2031 ~ 2040 |
| 22 | + 0x00b6a, 0x04daa, 0x00d92, 0x0eea5, 0x00d25, 0x00a55, 0x0ba4d, 0x004b6, 0x005b5, 0x076d2, # 2041 ~ 2050 |
| 23 | + 0x00ec9, 0x10f92, 0x00e92, 0x00d26, 0x0d516, 0x00a57, 0x00556, 0x09365, 0x00755, 0x00749, # 2051 ~ 2060 |
| 24 | + 0x0674b, 0x00693, 0x0eaab, 0x0052b, 0x00a5b, 0x0aaba, 0x0056a, 0x00b65, 0x08baa, 0x00b4a, # 2061 ~ 2070 |
| 25 | + 0x10d95, 0x00a95, 0x0052d, 0x0c56d, 0x00ab5, 0x005aa, 0x085d5, 0x00da5, 0x00d4a, 0x06e4d, # 2071 ~ 2080 |
| 26 | + 0x00c96, 0x0ecce, 0x00556, 0x00ab5, 0x0bad2, 0x006d2, 0x00ea5, 0x0872a, 0x0068b, 0x10697, # 2081 ~ 2090 |
| 27 | + 0x004ab, 0x0055b, 0x0d556, 0x00b6a, 0x00752, 0x08b95, 0x00b45, 0x00a8b, 0x04a4f, ] |
| 28 | + |
| 29 | +# 农历数据 每个元素的存储格式如下: |
| 30 | +# 12~7 6~5 4~0 |
| 31 | +# 离元旦多少天 春节月 春节日 |
| 32 | +##################################################################################### |
| 33 | +g_lunar_year_day = [ |
| 34 | + 0x18d3, 0x1348, 0x0e3d, 0x1750, 0x1144, 0x0c39, 0x15cd, 0x1042, 0x0ab6, 0x144a, # 1901 ~ 1910 |
| 35 | + 0x0ebe, 0x1852, 0x1246, 0x0cba, 0x164e, 0x10c3, 0x0b37, 0x14cb, 0x0fc1, 0x1954, # 1911 ~ 1920 |
| 36 | + 0x1348, 0x0dbc, 0x1750, 0x11c5, 0x0bb8, 0x15cd, 0x1042, 0x0b37, 0x144a, 0x0ebe, # 1921 ~ 1930 |
| 37 | + 0x17d1, 0x1246, 0x0cba, 0x164e, 0x1144, 0x0bb8, 0x14cb, 0x0f3f, 0x18d3, 0x1348, # 1931 ~ 1940 |
| 38 | + 0x0d3b, 0x16cf, 0x11c5, 0x0c39, 0x15cd, 0x1042, 0x0ab6, 0x144a, 0x0e3d, 0x17d1, # 1941 ~ 1950 |
| 39 | + 0x1246, 0x0d3b, 0x164e, 0x10c3, 0x0bb8, 0x154c, 0x0f3f, 0x1852, 0x1348, 0x0dbc, # 1951 ~ 1960 |
| 40 | + 0x16cf, 0x11c5, 0x0c39, 0x15cd, 0x1042, 0x0a35, 0x13c9, 0x0ebe, 0x17d1, 0x1246, # 1961 ~ 1970 |
| 41 | + 0x0d3b, 0x16cf, 0x10c3, 0x0b37, 0x14cb, 0x0f3f, 0x1852, 0x12c7, 0x0dbc, 0x1750, # 1971 ~ 1980 |
| 42 | + 0x11c5, 0x0c39, 0x15cd, 0x1042, 0x1954, 0x13c9, 0x0e3d, 0x17d1, 0x1246, 0x0d3b, # 1981 ~ 1990 |
| 43 | + 0x16cf, 0x1144, 0x0b37, 0x144a, 0x0f3f, 0x18d3, 0x12c7, 0x0dbc, 0x1750, 0x11c5, # 1991 ~ 2000 |
| 44 | + 0x0bb8, 0x154c, 0x0fc1, 0x0ab6, 0x13c9, 0x0e3d, 0x1852, 0x12c7, 0x0cba, 0x164e, # 2001 ~ 2010 |
| 45 | + 0x10c3, 0x0b37, 0x144a, 0x0f3f, 0x18d3, 0x1348, 0x0dbc, 0x1750, 0x11c5, 0x0c39, # 2011 ~ 2020 |
| 46 | + 0x154c, 0x0fc1, 0x0ab6, 0x144a, 0x0e3d, 0x17d1, 0x1246, 0x0cba, 0x15cd, 0x10c3, # 2021 ~ 2030 |
| 47 | + 0x0b37, 0x14cb, 0x0f3f, 0x18d3, 0x1348, 0x0dbc, 0x16cf, 0x1144, 0x0bb8, 0x154c, # 2031 ~ 2040 |
| 48 | + 0x0fc1, 0x0ab6, 0x144a, 0x0ebe, 0x17d1, 0x1246, 0x0cba, 0x164e, 0x1042, 0x0b37, # 2041 ~ 2050 |
| 49 | + 0x14cb, 0x0fc1, 0x18d3, 0x1348, 0x0dbc, 0x16cf, 0x1144, 0x0a38, 0x154c, 0x1042, # 2051 ~ 2060 |
| 50 | + 0x0a35, 0x13c9, 0x0e3d, 0x17d1, 0x11c5, 0x0cba, 0x164e, 0x10c3, 0x0b37, 0x14cb, # 2061 ~ 2070 |
| 51 | + 0x0f3f, 0x18d3, 0x12c7, 0x0d3b, 0x16cf, 0x11c5, 0x0bb8, 0x154c, 0x1042, 0x0ab6, # 2071 ~ 2080 |
| 52 | + 0x13c9, 0x0e3d, 0x17d1, 0x1246, 0x0cba, 0x164e, 0x10c3, 0x0bb8, 0x144a, 0x0ebe, # 2081 ~ 2090 |
| 53 | + 0x1852, 0x12c7, 0x0d3b, 0x16cf, 0x11c5, 0x0c39, 0x154c, 0x0fc1, 0x0a35, 0x13c9, # 2091 ~ 2100 |
| 54 | +] |
| 55 | + |
| 56 | +# ================================================================================== |
| 57 | + |
| 58 | +from datetime import date, datetime |
| 59 | +import calendar |
| 60 | +# 开始年份 |
| 61 | +START_YEAR = 1901 |
| 62 | + |
| 63 | +month_DAY_BIT = 12 |
| 64 | +month_NUM_BIT = 13 |
| 65 | + |
| 66 | +# todo:正月初一 == 春节 腊月二十九/三十 == 除夕 |
| 67 | +yuefeng = ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"] |
| 68 | +riqi = ["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", |
| 69 | + "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "廿十", |
| 70 | + "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"] |
| 71 | + |
| 72 | +xingqi = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] |
| 73 | + |
| 74 | +tiangan = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] |
| 75 | +dizhi = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] |
| 76 | +shengxiao = ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"] |
| 77 | + |
| 78 | +def change_year(num): |
| 79 | + dx = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"] |
| 80 | + tmp_str = "" |
| 81 | + # 将年份 转换为字符串,然后进行遍历字符串 ,将字符串中的数字转换为中文数字 |
| 82 | + for i in str(num): |
| 83 | + tmp_str += dx[int(i)] |
| 84 | + return tmp_str |
| 85 | + |
| 86 | +# 获取星期 |
| 87 | +def week_str(tm): |
| 88 | + return xingqi[tm.weekday()] |
| 89 | + |
| 90 | +# 获取天数 |
| 91 | +def lunar_day(day): |
| 92 | + return riqi[(day - 1) % 30] |
| 93 | + |
| 94 | + |
| 95 | +def lunar_day1(month, day): |
| 96 | + if day == 1: |
| 97 | + return lunar_month(month) |
| 98 | + else: |
| 99 | + return riqi[day - 1] |
| 100 | + |
| 101 | +# 判断是否是闰月 |
| 102 | +def lunar_month(month): |
| 103 | + leap = (month >> 4) & 0xf |
| 104 | + m = month & 0xf |
| 105 | + month = yuefeng[(m - 1) % 12] |
| 106 | + if leap == m: |
| 107 | + month = "闰" + month |
| 108 | + return month |
| 109 | + |
| 110 | +#求什么年份,中国农历的年份和 什么生肖年 |
| 111 | +def lunar_year(year): |
| 112 | + return tiangan[(year - 4) % 10] + dizhi[(year - 4) % 12] + '[' + shengxiao[(year - 4) % 12] + ']' |
| 113 | + |
| 114 | + |
| 115 | +# 返回: |
| 116 | +# a b c |
| 117 | +# 闰几月,该闰月多少天 传入月份多少天 |
| 118 | +def lunar_month_days(lunar_year, lunar_month): |
| 119 | + if (lunar_year < START_YEAR): |
| 120 | + return 30 |
| 121 | + |
| 122 | + leap_month, leap_day, month_day = 0, 0, 0 # 闰几月,该月多少天 传入月份多少天 |
| 123 | + |
| 124 | + tmp = g_lunar_month_day[lunar_year - START_YEAR] |
| 125 | + |
| 126 | + if tmp & (1 << (lunar_month - 1)): |
| 127 | + month_day = 30 |
| 128 | + else: |
| 129 | + month_day = 29 |
| 130 | + |
| 131 | + # 闰月 |
| 132 | + leap_month = (tmp >> month_NUM_BIT) & 0xf |
| 133 | + if leap_month: |
| 134 | + if (tmp & (1 << month_DAY_BIT)): |
| 135 | + leap_day = 30 |
| 136 | + else: |
| 137 | + leap_day = 29 |
| 138 | + |
| 139 | + return (leap_month, leap_day, month_day) |
| 140 | + |
| 141 | + |
| 142 | +# 算农历日期 |
| 143 | +# 返回的月份中,高4bit为闰月月份,低4bit为其它正常月份 |
| 144 | +def get_ludar_date(tm): |
| 145 | + year, month, day = tm.year, 1, 1 |
| 146 | + code_data = g_lunar_year_day[year - START_YEAR] |
| 147 | + days_tmp = (code_data >> 7) & 0x3f |
| 148 | + chunjie_d = (code_data >> 0) & 0x1f |
| 149 | + chunjie_m = (code_data >> 5) & 0x3 |
| 150 | + span_days = (tm - datetime(year, chunjie_m, chunjie_d)).days |
| 151 | + # print("span_day: ", days_tmp, span_days, chunjie_m, chunjie_d) |
| 152 | + |
| 153 | + # 日期在该年农历之后 |
| 154 | + if (span_days >= 0): |
| 155 | + (leap_month, foo, tmp) = lunar_month_days(year, month) |
| 156 | + while span_days >= tmp: |
| 157 | + span_days -= tmp |
| 158 | + if (month == leap_month): |
| 159 | + (leap_month, tmp, foo) = lunar_month_days(year, month) # 注:tmp变为闰月日数 |
| 160 | + if (span_days < tmp): # 指定日期在闰月中 |
| 161 | + month = (leap_month << 4) | month |
| 162 | + break |
| 163 | + span_days -= tmp |
| 164 | + month += 1 # 此处累加得到当前是第几个月 |
| 165 | + (leap_month, foo, tmp) = lunar_month_days(year, month) |
| 166 | + day += span_days |
| 167 | + return year, month, day |
| 168 | + # 倒算日历 |
| 169 | + else: |
| 170 | + month = 12 |
| 171 | + year -= 1 |
| 172 | + (leap_month, foo, tmp) = lunar_month_days(year, month) |
| 173 | + while abs(span_days) >= tmp: |
| 174 | + span_days += tmp |
| 175 | + month -= 1 |
| 176 | + if (month == leap_month): |
| 177 | + (leap_month, tmp, foo) = lunar_month_days(year, month) |
| 178 | + if (abs(span_days) < tmp): # 指定日期在闰月中 |
| 179 | + month = (leap_month << 4) | month |
| 180 | + break |
| 181 | + span_days += tmp |
| 182 | + (leap_month, foo, tmp) = lunar_month_days(year, month) |
| 183 | + day += (tmp + span_days) # 从月份总数中倒扣 得到天数 |
| 184 | + return year, month, day |
| 185 | + |
| 186 | +# 打印 某个时间的农历 |
| 187 | +def _show_month(tm): |
| 188 | + (year, month, day) = get_ludar_date(tm) |
| 189 | + print("%d年%d月%d日" % (tm.year, tm.month, tm.day), week_str(tm), end='') |
| 190 | + print("\t农历 %s年 %s年%s%s " % (lunar_year(year), change_year(year), lunar_month(month), lunar_day(day))) # 根据数组索引确定 |
| 191 | + |
| 192 | +# 判断输入的数据是否符合规则 |
| 193 | +def show_month(year, month, day): |
| 194 | + if year > 2100 or year < 1901: |
| 195 | + return |
| 196 | + if month > 13 or month < 1: |
| 197 | + return |
| 198 | + |
| 199 | + tmp = datetime(year, month, day) |
| 200 | + _show_month(tmp) |
| 201 | + |
| 202 | + |
| 203 | +# 显示现在的日期 |
| 204 | +def this_month(): |
| 205 | + show_month(datetime.now().year, datetime.now().month, datetime.now().day) |
| 206 | + |
| 207 | + |
| 208 | +print('今天的日期是:') |
| 209 | +this_month() |
| 210 | +show_month(2021, 2, 10) |
| 211 | +print(get_ludar_date(datetime.now())) |
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | + |
0 commit comments