前言
前段時(shí)間在微博看到一段摸魚人的倒計(jì)時(shí)模板,感覺還挺有趣的。

于是我用了一小時(shí)的時(shí)間寫了個(gè)頁面出來 摸魚辦地址 (當(dāng)然是摸魚的時(shí)間啦)。
模板是這樣的:
摸魚辦公室 ??
【摸魚辦公室】今天是 2021-11-30 星期二\
你好,摸魚人,工作再累,一定不要忘記摸魚哦 ! 有事沒事起身去茶水間去廊道去天臺走走,別老在工位上坐著。多喝點(diǎn)水,錢是老板的,但命是自己的 !
?? 距離 周末 放假還有 2 天
?? 距離 元旦 放假還有 3 天
?? 距離 過年 放假還有 34 天
?? 距離 清明節(jié) 放假還有 97 天
?? 距離 勞動節(jié) 放假還有 123 天
?? 距離 端午節(jié) 放假還有 156 天
?? 距離 中秋節(jié) 放假還有 255 天
?? 距離 國慶節(jié) 放假還有 276 天
由于前端是單頁面服務(wù),直接擼一個(gè)原始的html網(wǎng)頁就行。
FastAPI對于異步請求是一把好手、更輕、性能更佳。
掛上一層Nginx讓它看起來像那么回事兒。
實(shí)現(xiàn)過程
首先要知道、除了靜態(tài)文字之外的比如當(dāng)前日期、距離節(jié)日放假的天數(shù)等都是動態(tài)返回的,我需要使用 Jinja2 模板進(jìn)行動態(tài)綁定。
我應(yīng)該把重點(diǎn)放在時(shí)間的處理上。
而且在這個(gè)模板中,有陽歷的節(jié)日,也是陰歷的節(jié)日,我需要轉(zhuǎn)換。
初始化一個(gè) FastAPI 對象并聲明靜態(tài)頁面的模板目錄 (Jinja2Templates)
#?-*-?coding:?utf-8?-*-
import?datetime
from?fastapi?import?FastAPI,?Request
from?fastapi.responses?import?HTMLResponse
from?fastapi.templating?import?Jinja2Templates
from?zhdate?import?ZhDate?as?lunar_date
app?=?FastAPI(
????debug=False,
????title="My?API",
????docs_url="/docs",
????openapi_url=f"/openapi.json"
)
templates?=?Jinja2Templates(directory="templates")
可以看到的是我用到了zhdate這個(gè)庫、主要用于陰歷和陽歷之間的相互轉(zhuǎn)換。用法如下
today?=?datetime.date.today()
print(today.year,?today.month,?today.day)
print("大年時(shí)間:?",?lunar_date(today.year+1,?1,?1).to_datetime().date())
print("端午時(shí)間:?",?lunar_date(today.year,?5,?5).to_datetime().date())
print("中秋時(shí)間:?",?lunar_date(today.year,?8,?15).to_datetime().date())
print("元旦時(shí)間:?",?f"{today.year+1}-01-01")
print("清明時(shí)間:?",?f"{today.year}-04-05")
print("勞動時(shí)間:?",?f"{today.year}-05-01")
print("國慶時(shí)間:?",?f"{today.year}-10-01")
我們可以梳理一下:
計(jì)算距離大年、元旦的天數(shù)時(shí),要在年份上+1
計(jì)算距離其他節(jié)日的天數(shù)時(shí),要判斷天數(shù)差是否小于0,如果是,則年份需要+1,因?yàn)橐呀?jīng)過去的節(jié)日對此沒有意義
distance_big_year?=?(lunar_date(today.year?+?1,?1,?1).to_datetime().date()?-?today).days
distance_5_5?=?(lunar_date(today.year,?5,?5).to_datetime().date()?-?today).days
distance_5_5?=?distance_5_5?if?distance_5_5?>?0?else?(
????????lunar_date(today.year?+?1,?5,?5).to_datetime().date()?-?today).days
distance_8_15?=?(lunar_date(today.year,?8,?15).to_datetime().date()?-?today).days
distance_8_15?=?distance_8_15?if?distance_8_15?>?0?else?(
????????lunar_date(today.year?+?1,?8,?15).to_datetime().date()?-?today).days
distance_year?=?(datetime.datetime.strptime(f"{today.year?+?1}-01-01",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?(datetime.datetime.strptime(f"{today.year}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?distance_4_5?if?distance_4_5?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?(datetime.datetime.strptime(f"{today.year}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?distance_5_1?if?distance_5_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?(datetime.datetime.strptime(f"{today.year}-10-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?distance_10_1?if?distance_10_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-10-01",?"%Y-%m-%d").date()?-?today).days
怎么樣? 我的命名足夠瘋狂吧。 接下來需要計(jì)算一下距離周末的天數(shù)。
def?get_week_day(date):
????week_day_dict?=?{
????????0:?'星期一',
????????1:?'星期二',
????????2:?'星期三',
????????3:?'星期四',
????????4:?'星期五',
????????5:?'星期六',
????????6:?'星期天',
????}
????day?=?date.weekday()
????return?week_day_dict[day]
week_day_?=?get_week_day(today)
print(f"今天是:?{week_day_}")?#?先獲取今天是星期幾
按照每周5個(gè)工作日計(jì)算,今天距離周末的天數(shù)就是
5?-?today.weekday()?#?today.weekday()?今天距離周末
現(xiàn)在將所有的數(shù)據(jù)組裝起來
time_?=?[
????{"v_":?distance_year,?"title":?"元旦"},??#?距離元旦
????{"v_":?distance_big_year,?"title":?"過年"},??#?距離過年
????{"v_":?distance_4_5,?"title":?"清明節(jié)"},??#?距離清明
????{"v_":?distance_5_1,?"title":?"勞動節(jié)"},??#?距離勞動
????{"v_":?distance_5_5,?"title":?"端午節(jié)"},??#?距離端午
????{"v_":?distance_8_15,?"title":?"中秋節(jié)"},??#?距離中秋
????{"v_":?distance_10_1,?"title":?"國慶節(jié)"},??#?距離國慶
]
至于為什么是List而不是Dict,那是我需要做一個(gè)根據(jù)距離天數(shù)的排序,讓最先放假的節(jié)日放于最前面, 這樣看起來會舒服得多。
time_?=?sorted(time_,?key=lambda?x:?x['v_'],?reverse=False)
接下來要寫一個(gè) 路由,將數(shù)據(jù)傳入到html頁面中去。
@app.get("/",?response_class=HTMLResponse)
async?def?readme(request:?Request):
????return?templates.TemplateResponse("readme.html",
??????????????????????????????????????{"request":?request,?"time_":?time_,?"now_":?now_,?"week_day_":?week_day_})
來看一下完整的代碼 (main.py):
#?-*-?coding:?utf-8?-*-
import?datetime
from?fastapi?import?FastAPI,?Request
from?fastapi.responses?import?HTMLResponse
from?fastapi.templating?import?Jinja2Templates
from?zhdate?import?ZhDate?as?lunar_date
app?=?FastAPI(
????debug=False,
????title="My?API",
????docs_url=f"/docs",
????openapi_url=f"/openapi.json"
)
templates?=?Jinja2Templates(directory="templates")
today?=?datetime.date.today()
#?print(today.year,?today.month,?today.day)
#?print("大年時(shí)間:?",?lunar_date(today.year+1,?1,?1).to_datetime().date())
#?print("端午時(shí)間:?",?lunar_date(today.year,?5,?5).to_datetime().date())
#?print("中秋時(shí)間:?",?lunar_date(today.year,?8,?15).to_datetime().date())
#?print("元旦時(shí)間:?",?f"{today.year+1}-01-01")
#?print("清明時(shí)間:?",?f"{today.year+1}-04-05")
#?print("勞動時(shí)間:?",?f"{today.year+1}-05-01")
#?print("國慶時(shí)間:?",?f"{today.year+1}-10-01")
distance_big_year?=?(lunar_date(today.year?+?1,?1,?1).to_datetime().date()?-?today).days
distance_5_5?=?(lunar_date(today.year,?5,?5).to_datetime().date()?-?today).days
distance_5_5?=?distance_5_5?if?distance_5_5?>?0?else?(
????????lunar_date(today.year?+?1,?5,?5).to_datetime().date()?-?today).days
distance_8_15?=?(lunar_date(today.year,?8,?15).to_datetime().date()?-?today).days
distance_8_15?=?distance_8_15?if?distance_8_15?>?0?else?(
????????lunar_date(today.year?+?1,?8,?15).to_datetime().date()?-?today).days
distance_year?=?(datetime.datetime.strptime(f"{today.year?+?1}-01-01",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?(datetime.datetime.strptime(f"{today.year}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_4_5?=?distance_4_5?if?distance_4_5?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-04-05",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?(datetime.datetime.strptime(f"{today.year}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_5_1?=?distance_5_1?if?distance_5_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-05-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?(datetime.datetime.strptime(f"{today.year}-10-01",?"%Y-%m-%d").date()?-?today).days
distance_10_1?=?distance_10_1?if?distance_10_1?>?0?else?(
????????datetime.datetime.strptime(f"{today.year?+?1}-10-01",?"%Y-%m-%d").date()?-?today).days
def?get_week_day(date):
????week_day_dict?=?{
????????0:?'星期一',
????????1:?'星期二',
????????2:?'星期三',
????????3:?'星期四',
????????4:?'星期五',
????????5:?'星期六',
????????6:?'星期天',
????}
????day?=?date.weekday()
????return?week_day_dict[day]
#?print("距離大年:?",?distance_big_year)
#?print("距離端午:?",?distance_5_5)
#?print("距離中秋:?",?distance_8_15)
#?print("距離元旦:?",?distance_year)
#?print("距離清明:?",?distance_4_5)
#?print("距離勞動:?",?distance_5_1)
#?print("距離國慶:?",?distance_10_1)
#?print("距離周末:?",?5?-?today.weekday())
now_?=?f"{today.year}年{today.month}月{today.day}日"
week_day_?=?get_week_day(today)
time_?=?[
????{"v_":?5?-?1?-?today.weekday(),?"title":?"周末"},??#?距離周末
????{"v_":?distance_year,?"title":?"元旦"},??#?距離元旦
????{"v_":?distance_big_year,?"title":?"過年"},??#?距離過年
????{"v_":?distance_4_5,?"title":?"清明節(jié)"},??#?距離清明
????{"v_":?distance_5_1,?"title":?"勞動節(jié)"},??#?距離勞動
????{"v_":?distance_5_5,?"title":?"端午節(jié)"},??#?距離端午
????{"v_":?distance_8_15,?"title":?"中秋節(jié)"},??#?距離中秋
????{"v_":?distance_10_1,?"title":?"國慶節(jié)"},??#?距離國慶
]
time_?=?sorted(time_,?key=lambda?x:?x['v_'],?reverse=False)
@app.get("/",?response_class=HTMLResponse)
async?def?readme(request:?Request):
????return?templates.TemplateResponse("readme.html",
??????????????????????????????????????{"request":?request,?"time_":?time_,?"now_":?now_,?"week_day_":?week_day_})
if?__name__?==?'__main__':
????import?uvicorn
????uvicorn.run(app='main:app',?host="0.0.0.0",?port=8080,?reload=True)
最后就到了html頁面部分了,來看一下主要的傳值。
<center>
????【摸魚辦公室】今天是?{{?now_?}}?{{?week_day_?}}
????<br><br>
????{%?for?v_?in?time_?%}
????????<p>???距離?{{?v_.title?}}?放假還有?{{?v_.v_?}}?天</p>
????{%?else?%}
????????<p>沒有任何值</p>
????{%?endfor?%}
</center>
這樣整個(gè)的路由構(gòu)造和頁面編寫就算是完成了。