I’m using the Users service, and I noticed that the signed_up and last_login columns in the Users table are set to the time in the UK where Anvil (and its servers) are based. So although I’m the USA (EST), the time is always 5 hours ahead of me. I confirmed that in my app, Python’s date/time functions return different values 5 hours apart based on whether they’re called from a form (i.e. the user’s browser) or in a server module. Is there a way for all date/times to be consistent, or will I simply have to make sure that all date/times I’m computing are done in a form?
We noticed the same thing. Sooner or later, you may need to use timestamps to determine the order or sequence in which events occurred. (E.g., to settle a dispute.) To that end, you are right to standardize on a single time zone. But it’s also important to eliminate Daylight Saving effects.
Not so long ago, thanks to DST, we had a morning with two separate times named “01:30”. Which came first? Will your database entries tell you? Reliably?
To avoid this problem, we are standardizing on UTC. It is unaffected by DST. I suspect that Server Modules use UTC.
Any naive datetime.datetime objects that are transferred between client and server (or vice versa) will have a timezone explicitly set before being sent. When leaving the server, they will be set to UTC, and when leaving the client they will be set to the timezone of the user’s browser.
A combination of a date and a time. Attributes: year, month, day, hour, minute, second, microsecond, and tzinfo.
So you should be able to convert all of them to UTC – or to whatever standard you choose.
Anvil actually takes extreme care with Python
datetime objects, because dealing with timezones is such a minefield. Here’s how it works:
- Any timezone-aware
datetimeobject retains its timezone when transferred in any direction between client, server and Data Tables.
- Any naïve
datetimeobject that is transferred between client and server gets automatically ‘stamped’ with the timezone of the place where it was created before it is transferred. This means that
datetimeobjects generated on the client get the timezone of the browser, while those generated on the server are stamped with the timezone of the server, which is always guaranteed to be UTC (not UK time, which is different in the summer).
These deceptively simple rules mean that you can always compare
datetime objects, no matter where they were created and no matter how much you’ve moved them around or stored them in the DB.
You can explictly create timezone-aware
datetime objects if you wish, using helper classes from the
import anvil.tz naive_local = datetime.now() aware_local = datetime.now(anvil.tz.tzlocal()) naive_utc = datetime.utcnow() aware_utc = datetime.now(anvil.tz.tzutc()) # note: NOT datetime.utcnow() aware_custom = datetime(2017,11,16,23,45,15,0, anvil.tz.tzoffset(hours=3)) print "Naive local: %s" % naive_local print "Aware local: %s" % aware_local print "Naive UTC: %s" % naive_utc print "Aware UTC: %s" % aware_utc print "Aware custom: %s" % aware_custom
I hope that helps!
Thanks for the explanation Ian!
What is it?
Is it documented?
For some reason tz thinks I am in UTC.
print(“You local time zone is”)
You local time zone is
tzlocal(0.0 hour offset)
I’m in California. Thoughts?
Are you running it in Server Modules or in the browser? Server Modules always run in UTC!
Hi @meredydd! It’s a client function but we were tryin’ to do some clever refactoring and imported it to the server library. D’oh!
Having just spent the last few hours dealing with the pains of trying to get all my datetimes consistent. I found this particularly helpful:
Many of the time zone functions (such as pyzt and timezone) do not seem to be very available for a free Anvil account, which made it difficult for me to print EST to the UI when UTC or naive was stored in the data tables. My recommendation for others is to make everything time zone aware by only pulling datetimes from the client (for example: do not run datetime.now(anvil.tz.tzlocal()) on the server and especially do not run datetime.now()). Then, when you want to store the datetime in a data table, transfer this to the server and add it. It is automatically stamped with the local time zone info. This seems to be the only way everything works consistently for me without a huge headache.
A post was split to a new topic: Server-side anvil.tz.tzlocal