This is my first Stackoverflow post, pardon my syntax.
I am trying to have a time stamp in date timestamp without time zone in a SQLAlchemy database display the time in the user's browser with the time in the their timezone, not UTC.
Here is my python/Flask code (I'm a beginner):
First I query the database
timeclockinfo = TimeClock.query.filter_by(parent_id=current_user.parent_id, user_id=current_user.user_id, closed=1).all()
#Then I tuple the data
child_patient = zip(timeclockinfo, user_names, visit_dates )
#I render the data with Flask
return render_template('locationcheckinrpt.html', form=form, child_patient=child_patient, timeclockinfo=timeclockinfo, searchForm=searchForm)
.
.
.
#In the template I have a date time field for the records rendered
{% for times in child_time %}
{{ times[0].checkintime.strftime('%Y/%m/%d # %I:%M %p') }}
{% endfor %}
Can anyone advise me on how to have the UTC times[0].checkintime display in the browser users timezone and not UTC.
I do have the User enter their time zone so I subtract the appropriate number of hours.
But, I cannot hack my way through getting this to display.
If you have the datetime and the user's time zone, you could create a template filter that takes a datetime object, does the required computation, and then prints the string.
If your questions is about actually about applying a time zone to a naive datetime object, then take a look at pytz (relevant section):
from datetime import datetime
from pytz import timezone
tz = timezone('saved_user_timezone')
dt = saved_time_from_db
locl_dt = tz.localize(dt)
To display the datetime with the timezone offset, try:
local_dt.replace(hour=local_dt.hour + int(local_dt.utcoffset().total_seconds() / 3600))
local_dt.strftime('your format')
Related
I'm using PostgreSQL to store an object with a DateTimeField.
The DateTimeField is using auto_now_add options.
And it is created automatically from serializer in Django Rest Framework.
As described in Django docs, I tried to get local timezone and activate it.
from django.utils.timezone import localtime, get_current_timezone
tz = get_current_timezone()
timezone.activate(tz)
session.started_at = localtime(session.started_at)
In template index.html, I also try to load timezone.
{% localtime on %}
Session: start time {{ item.session.started_at }}
{% endlocaltime %}
In settings.py
USE_TZ = True
TIME_ZONE = 'UTC'
I'm using GMT+7 timezone but it still shows UTC time on template.
I'm using Django development server to test.
Am I missing something?
Supposing that all your datetimes are right stored in database as UTC, you can use tz django utility in your template to cast your date to your local time
IE if a datetime is stored as Oct 12, 2017 18:00:00 and i want to convert it to America/La_Paz local time (GMT -4) i can use
Session: start time {{ item.session.started_at|timezone:"America/La_Paz" }}
And in the template will show the local time to America/La_Paz (Oct 12, 2017 14:00:00 in this case)
templates/my_template.html
{% load tz %}
<!-- some html code here -->
Session: start time {{ item.session.started_at|timezone:"America/La_Paz" }}
You can create a cotext var or a var in your view to set the timezone that you wnat to use to cast the date in the tmeplate, ans use it to do the cast
in your view: my_timezone = 'A VALID TIMEZONE NAME'
and again in your template
templates/my_template.html
{% load tz %}
<!-- some html code here -->
Session: start time {{ item.session.started_at|timezone:my_timezone}}
After finding the user's timezone, do this in Django 2 and beyond:
{% load tz %}
{% timezone "Europe/Paris" %}
Paris time: {{ object.date }}
{% endtimezone %}
If I'm not mistaken the TIME_ZONE setting sets the "local" timezone, so change that from UTC to your local time zone.
There is no HTTP-Header that shows the server the client's time zone. Most websites that use localized times ask the user what timezone they are in and save that in the users profile. See Django Documentation
https://docs.djangoproject.com/en/2.0/topics/i18n/timezones/#selecting-the-current-time-zone
Javascript has a way of accessing the UTC offset, maybe you can use that to send the information to your server along with the request.
The users of your webapp may be in different time zones, so the conversion to an appropriate time zone is necessary. You can create a middleware and use activate function to set the current time zone. To get the appropriate time zone you can do an ajax api call to Free IP Geolocation API in your landing page and the time zone value can be saved in a cookie variable which can be later accessed in the middleware.
landingpage.html
<script>
$.ajax({
url: 'https://freegeoip.app/json/',
dataType: 'json',
success: function (data) {
document.cookie = 'timezone=' + data['time_zone'] + '; path=/';
}
});
</script>
middleware.py
import pytz
import requests
from django.utils import timezone
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
tzname = request.COOKIES.get('timezone')
if tzname:
timezone.activate(pytz.timezone(tzname))
else:
timezone.deactivate()
return self.get_response(request)
settings.py
MIDDLEWARE = [ ........
'projectname.middleware.TimezoneMiddleware',
]
The application I am working on has as target users USA. And (as you may know) in USA there's more than one time zone. So I have some doubts:
so how could I get the current time in server side based on the
current user?
And how could I store DateTime data to show the correct time for
every user?
How can I compare times (example: user.event.created > datetime.now())? What timezone will .now() use?
What TIME_ZONE should I set in settings.py file.
This is for an API, to grab user's timezone via JS is not an option. I get the current user via TokenAuthentication.
Use UTC for settings.py and grab their timezone offset from Javascript:
var utcOffset = -((new Date()).getTimezoneOffset()) / 60;
e.g. for Los Angeles right now utcOffset == -7
Unfortunately this doesn't account for Daylight Savings Time changes later (offset changes to -8), so you may have to figure that out at the time of retrieval in order to get Pacific/Los_Angeles. Otherwise you could always just ask the user in a signup form if it's important for your business.
EDIT: Since you're using an API, you could also try using the IPInfoDB API to geolocate based on client IP address. It's not always completely accurate, but almost always enough to get the correct timezone.
Don't use datetime.now(), use the now() function in the timezone module instead.
from django.utils import timezone
now = timezone.now()
Django will figure out which timezone you are in and compare them accordingly.
user.event.created > timezone.now()
https://docs.djangoproject.com/en/1.8/topics/i18n/timezones/
The solution is to always store unix timestamps in the database. You can generate with time.time() . That means your model should have a Floatfield (or even a BigIntegerField depending on the accuracy needed).
Your template should display the numeric value as it is. Then you need a tiny bit of javascript to convert that unix timestamp to a date time.
new Date(unix_timestamp);
The users of your webapp may be in different time zones, so the conversion to an appropriate time zone is necessary. You can create a middleware and use activate function to set the appropriate time zone. You can get the client-side timezone by doing an ajax api call to Free IP Geolocation API in your landing page and the timezone value can be saved in a cookie variable which can be later accessed in the middleware.
landingpage.html
<script>
$.ajax({
url: 'https://freegeoip.app/json/',
dataType: 'json',
success: function (data) {
document.cookie = 'timezone=' + data['time_zone'] + '; path=/';
}
});
</script>
middleware.py
import pytz
import requests
from django.utils import timezone
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
tzname = request.COOKIES.get('timezone')
if tzname:
timezone.activate(pytz.timezone(tzname))
else:
timezone.deactivate()
return self.get_response(request)
settings.py
MIDDLEWARE = [ ........
'projectname.middleware.TimezoneMiddleware',
]
I have a model that has a DateTimeField in it.
class Event(models.Model):
.....
date = models.DateTimeField()
and a model form for this event
class EventForm(ModelForm):
class Meta:
model= Event
When I create an event from admin I set the time to the time I want the event to occure, let's say 19:30. But if I call the events.date property I get
event.date
datetime.datetime(2013, 11, 20, 17, 30, tzinfo=<UTC>)
If I use it in a template like
{{event.date.hour}}:{{event.date.minute}}
it shows 17:30.
But when i load it on template within the model form
event_form = EventForm(instance=event)
and in template
{{event_form.as_p}}
then the date renders the same as I added it in the admin page, that is 19:30
How can I change this behavour. Does django always save in UTC the dates? I am in Greece hence the minus 2 hours (I think) of the datetime object. Supposingly my app will run in many different countries, can I automate this, like when I render the date on a template using the property it will show the time that was actually saved and not the time in UTC. Hope I am making sense....
In my settings file i have
TIME_ZONE = 'Europe/Athens'
USE_TZ = True
If you want time zone per user, you need to store that in your user profiles or something like that. And then use that information to convert user entered time to appropriate UTC to store.
Without that you are storing the times as per the timezone set on your server. So if some user in GMT, selects time as 0800, it will be actually 0800 in Athens not in GMT.
In template you can do
{% load tz %}
{% timezone get_current_users_timezone %}
{{ event.date }}
{% endtimezone %}
Refer django timezones for details info.
I understand that the best practice now with Django 1.4 is to store all datetime in UTC and I agree with that. I also understand that all timezone conversation should be done in the template level like this:
{% load tz %}
{% timezone "Europe/Paris" %}
Paris time: {{ value }}
{% endtimezone %}
However, I need to convert the UTC time to the request's local time all in Python. I can't use the template tags since I am returning the string in JSON using Ajax (more specifically Dajaxice).
Currently this is my code ajax.py:
# checked is from the checkbox's this.value (Javascript).
datetime = timezone.now() if checked else None
$ order_pk is sent to the Ajax function.
order = Order.objects.get(pk=order_pk)
order.time = datetime
order.save()
return simplejson.dumps({
'error': False,
'datetime': dateformat.format(datetime, 'F j, Y, P') if checked else 'None'
})
So even if the current time is April 14, 2012, 5:52 p.m. in EST time (my local timezone), the JSON response will return April 14, 2012, 9:52 p.m, because that is the UTC time.
Also I noticed that Django stores a template variable called TIME_ZONE for each request (not actually part of the request variable), so since my is America/New_York, I'm assuming that Django can figure out each visitor's own local timezone (based on HTTP header)?
Anyway, so my question is two-fold:
How do I get the visitor's local timezone in my ajax.py? (Probably pass it as a string argument like {{ TIME_ZONE }})
With the visitor's local timezone, how to convert the UTC timezone.now() to the local timezone and output as a string using Django's dateformat?
EDIT: for #agf
timezone.now() gives the UTC time when USE_TZ = True:
# From django.utils.timezone
def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
"""
if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower
return datetime.utcnow().replace(tzinfo=utc)
else:
return datetime.now()
Is there anyway to convert a datetime to something other than UTC? For example, can I do something like current_time = timezone.now(), then current_time.replace(tzinfo=est) (EST = Eastern Standard Time)?
You need to read the Django Timezones docs carefully.
One important point:
there's no equivalent of the Accept-Language HTTP header that Django could use to determine the user's time zone automatically.
You have to ask the user what their timezone is or just use a default.
You also need to make sure:
USE_TZ = True
in your settings.py.
Once you have a timezone tz, you can:
from django.utils import timezone
timezone.activate(tz)
datetime = timezone.now() if checked else None
to get a timezone-aware datetime object in timezone tz.
While the browser does not send any headers to the server that would indicate a timezone, the JavaScript environment does know its current timezone.
This has two important effects: While the server can't find out your current timezone on the initial request, you can send down some javascript code which will determine the TZ offset and send that information back to the server so that the zone info can be associated with the current session from that point forward.
But more importantly, if you're sending your time value inside JSON data which will be interpreted by the browser client-side, the browser's timezone doesn't need to be known. Instead, you only have to ensure the timezone offset is present in your JSON output so that the browser can do its own timezone math after-the-fact.
var now = new Date()
var offset_minutes = now.getTimezoneOffset() # e.g. 240 for GMT-0400
Since you want the users' timezones, it makes sense to me that this should be done on the browser with Javascript.
I pass something like this into the template:
{"t": str(obj.timestamp))
Where obj is an instance of a django model where the timestamp field is of type DateTimeField.
The template:
<div class="timestring">{{ t }}</div>
...
<script>
$('.timestring').each(function(){
var d = new Date($(this).text());
$(this).text(d.toLocaleDateString() + ", " + d.toLocaleFormat("%r (%Z)"));
})
</script>
For me, this outputs something like: 2/15/2017, 05:22:24 PM (PST)
The relevant documentation:
Javascript Date class (see especially the constructor which accepts datestrings, and the toLocaleFormat() method)
strftime (comes with lots of date formatting shortcuts)
I am learning how to use Python and Django to produce a small webapp that prints out the current time. I am using this with the Google App Engine.
Right now it's only displaying a blank page, but I want it to display the current time. I also want to map the function to the home page.. not /time/.
from django.http import HttpResponse
from django.conf.urls.defaults import *
import datetime
# returns current time in html
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
def main():
# maps url to current_datetime func
urlpatterns = patterns('',
(r'^time/$', current_datetime),
)
if __name__ == '__main__':
main()
Maybe this documentation is useful to you: Time Zones
Formatting time in a view
You can get the current time using:
import datetime
now = datetime.datetime.now()
or
to get time depending on timezone:
import datetime
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
to format the time you can do:
import datetime
now = datetime.datetime.now().strftime('%H:%M:%S') # Time like '23:12:05'
Formatting time in a template
You can send a datetime to the template, let's supose you send a variable called myDate to the template from the view. You could do like this to format this datetime:
{{ myDate | date:"D d M Y"}} # Format Wed 09 Jan 2008
{{ myDate | date:"SHORT_DATE_FORMAT"}} # Format 09/01/2008
{{ myDate | date:"d/m/Y"}} # Format 09/01/2008
Check the Template filter date
I hope this is useful to you
Use the now template tag. For example:
{% now "jS F Y H:i" %}
but you'll need to send your string through template engine before sending the response for it to work.
For Django code, not in template the support is actually quite simple.
In settings change the timezone:
TIME_ZONE = 'Asia/Kolkata'
And where you need to use, use the following code:
from django.utils import timezone
now = timezone.now()
Source: https://docs.djangoproject.com/en/2.1/topics/i18n/timezones/
You can use time.strftime() for printing the current time. In your urlpatterns, just change '^time/$' to '^/$' to map the root page to your time function.