- Part 0: The Starting Point - What you get out the box from Google App Engine and the Base Python Environment.
- Part 1: Getting Timezone information with pytz
- Part 2: Making the Google App Datastore more consistent by writing a UtcDatetimeProperty class
- Part 3: Handling timezones throughout your application (this post)
Note: I've scaled this post back, mostly since I was being tardy in completing it and also with the realisation that the extra detail I might add would be too specific to my recent experience.
Converting datetimes on input
Sometimes your application will accept as input a user provided date or datetime. In a timezone aware application the working assumption must be that this date is in the user's local timezone. It therefore needs to be converted to UTC for storage.
A handy feature of the datastore datetime property is that as long as your datetime is marked with a specific timezone, the datastore will automatically convert the value to UTC when it is persisted. Once you have parsed your datetime from the input, simply assign the user's timezone before persisting. For example:
user_datetime = parse_datetime(self.request.get('user_date'))
my_model_entity.user_datetime = user_datetime.replace(tzinfo=pytz.timezone(user_timezone_name))
my_model_entity.put()
Of course if you are accepting input from the system time, you do not need to assign a timezone, it is already in UTC, even thought it is a naive datetime.
my_model_entity.log_datetime = datetime.datetime.now()
my_model_entity.put()
Converting dates (only) on input
This is pretty straightforward. There is a situation though where your application would normally only care about dates, but because of your support for timezones you are persisting datetime objects. The user would select a date, say the 10th of January of this year, but when persisting this as a datetime you have a crucial decision to make - what time on the 10th of January should you store? In all situations you will want to set this time prior to converting to UTC. The decision about which time to use is non-trivial since your application will likely want to use the information in the effective manner. The answer will vary from application to application, but a couple of examples might illustrate the point.
In my application My Web Brain, the user can enter a Due Date for a next action that they define. In this application we will be asking one critical question on a regular basis concerning the due date - is the next action overdue? Something is overdue when the due date has past, not during that date, so My Web Brain adds 23 hours and 59 minutes to the due date. This gets converted to UTC when it is persisted, so any Next Action which is overdue can be queried easily by using a condition comparing the due date with the system time.
To provide some contrast, My Web Brain also supports Someday Maybe items with 'tickle dates'. A tickle date is provided by the user to indicate when they should be reminded. In this situation the application will want to find all Someday Maybe items that are due to be 'tickled', and this should include any such item on the same local date the user entered. Therefore, we do not add any amount of time when combining to create a tickle date. Again, since this date was converted to UTC prior to persisted this query is easy for the application to do without knowing the user's local timezone.
Other situations will require other time offsets. Perhaps if a user's work day ends at 5pm, the due date should reflect this. The common thread is that right time offset will depend on the application. Once you have a determined this, the code is easy:
due_date = parse_date (self.request.get('user_date'))
due_datetime = due_date.combine(datetime.time(hours=17))
next_action_entity.duedate = due_datetime.replace(tzinfo=pytz.timezone(user_timezone_name))
next_action_entity.put()
Converting datetimes on output
At the other end of your application you will want to show the user dates and datetimes in their local time. From the datastore you will retrieve datetimes in UTC - these values need to be converted to the user's timezone.
local_duedate = next_action_entity.duedate.astimezone(pytz.timezone(user_timezone_name))
There is nothing overwhelmingly difficult about the above line of code, but you could be forgiven for wondering where in your application it should go. You need to decide if the derived local time of the data should belong to the model, view or controller part of your application:
- If make the conversion to local time a part of the view, you need to share the user's timezone information with the view. The view is often implemented in a templating language like Django templates which out of the box does not provide the capability to do this as a view operation. The best way to use the view in this way would be to define a custom tag for the templating engine, which is not overly difficult.
- You might make the conversion to local time a responsibility of the controller, which after all can access different parts of the model to both find the user's timezone preference and the data with the times to be converted. On the downside, converting the date times and providing them separately (or mixed in to the data) is messy and, in my opinion, increases the coupling between controller and view more than necessary.
- Making the conversion to local time a responsibility of the model is perhaps the easiest approach in the short term. Simple add a method to provide the local time to your entity's class. This has the benefit of making your entities less anemic, but introduces the requirement for one piece of your model to know the user's timezone, which might belong in somewhere else in the model entirely. It can also lead to timezone conversion code duplication across your model.
For My Web Brain I have at the moment chosen to invest the responsibility of converting times to the user's local time to the model, but I wonder if view-based solution would provide more long-term benefits to performance and model design.
Who knew the single line of code converting a time between timezones could require such thinking? Maybe it is only me who can make it so.
Other Questions
There are some other points to cover about using making your application timezone aware. How do you generate a list of timezones for the user to pick from? I have a solution for this, but it isn't elegant. Another good question is how the best way would be to guess the correct timezone for a user. Those who have seen my frequent calls to pytz.timezone() may wonder what the performance penalty is (from what I have read, it is worth looking into).
But- This entry is getting long and I might leave these topics for another occasion. Remember that if you have something to add or something to ask, you are welcome to go ahead and do so. I still have significant learning to do in this area and I will keep you posted when I do.
Hey there, thanks for the great post! I'm trying to figure out how to get the user's timezone programmatically (user_timezone_name).
ReplyDeleteHave any suggestions?
Hi Anekdotz Team - This is something I am interested in too. From my reading there does not appear to be a perfect answer. You can guess the user's timezone using either javascript (to get the browser time and the UTC offset) or via IP Geo Location. Either way you can not be completely sure it is correct. Let me know if you find out anything useful. Thanks for your comment.
ReplyDeletePS. I thought this blog post and comments were useful:
http://mces.blogspot.com/2008/10/timezone-in-http-header.html
Wow what a Great Information about World Day its very nice informative post. thanks for the post. Get online Reviews For Your Business
ReplyDeleteKeep on putting up! You completely match our expectation and the variety of our information. technowalla
ReplyDeleteAll in all, what is the correct method to building the endeavor apps? https://iphoneappdevelopmentcompany.com/ In spite of the fact that the correct approach relies upon the circumstance and methodology, here are some broad rules to construct portable apps for business the correct way.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteAndroid 3 Apps is other free utility to make an android application for your Android contraptions of your decision. It has three straightforward strides to make Android application.
ReplyDeletehttps://appcloner.app
https://appcloner.net
In short, a mobile application will assist you in the promotion and improvement of your business. It will also keep your brand ahead in this race of technology.Mobile app development
ReplyDeleteFree Android App Maker is a standout amongst other free utility to make an android application. Bulk SMS Service Provider in Sharjah UAE
ReplyDeleteOne challenge for enterprise mobile app developers is to ensure the app actually performs well. Other than performance, the app should be bug free and able to operate at minimum battery power.Mobile App development
ReplyDeleteA mobile application is the best marketing and communication tool for any business/company in an inexpensive way. Keeping in mind, the importance of mobile application and its usability, you can either choose Android or iOS.Smart AudioBook Player Download
ReplyDeleteAs an app developer, you must implement a complete mobile application testing strategy to release a bug-free application. However, you can either test the app manually or automate the testing efforts.https://thefrisky.com/how-the-spy-apps-can-help-you-to-keep-a-check-on-the-dishonest-employees/
ReplyDeleteApplications that are produced for Android stage are Android application. Every application when created conveys a wide range of records and envelopes inside it..itools crack
ReplyDeleteA backlink is a link created when one website links to another. Backlinks are important to SEO & impact for higher ranking. In my 7+ years seo Career i see, without backlinks a website doesn't rank higher on google SERP.
ReplyDeleteGet Your 300+ High Quality DoFollow Backlinks Here!
Order Now with Full Confidence & 100% satisfaction.
With Brandsoo, it’s never been easier or more convenient to shop high quality domain names and professional logos that’ll instantly give your brand a leg up and resonate with your audience! With many brandable domain names different domain sellers all competing for your business, you need to know where your business and brand will see.
ReplyDeleteForex Signals, MT4 and MT5 Indicators, Strategies, Expert Advisors, Forex News, Technical Analysis and Trade Updates in the FOREX IN WORLD
ReplyDeleteForex Signals Forex Strategies Forex Indicators Forex News Forex World
Hey! Finally we are launch 150+ High DA Dofollow Quality Backlinks here! Order Now and Boost your website ranking.
ReplyDeleteManual Backlinks | Quality Backlinks | Dofollow Backlinks | High Quality Backlinks
Thank you!
DigiPeek
Shield Security Solutions Offers Security Guard License Training across the province of Ontario. Get Started Today!
ReplyDeleteSecurity Guard License | Security License | Ontario Security license | Security License Ontario | Ontario Security Guard License | Security Guard License Ontario
Thanks for sharing. Nếu cần vận chuyển hàng đi campuchia thì a/c liên hệ bên mình nhé. Hotline: 0903751981
ReplyDeleteKeeping up with Brilyent Kelly. Get Exlcusive offers and see the latest Music and news & Follow me on instragram Celebrity.
ReplyDeleteIt's amaizing information. Thank. Quikads
ReplyDeleteEco technology is the best environmental consulting firm in Bangladesh. To solve all kind of support.
ReplyDelete
ReplyDeleteNurse Practitioner interview questions often focus on clinical knowledge, patient care experience, and critical thinking abilities, aiming to assess candidates' readiness for advanced practice roles. These questions may also explore candidates' communication skills, professionalism, and commitment to continuing education and professional development.
click here