10行代码实现一个值班提醒应用在工作中,我们经常会遇到团队成员需要值班提醒的应用场景。虽然有一些现成的APP可以使用,但是对于程序员来说使用起来难免繁琐,而且可能不是很灵活。那么,我们如何制作一个简单的排班提醒应用呢?考虑一个简单的情况,对约束做如下假设:值班顺序是固定的,一旦确定,每个人固定时间的轮班就不会再修改。例如:每人值班一周。需求假设如下:在合适的时间,提醒值班人员与下一个值班人员同时提醒值班人员。约束和要求转换成代码如下:on_duty_list=['孙悟空','沙僧','猪八戒','白龙马']#值班人员名单on_duty_period_in_days=7#每一周notify_days=[1,5]#假设第一天值班提醒,第五天再提醒一次#第一个值班的人开始on_duty_first_person='孙悟空'on_duty_first_day='2022-03-2400:00:00'#提醒消息模板notify_template=Template(r"""【===========报警值班提醒========】【本周值班人员】${on_duty_person_this_week}【值班时间]${on_duty_range}【下周值班人员】${on_duty_person_next_week}""")如何用程序计算出当前时间应该值班的人?这里用到了简单的数学计算:整数除法和求余数当前时间与第一值班人员开始时间的时间差除以7天得到已经过去了多少周,然后从总数中取余数值班人数获取当前值班人数。defWhoIsOnDuty(timeTs=int(time.time())):ref_timeTs=UnixTimeFromDate(on_duty_first_day)deltaTs=timeTs-ref_timeTsdeltaDay=deltaTs/oneDayTsindex=deltaDay/on_duty_period_in_days%len(on_duty_list)returnon_duty_list[index]如何计算计数器范围呢?这里涉及到简单的日期计算,使用了datetime库defWhoIsOnDuty(timeTs=int(time.time())):ref_timeTs=UnixTimeFromDate(on_duty_first_day)deltaTs=timeTs-ref_timeTsdeltaDay=deltaTs/oneDayTs/indexon_duty_period_in_days%len(on_duty_list)day_index=deltaDay%on_duty_period_in_daysts=time.localtime(timeTs)start_day=str(datetime.date(ts.tm_year,ts.tm_mon,ts.tm_mday)+datetime.timedelta(天数=-day_index))end_day=str(datetime.date(ts.tm_year,ts.tm_mon,ts.tm_mday)+datetime.timedelta(days=-day_index+on_duty_period_in_days-1))返回on_duty_list[index],day_index+1,start_day,end_day,on_duty_list[(index+1)%len(on_duty_list)]这10行代码,是整个应用的核心整个应用代码如下:#!/usr/bin/envpython#coding:utf-8importtimefromstringimportTemplateimportdatetimeon_duty_list=['孙悟空','沙僧','猪八戒','白龙马']on_duty_period_in_days=7#daynotify_days=[1,5]on_duty_first_person='孙悟空'on_duty_first_day='2022-03-2410:00:00'oneDayTs=24*60*60notify_template=Template(r"""【===========报警值班提醒========]【本周值班人员】${on_duty_person_this_week}【值班时间】${on_duty_range}【下周值班人员】${on_duty_person_next_week}""")defSendMessage(message='test'):printmessagedefPairListToMessage(pair_list):conent_arr=[]fork,vinpair_list:conent_arr.append(''.join(['【'+k+'】',v]))return'\n'.join(conent_arr)defUnixTimeFromDate(time_str,format='%Y-%m-%d%H:%M:%S'):#先转为时间数组timeArray=time.strptime(time_str,"%Y-%m-%d%H:%M:%S")#转换为时间戳timeStamp=int(time.mktime(timeArray))returntimeStampdefDatetimeStr(timeTs,format='%Y-%m-%d%H:%M:%S'):返回rntime.strftime(format,time.localtime(timeTs))defWhoIsOnDuty(timeTs=int(time.time())):ref_timeTs=UnixTimeFromDate(on_duty_first_day)deltaTs=timeTs-ref_timeTsdeltaDay=deltaTs/oneDayTs索引=deltaDay/on_duty_period_in_days%len(on_duty_list)day_index=deltaDay%on_duty_period_in_daysts=time.localtime(timeTs)start_day=str(datetime.date(ts.tm_year,ts.tm_mon,ts.tm_mday)+datetime.timedelta(days=-day_index))end_day=str(datetime.date(ts.tm_year,ts.tm_mon,ts.tm_mday)+datetime.timedelta(days=-day_index+on_duty_period_in_days-1))返回on_duty_list[index],day_index+1,start_day,end_day,on_duty_list[(index+1)%len(on_duty_list)]#周四、每周一提醒本周值班员,下周值班员notify_counter=0on_duty_person_this_week=''WhileTrue:timeTs=int(time.time())timeStr=DatetimeStr(timeTs)on_duty_person,day,start_day,end_day,on_duty_person_next=WhoIsOnDuty(timeTs)如果on_duty_person!=on_duty_person_this_week:on_duty_person_this_week=on_duty_personnotify_counter=0SendMessage(notify_template.safe_substitute({'on_duty_person_this_week':on_duty_person,'on_duty_person_next_week':on_duty_person_next,'on_duty_range':'~'.join([start_day,end_day_counter],+}))通知=1否则:如果notify_counter<2和notify_days中的日期:SendMessage(notify_template.safe_substitute({'on_duty_person_this_week':on_duty_person,'on_duty_person_next_week':on_duty_person_next,'on_duty_range':'~'.end_day,))notify_counter+=1次。sleep(1)效果如下:这里提一个问题供读者思考。欢迎评论区交流如何实现临时换班功能?调用第三方API实现如公众号提醒、短信提醒等,如果觉得文章对你有帮助,可以关注微信公众号:小而美的实用Python,获取更多新鲜文章.
