首页 > 解决方案 > Flask 中的本地客户端时间

问题描述

我有一个带有截止日期的烧瓶待办事项列表应用程序。截止日期基本上是您想要完成待办事项的时间戳。

当当前时间超过待办事项的截止日期时,它会发送推送通知。截止日期以年-月-日时:分(24 小时制)格式输入。它现在在我的机器上运行良好,但如果我将它部署在服务器上,它会将服务器的时间与截止日期进行比较。我想得到客户端/浏览器的时间。我怎样才能做到这一点?

这是我的 Python 代码

@app.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():
    incomplete_todos = Todo.query.filter_by(writer=current_user, complete=False).all()
    complete_todos = Todo.query.filter_by(writer=current_user, complete=True).all()

    return render_template('dashboard.html', incomplete_todos=incomplete_todos, complete_todos=complete_todos, datetime=datetime.datetime.now())

这是我的 HTML/Jinja 代码

{% if datetime >= todo.due_date %}
    <meta http-equiv="refresh">
        <script>
            Push.create("Overdue Todos", {
                tag: 'overdue',
                body: "Your overdue todos are listed below.",
                icon: '../static/todos.png',
                timeout: 5000,
                onClick: function () {
                window.focus();
                this.close();
              }
            });
        </script>
        <i class="fas fa-exclamation-circle important"></i>
        <a class='edit' href="{{ url_for('edit_todo', todo_id=todo.id)}}"><i class="far fa-edit"></i></a>
        <a class='complete' href="{{ url_for('complete_todo', todo_id=todo.id)}}"><i class="far fa-check-square"></i></a>
        <a class='delete' href="{{ url_for('delete_todo', todo_id=todo.id)}}"><i class="far fa-trash-alt"></i></a>
        {% else %}
            <a class='edit' href="{{ url_for('edit_todo', todo_id=todo.id)}}"><i class="far fa-edit"></i></a>
            <a class='complete' href="{{ url_for('complete_todo', todo_id=todo.id)}}"><i class="far fa-check-square"></i></a>
            <a class='delete' href="{{ url_for('delete_todo', todo_id=todo.id)}}"><i class="far fa-trash-alt"></i></a>
        {% endif %}

不要担心 Push.create 的东西,这就是我用来发出推送通知的东西,但我的主要问题是如何在烧瓶中获取客户端/浏览器时间,然后将其放入 html 中进行比较?我也想拥有相同的格式。

标签: pythonflaskweb-applications

解决方案


通常,服务器中的 DateTime 为 UTC,因此最好将所有 DateTime 保存为 UTC。

关于您的问题,如果您将所有 DateTime 存储在 UTC 中,则无需转换为客户端时间来判断任务是否过时。因为如果按照 UTC 顺序它已过时,它将在客户端时间过时,您可以将 UTC 中的待办事项时间与 UTC 中的当前时间进行比较。

所以当客户端在日期时间之间,我们应该在保存之前将其转换为UTC日期时间,但万一我们知道客户端时差。

但是,我们怎样才能得到客户端的 DateTime 差异呢?它与客户端的位置无关,而与客户端的计算机设置有关。

因此,唯一的客户端计算机可以告诉我们时差,这可能是通过使用在客户端浏览器上运行的 javascript 将客户端时差发送到烧瓶服务器。

为了获取客户端时间服务器,我采用了一种间接方式,即要求 Html 页面send_client_time_diff.html将时间差提供给dashboard变量中的视图函数(例如)sent_to="dashboard"

return  render_template('send_client_time_diff.html',sent_to='dashboard')

此 Html 页面具有打开窗口(在同一窗口中重定向)并触发存储在变量中的函数的 javascriptsen_to

send_client_time_diff.html页面的内容是:

<script>
    var date = new Date();
    var diff = date.getTimezoneOffset();
    window.open("{{url_for('receive_client_time_diff')}}?diff="+diff);
</script>

反过来,视图函数dashboard处理参数中发送的时间差diff

我将假设视图功能dashboard如下:

@app.route('/dashboard', methods=['GET', 'POST'])
def dashboard():
    diff = request.args.get('diff', None, type=int)
    server_time = datetime.utcnow()
    client_time = server_time - timedelta(minutes=diff)
    text= f'client datetime : {client_time}  & server datetime : {server_time}'
    return  text

我们应该注意到页面send_client_time_diff.html不等待客户端反应,它会自动重定向以触发视图功能sent_to

但是,如果我们想对相关函数进行修改,如果您存储客户端时间而不转换为 UTC,它将是:

@app.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():

    diff = request.args.get('diff', None, type=int) ###

    incomplete_todos = Todo.query.filter_by(writer=current_user, complete=False).all()
    complete_todos = Todo.query.filter_by(writer=current_user, complete=True).all()

    datetime_client=datetime.datetime.utc_now()-datetime.timedelat(minutes=diff) ###

    return render_template('dashboard.html', incomplete_todos=incomplete_todos, complete_todos=complete_todos, datetime= datetime_client)

期待任何评论


推荐阅读