Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flask: convert utc time to user's local time

I'm trying to convert a UTC time to the appropriate local time in a flask application. I'm wondering if I can detect the user's timezone and dynamically set it.

This is my code so far which works for everyone in the US/Pacific timezone only (datetimefilter pulled from this SO question)

from flask import Flask, render_template_string
import datetime
import pytz

app = Flask(__name__)

@app.template_filter('datetimefilter')
def datetimefilter(value, format='%b %d %I:%M %p'):
    tz = pytz.timezone('US/Pacific')  # timezone you want to convert to from UTC (America/Los_Angeles)
    utc = pytz.timezone('UTC')
    value = utc.localize(value, is_dst=None).astimezone(pytz.utc)
    local_dt = value.astimezone(tz)
    return local_dt.strftime(format)

@app.route('/')
def index():
    dt = datetime.datetime.utcnow()
    return render_template_string(
        '''
        <h4>UTC --> Local Time</h4>
        Datetime right now is:
        <p>{{ dt | datetimefilter }} (utc --> local)</p>
        ''',
        dt=dt, now=now)


if __name__ == '__main__':
    app.run(debug=True)

I imagine this can't be handled server-side because the timezone will always be set to wherever the server is located? Is there a way to handle this by changing datetimefilter?

like image 577
Johnny Metz Avatar asked Dec 02 '17 23:12

Johnny Metz


1 Answers

If you want to dynamically detect user's local time on a website, it's easiest to get browser's datetime via JavaScript Date() object. This way, you can display the correct local time without having to detect anything in the literal sense. Your snippet might look like this:

@app.route('/')
def index():
    dt = datetime.datetime.utcnow()
    return render_template_string(
        '''
        <html><body>
        <h4>UTC --> Local Time</h4>
        Datetime right now is:
        <p>{{ dt | datetimefilter }} (utc)</p>
        <p><span id="timeNow"></span> (local)</p>
        <script>
        var elem = document.getElementById("timeNow")
        var now = new Date();
        var options = { month: 'short', day: '2-digit',
                        hour: 'numeric', minute: '2-digit' };
        elem.innerHTML = now.toLocaleString('en-us', options);
        </script>
        </body></html>
        ''',
        dt=dt)

And it will render following result, depending on the user's local time:

UTC --> Local Time
Datetime right now is:

Dec 02 06:20 PM (utc)

Dec 03, 4:20 PM (local)

Then, if you need to save or process some data depending on the user's local time, you can add another @app.route (with POST-method) to receive that Date() value via AJAX from the website's front-end.

Upon receiving on the back-end side, you probably want to parse javascript Date() object (note, that in this case it's better to use plain getTime() method, instead of toLocaleString() formatting) into Python's datetime, validate it via e.g. webargs/marshmallow, and keep it in, say, user's session.

Please note that similar question has already been answered earlier.

like image 137
user3576508 Avatar answered Oct 05 '22 23:10

user3576508