84 lines
2.0 KiB
Python
84 lines
2.0 KiB
Python
import datetime
|
|
from icalendar import Event, Calendar, Timezone, TimezoneStandard
|
|
|
|
|
|
def create_timezone():
|
|
tz = Timezone()
|
|
tz.add('TZID', 'Asia/Shanghai')
|
|
|
|
tz_standard = TimezoneStandard()
|
|
tz_standard.add('DTSTART', datetime.datetime(1970, 1, 1))
|
|
tz_standard.add('TZOFFSETFROM', datetime.timedelta(hours=8))
|
|
tz_standard.add('TZOFFSETTO', datetime.timedelta(hours=8))
|
|
|
|
tz.add_component(tz_standard)
|
|
return tz
|
|
|
|
|
|
def create_event(event_name, start, end):
|
|
# 创建事件/日程
|
|
event = Event()
|
|
event.add('SUMMARY', event_name)
|
|
|
|
event.add('DTSTART', start)
|
|
event.add('DTEND', end)
|
|
# 创建时间
|
|
event.add('DTSTAMP', start)
|
|
|
|
# UID保证唯一
|
|
event['UID'] = f'{start}/{end}/NateScarlet/holiday-cn'
|
|
|
|
return event
|
|
|
|
|
|
def ranger(lst):
|
|
if len(lst) == 0:
|
|
return []
|
|
|
|
if len(lst) == 1:
|
|
return [(lst[0], lst[0])]
|
|
|
|
fr, to = lst[0], lst[0]
|
|
for cur in lst[1:]:
|
|
if (cur.get('date') - to.get('date')).days == 1 \
|
|
and cur.get('isOffDay') == to.get('isOffDay'):
|
|
to = cur
|
|
else:
|
|
yield fr, to
|
|
fr, to = cur, cur
|
|
yield fr, to
|
|
|
|
|
|
def conv_json_to_ics(data, filename):
|
|
"""
|
|
将爬取的节假日JSON数据转换为ICS
|
|
|
|
Args:
|
|
filename: str
|
|
data: from `fetch_holiday`
|
|
"""
|
|
cal = Calendar()
|
|
cal.add('VERSION', '2.0')
|
|
cal.add('METHOD', 'PUBLISH')
|
|
cal.add('CLASS', 'PUBLIC')
|
|
|
|
cal.add_component(create_timezone())
|
|
|
|
days = data.get('days', [])
|
|
for day in days:
|
|
if isinstance(day.get('date'), str):
|
|
day['date'] = datetime.date(*map(int, day['date'].split('-')))
|
|
|
|
for fr, to in ranger(days):
|
|
start = fr.get('date')
|
|
end = to.get('date') + datetime.timedelta(days=1)
|
|
|
|
name = fr.get('name') + "假期"
|
|
if not fr.get('isOffDay'):
|
|
name = "上班(补" + name + ")"
|
|
cal.add_component(create_event(name, start, end))
|
|
|
|
with open(f'{filename}.ics', 'wb') as ics:
|
|
ics.write(cal.to_ical())
|
|
|