圖論 圖論是數學的一個分支。它以圖為研究對象。圖論中的圖是由若幹給定的點及連接兩點的線所構成的圖形,這種圖形通常用來描述某些事物之間的某種特定關係,用點代表事物,用連接兩點的線表示相應兩個事物間具有這種關係。 樹 樹是一種數據結構,它是由n(n≥1)個有限節點組成一個具有層次關係的集合。把它叫做“樹 ...
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實現如公眾號提醒、簡訊提醒等
如果覺得文章對你有些幫助,可以在微信公眾號關註:小而美實用Python,獲取更多新鮮文章。