preface
Some time ago, I saw a fishing man's countdown template on Weibo. I felt very interesting.
So I spent an hour writing a page to find the address of the Fishing Office (fishing time, of course).
The template is as follows:
Fishing Office 🐟
[Fishing Office] today is Tuesday, November 30, 2021
Hello, fisherman, no matter how tired you are, you must not forget to fish! If you have nothing to do, get up and go to the tea room, the corridor and the roof. Don't always sit on the station. Drink more water. The money belongs to the boss, but the life belongs to you!
🐟 Two days before the weekend holiday
🐟 There are three days before the new year's Day holiday
🐟 There are 34 days before the Chinese New Year holiday
🐟 There are 97 days before the Tomb Sweeping Day holiday
🐟 123 days before Labor Day holiday
🐟 There are 156 days before the Dragon Boat Festival holiday
🐟 There are 255 days before the Mid Autumn Festival holiday
🐟 There are 276 days before the National Day holiday
- Since the front end is a single page service, it is OK to directly create an original html page.
- FastAPI is a good hand for asynchronous requests, lighter and better performance.
- Hang up a layer of Nginx to make it look like that.
Implementation process
- First of all, except for static text, such as the current date and the number of days from the holiday are returned dynamically. I need to use the Jinja2 template for dynamic binding.
- I should focus on dealing with time.
- And in this template, there are both Gregorian and lunar festivals. I need to convert them.
Initialize a FastAPI object and declare the template directory (Jinja2Templates) of the static page
-
# -*- 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")
You can see that I used the zhdate library, which is mainly used for the conversion between the lunar calendar and the Gregorian calendar. The usage is as follows
-
today = datetime.date.today() print(today.year, today.month, today.day) print("New year time: ", lunar_date(today.year+1, 1, 1).to_datetime().date()) print("Dragon Boat Festival time: ", lunar_date(today.year, 5, 5).to_datetime().date()) print("Mid Autumn Festival time: ", lunar_date(today.year, 8, 15).to_datetime().date()) print("New year's day time: ", f"{today.year+1}-01-01") print("Qingming time: ", f"{today.year}-04-05") print("Working hours: ", f"{today.year}-05-01") print("National day time: ", f"{today.year}-10-01")
We can sort out:
- When calculating the number of days from New Year's day and new year's day, add + 1 to the year
- When calculating the number of days from other festivals, judge whether the number of days difference is less than 0. If so, the year needs to be + 1, because the past festivals have no meaning
-
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
how? My name is crazy enough.
Next, you need to calculate the number of days from the weekend.
-
def get_week_day(date): week_day_dict = { 0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday', 4: 'Friday', 5: 'Saturday', 6: 'Sunday', } day = date.weekday() return week_day_dict[day] week_day_ = get_week_day(today) print(f"Today is: {week_day_}") # Get the day of the week first
According to the calculation of five working days per week, the number of days from today to the weekend is
-
5 - today.weekday() # today.weekday() today is the weekend
Now assemble all the data
-
time_ = [ {"v_": distance_year, "title": "New year's Day"}, # Distance from New Year's Day {"v_": distance_big_year, "title": "celebrate the Spring Festival"}, # Distance from the Chinese New Year {"v_": distance_4_5, "title": "the Pure Brightness Festival"}, # Distance to Qingming {"v_": distance_5_1, "title": "labor day"}, # Distance labor {"v_": distance_5_5, "title": "The Dragon Boat Festival"}, # Distance to Dragon Boat Festival {"v_": distance_8_15, "title": "Mid-Autumn Festival"}, # Distance from Mid Autumn Festival {"v_": distance_10_1, "title": "National Day"}, # Distance from National Day ]
As for why it is List instead of Dict, I need to make a ranking according to the distance days, so that the first holiday is placed at the front, which will look much more comfortable.
-
time_ = sorted(time_, key=lambda x: x['v_'], reverse=False)
Next, write a route to transfer the data into the html page.
-
@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_})
Take a look at the complete code (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("big year time:", lunar_date (today. Year + 1, 1, 1) to_ datetime(). date()) # print("Dragon Boat Festival time:", lunar_date (today. Year, 5, 5) to_ datetime(). date()) # print("Mid Autumn Festival time:", lunar_date (today. Year, 8, 15) to_ datetime(). date()) # print("New Year's day time:", f"{today.year+1}-01-01") # print("Qingming time:", f"{today.year+1}-04-05") # print("labor time:", f"{today.year+1}-05-01") # print("national day time:", 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: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday', 4: 'Friday', 5: 'Saturday', 6: 'Sunday', } day = date.weekday() return week_day_dict[day] # print("distance_big_year:", distance_big_year) # print("distance from Dragon Boat Festival:", distance_5_5) # print("distance from Mid Autumn Festival:", distance_8_15) # print("distance from New Year's Day:", distance_year) # print("distance Qingming:", distance_4_5) # print("distance labor:", distance_5_1) # print("distance from National Day:", distance_10_1) # print("distance from weekend:", 5 - today.weekday()) now_ = f"{today.year}year{today.month}month{today.day}day" week_day_ = get_week_day(today) time_ = [ {"v_": 5 - 1 - today.weekday(), "title": "weekend"}, # Distance weekend {"v_": distance_year, "title": "New year's Day"}, # Distance from New Year's Day {"v_": distance_big_year, "title": "celebrate the Spring Festival"}, # Distance from the Chinese New Year {"v_": distance_4_5, "title": "the Pure Brightness Festival"}, # Distance to Qingming {"v_": distance_5_1, "title": "labor day"}, # Distance labor {"v_": distance_5_5, "title": "The Dragon Boat Festival"}, # Distance to Dragon Boat Festival {"v_": distance_8_15, "title": "Mid-Autumn Festival"}, # Distance from Mid Autumn Festival {"v_": distance_10_1, "title": "National Day"}, # Distance from National Day ] 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)
Finally, we'll come to the html page. Let's take a look at the main value transfer.
-
<center> [[Fishing Office] today is {{ now_ }} {{ week_day_ }} <br><br> {% for v_ in time_ %} <p>🐟 distance {{ v_.title }} Holidays and {{ v_.v_ }} day</p> {% else %} <p>No value</p> {% endfor %} </center>
In this way, the whole route construction and page writing are completed.
Finally, it is deployed to my site through Nginx.
Preview address of Fishing Office
The code has been uploaded to the fishing office: