Teach you how to use Python to create a fishing countdown interface

Posted by ORiGIN on Thu, 06 Jan 2022 01:24:57 +0100

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.

Topics: Python