I am using: datetime.now() to get the current time in an Event app that lets you create an event that has an end date, then all of the events are displayed in a calendar and if an event is passed due it is displayed in red.
My issue is that I have some users in different timezones than me saying that the events are ending at the wrong time. They should end at midnight on the day they are due.
I have the timezone setup in my django settings.py. When I use: datetime.now() is that going off of the users local timezone or is it going off of what timezone I have setup in django?
What I want is to find midnight for the users current timezone, so if my method above is wrong, how do I go about doing that?
Thanks
You will need your users to specify their timezone in their user profile. This can then be used to calculate local times correctly.
Check out Relativity of time – shortcomings in Python datetime, and workaround for some good information (and concrete examples).
UPDATE: From Django 1.4 it comes up with timezone support. Check it out.
I worked on a library to work with user timezones transparently. You should just use a Field and some timezone utils and you should get everything converted to the user timezone everytime you do a request or a query.
The library is named django-timezones, and is a modification of the one that Brosner first made.
Give it a try to see if it works for you.
Try storing the UTC Datetime instead then make the necessary adjustments based on the user's timezone:
import datetime
def getUtcNow():
return datetime.datetime(*time.gmtime()[:6])
Related
I have a Django app which needs to support different time zones. I'm saving events to my database which have timestamps and based on those timestamps I want to send notifications. Because the user can move into different time zone, I want to store timestamps as UTC time and convert them to user current time zone later. If I'm correct, PostgreSQL converts datetimes to UTC automatically? At the moment I get an error RuntimeWarning: DateTimeField event.timestamp received a naive datetime (2022-02-15 15:00:00) while time zone support is active.. I used to use Django's make_aware when saving the timestamp and didn't get this warning then. The questions I'd like to get an answer are:
Should I save aware datetimes to the database if I want to support multiple time zones?
What should I use in variables TIME_ZONE and USE_TZ in settings.py? UTC and True?
I store the time zone info to the database, what is the correct method to activate it when I want to get the local time for the user? django.utils.timezone.activate + get_current_timezone or is there some function like astimezone(string_from_db)?
Should I save aware datetimes to the database if I want to support multiple time zones?
The thing that helped me understand timezones is the fact, that time when presented as unix timestamp is a constant and does not depend on where the user is on the globe. Timestamp is saved into Postgres as such. Timezone is just an optional extra information, nothing more. One can take unix timestamp number and transform it into Timezone A, B or whatever he wishes. This depends totally on the request.
Storing timezone information to the database only says that you have to provide timezone when persisting model attribute, otherwise you will get that warning. Warning means that database doesn't know how to treat it and will consider it to be in default timezone, which is usually wrong.
I find it very convenient to store timezone information into the database, but not because it "supports multiple time zones", but because it is less confusing and cleaner. Your users are already in multiple time zones and they are all expecting to see time in their own timezone. If you use timezones, then you don't need to convert to and from UTC and ponder if this number is already converted or not.
I faced issues such as: when a user creates an item, after a single second he sees that an item was created 2 hours ago because you did not include timezone in creation time.
What should I use in variables?
USE_TZ = True
TIME_ZONE = "UTC"
In Django 5.0 the USE_TZ will become True by default.
what is the correct method to get the local time for the user
If you return time values with timezone, the JavaScript easily transforms them to user's timezone by default. If you are using Django templates and all times should appear in different timezone than the user is in, then it is a bit more involved: need to save user's preferred timezone in his profile and activate it with timezone.activate as you correctly pointed out.
I am using flask sqlalchemy and postgreSQL and I have issues with the displayed datetimes, while investigating this issue I found an other weird thing:
Creating a DB entry in incognito mode (chrome browser tab) gives a different/wrong time.
EDIT: It has nothing to do with incognito mode, both cases happen in normal mode aswell. I have not figured out yet why.
This is the code:
I changed the default time zone of my database:
ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';
the model:
class User(UserMixin, Base):
__tablename__ = 'users'
date_added = Column(DateTime(timezone=True), nullable=False)
The method I use to add datetime to DB:
date_added=datetime.today()
How it looks in the DB (my localtime at this time was 13:53:46):
Creating entry not in incognito
timestamp with time zone
2019-02-01 13:53:46.73817+01
Creating entry in incognito
timestamp with time zone
2019-02-01 12:53:46.73817+01
This really makes me worry. It is simply wrong. Even if I would convert the datetime objects to localtime. Both entries have been done at the same time, but show different results, how is this possible?
Also when viewing these dates in HTML, postgreSQL does not apply the offset, so the first date looks correct, but the second is wrong.
Initially I just wanted to find a way to store ALL datetime objects in Europe/Berlin and return them in Europe/Berlin time, so I dont have to convert UTC to Europe/Berlin, but now I think something went horribly wrong.
I also have double checked my code everywhere, I am not using other methods to manipulate datetime objects.
EDIT
I am saving a datetime everytime a user logs in. Currently I tried this on not incognito. My localtime is 14:13:33 BUT it saved into the DB:
2019-02-01 13:13:33.804339+01. How is this even possible? I know it cant be random, but right now it looks like its saving times randomly sometimes UTC with offset and sometimes Europe/Berlin with offset.
EDIT
I double checked all tables in question with SHOW timezone; and they all correctly return Europe/Berlin
datetime.today() returns a timestamp without timezone info of the current local time (the returned value is timezone naive). The root of your problem is that somewhere between SQL Alchemy's postgres adapter and postgres itself it has to guess at a timezone. As you might imagine, computer systems tend toward assuming UTC if no timezone is explicitly provided, but the precise logic for a toolsuite set can be complex and hard to debug (and my depend on your local time zone settings on your computer, system-level settings in the db, session level settings, and the preference of the toolmaker). You can sidestep this entire can of worms by either:
Storing all of your timestamps without a time zone in UTC, then converting to the desired timestamp as appropriate
Always using timestamps with time zone (i.e. replace datetime.today() with datetime.now() and pass in the desired time zone so that you are always dealing with a timezone aware value ), so there is no need for the computer to assume a timezone.
Note that in postgres, the timestamp with time zone type is still always stored as UTC with no extra information, the database simply uses the session-level configuration to decide which time zone to display it as when outputting it.
I am working on Python/Django project. I am trying to let user select date and time using jQuery plugin datetimepicker add-on. So when I select now option and post data django is saving the time in UTC offset. This is what is saved in database, 2017-03-30 13:38:00+00:00. I need to convert this time from user's timezone and save it in system as utc. Because later I will have script running which will look for data in database which is less than the utc time.
Actually the script is to let user post information on website and let them chose the publish date and time. So for example, If use posted an article which will be published on April 2nd 1pm Chicago time, I don't want other users to read the article before this time. So people around the world can read article as soon as it is April 2nd and 1PM in Chicago. So how can I make this functionality work?
My solution was to get the time and remove it's timezone information using replace(tzinfo=pytz.timezone('America/Chicago')) and when I print the time, I am getting 2017-03-30 13:38:00-05:51. The actual offset right now is -05:00. Can anyone help me to and tell me what I am doing wrong?
What I am doing for form is that I have publish_date object in my model and I am using django forms to create form. I have added class as an attribute in it and using jquery plugin,
$('.datepicker').datetimepicker({
timeFormat: 'HH:mm',
stepHour: 1,
stepMinute: 1,
});
So when User submits the form, on post method this my code,
form = PublishForm(request.POST)
if form.is_valid():
f = form.save(commit=False)
f.created_by_user_id = request.user.id
f.save()
and than to get the date all I am doing is f.publish_date and the other options I have used lice replace and localize are pretty standard.
Thanks
As noted in the comments, you appear to have two problems. First is that the datetimepicker is saving a date and time with a UTC timezone offset, when it should be applying a different timezone or leaving off the timezone offset entirely. Second is that pytz is using the wrong offset.
I don't know how to fix the first problem, but I can help you with the second. You need to use pytz's localize function. This only works when the datetime doesn't have a timezone attached, but since you know the timezone is incorrect anyway you can delete it first.
tz = pytz.timezone('America/Chicago')
dt = tz.localize(dt.replace(tzinfo=None))
The naming of the datetime replace(tzinfo = ...) function is unfortunate. In fact, its behaviour is random. Do not use this!
Mark's answer is the way to go. Use localize.
I am working on creating a view that will only display posts whose deadlines dates have not passed. accomplish this I've added the following my views.py file:
current_posts = Posts.objects.filter(post_name=post, deadline__range=[date.today(), "2999-12-31"]).order_by('deadline')
This way I am able to only show posts whose deadline range fall between today and December 31, 2999. However I get the following error, and no posts show at all:
RuntimeWarning: DateTimeField OfferedFunds.deadline received a naive datetime (2999-12-31 00:00:00) while time zone support is active.
RuntimeWarning)
Past solutions posted left me trying the following which also does not work:
timezone.now()
current_posts = Posts.objects.filter(post_name=post, deadline__range=[timezone.now(), "2999-12-31"]).order_by('deadline')
What does work is if instead of entering: timezone.now(), I enter an actual date like "2015-10-10" however this defeats the purpose. Any ideas on how I can solve this?
Instead of checking a range, you can do deadline__gte=timezone.now()
This page has more info: https://docs.djangoproject.com/en/stable/ref/models/querysets/#gte
I actually ran into this problem today at work! Basically the deadline__range=[date.today(), '2999-10-10'] line has a UTC aware time in the first slot and a UTC unaware time in the second slot. Let me guide you to the post that helped me How to make an unaware datetime timezone aware in python. There are some pure python solutions and some django solutions but I think you'll find what you need there!
In your settings.py set USE_TZ = False, so that should fix the warning. In my case I wanted to work with native datetime globally so that's what I ended up doing. Cheers!
I'm building a web application which monitors the up times of friends on facebook in CherryPy (Python Web Framework) and I was wondering how it would be possible to get the time of a facebook user at any given time.
If I need to say that "friend A was online" at a specific time, it would need to match their timezones and hence I've been left a bit stumped.
I played around with the pytz module in python, however had no luck.
At the moment, I am retrieving the "timezone" for a user via the FQL and then adding the timezone value to a database:
user_details = fbconsole.fql("""SELECT uid, timezone, name FROM user WHERE uid = me()""")
I am wondering about a few things:
Is it possible to get the time in which friends are online through Facebook API?
Is it possible to alternatively figure out the time of the client at any given time, through using the timezone offset? (if so, how? I haven't been able to do this yet)
Thank you in advance
I was able to solve this problem myself through the following code:
from datetime import datetime
from pytz import timezone
#set user timezone (GMT +10)
user_timezone = timezone('Etc/GMT+10')
#convert local time to user time
user_timezone_time = user_timezone.localize(datetime.now())
#format in 12hr time (%I for 12 hour time and %p for AM PM clarification)
formatted_user_timezone = user_timezone_time.strftime('%Y-%m-%d %I:%M:%S %p %Z%z')
print formatted_user_timezone
This allowed me to retrieve the timezone field from the "user" field for the Facebook API and then apply it with the code above, to find out the local time of a facebook user.
Thanks! I hope this helps others.