10行代码实现一个值班提醒应用
工作当中,经常遇到团队成员需要值班排班及提醒的应用场景。虽然,有一些现成的APP可以用,但是对程序员来讲使用起来不免有些繁琐,而且可能不太灵活。
那么,我们如何手撸一个简单值班排班及提醒的应用呢?
考虑一种简单的情况,对约束做如下假设:
- 值班顺序固定,一旦确定下来不再修改
- 每人值固定时间的班,比如:每人值一周
对需求假设如下:
- 在合适的时间,提醒值班人值班时间
- 提醒值班人的同时预告下一个值班人
约束和需求转化为代码如下:
on_duty_list = ['孙悟空', '沙和尚', '猪八戒', '白龙马'] # 值班人列表
on_duty_period_in_days = 7 # 每人值一周
notify_days = [1, 5] # 假设值班第一天提醒一次,第5天再提醒一次
# 第一个值班人值班开始时间
on_duty_first_person = '孙悟空'
on_duty_first_day = '2022-03-24 00:00:00'
# 提醒消息模板
notify_template = Template(r"""
【===========报警值班提醒========】
【本周值班人】${on_duty_person_this_week}
【值班时间】 ${on_duty_range}
【下周值班人】${on_duty_person_next_week}
""")
如何用程序来计算当前时间应该是哪个人值班呢?
这里用到简单数学计算:整除、取余运算
当前时间与首个值班人值班开始时间的时间差整除7天得到过了多少周,然后再对总值班人数取余,得到当前应该是第几个值班人值班。
def WhoIsOnDuty(timeTs = int(time.time())):
    ref_timeTs = UnixTimeFromDate(on_duty_first_day)
    deltaTs = timeTs - ref_timeTs
    deltaDay = deltaTs / oneDayTs
    index = deltaDay / on_duty_period_in_days % len(on_duty_list)
    return on_duty_list[index]
如何计算值班时间范围呢?
这里涉及到简单的日期计算,使用了datetime库
def WhoIsOnDuty(timeTs = int(time.time())):
    ref_timeTs = UnixTimeFromDate(on_duty_first_day)
    deltaTs = timeTs - ref_timeTs
    deltaDay = deltaTs / oneDayTs
    index = deltaDay / on_duty_period_in_days % len(on_duty_list)
    day_index = deltaDay % on_duty_period_in_days
    ts = 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))
    return on_duty_list[index], day_index + 1, start_day, end_day, on_duty_list[(index+1)%len(on_duty_list)]
这10行代码,是整个应用的核心。
整个应用代码如下:
#!/usr/bin/env python
# coding: utf-8
import time
from string import Template
import datetime
on_duty_list = ['孙悟空', '沙和尚', '猪八戒', '白龙马']
on_duty_period_in_days = 7 # day
notify_days = [1, 5]
on_duty_first_person = '孙悟空'
on_duty_first_day = '2022-03-24 10:00:00'
oneDayTs = 24 * 60 * 60
notify_template = Template(r"""
【===========报警值班提醒========】
【本周值班人】${on_duty_person_this_week}
【值班时间】 ${on_duty_range}
【下周值班人】${on_duty_person_next_week}
""")
def SendMessage(message='test'):
    print message
def PairListToMessage(pair_list):
    conent_arr = []
    for k, v in pair_list:
        conent_arr.append(' '.join(['【' + k + '】', v]))
    return '\n'.join(conent_arr)
def UnixTimeFromDate(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))
    return timeStamp
def DatetimeStr(timeTs, format='%Y-%m-%d %H:%M:%S'):
    return time.strftime(format, time.localtime(timeTs))
def WhoIsOnDuty(timeTs = int(time.time())):
    ref_timeTs = UnixTimeFromDate(on_duty_first_day)
    deltaTs = timeTs - ref_timeTs
    deltaDay = deltaTs / oneDayTs
    index = deltaDay / on_duty_period_in_days % len(on_duty_list)
    day_index = deltaDay % on_duty_period_in_days
    ts = 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))
    return on_duty_list[index], day_index + 1, start_day, end_day, on_duty_list[(index+1)%len(on_duty_list)]
# 周四、每周一提醒本周值班人员,下周值班人员
notify_counter = 0
on_duty_person_this_week = ''
While True:
    timeTs = int(time.time())
    timeStr = DatetimeStr(timeTs)
    on_duty_person, day, start_day, end_day, on_duty_person_next = WhoIsOnDuty(timeTs)
    if on_duty_person != on_duty_person_this_week:
        on_duty_person_this_week = on_duty_person
        notify_counter = 0
        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': '~'.join([start_day, end_day]),
        }))
        notify_counter += 1
    else:
        if notify_counter < 2 and day in 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': '~'.join([start_day, end_day]),
            }))
            notify_counter += 1
    time.sleep(1)
效果如下:
这里留个思考题给读者,欢迎评论区交流。
- 如何实现临时调班的功能?
- 调用第三方API实现如公众号提醒、短信提醒等
点击查看更多内容
					为 TA 点赞
										
				 评论
				共同学习,写下你的评论
评论加载中...
作者其他优质文章
					正在加载中
				
			感谢您的支持,我会继续努力的~
		扫码打赏,你说多少就多少
		赞赏金额会直接到老师账户
		支付方式
		打开微信扫一扫,即可进行扫码打赏哦
	 
                 
            


 
			 
					 
					