4

I'm looking for a way to store a timezone-aware datetime object in mongoDB.

I read here: Create an ISODate with pyMongo that storing a datetime object in MongoDB with pymongo will result in a ISODate object being stored (or an object that looks like this when querying from the shell)

Using the datetime.replace(tzinfo=[...]) method, there is a way to make the datetime object aware of its timezone. Unfortunately, when storing such object in mongoDB, the timezone information seems to be lost.

My question is: is there a way to store the timezone in the ISODate object itself, so that it looks like something like this: ISODate("2012-07-14T01:00:00+01:00") when querying the shell and so that the datetime object is still timezone aware when reloaded with pymongo later on?

Thanks a lot for your help!

Community
  • 1
  • 1
Romain G
  • 1,276
  • 1
  • 15
  • 27
  • 1
    related: [What is the correct way to handle time zones with PyMongo?](https://api.mongodb.org/python/current/faq.html#what-is-the-correct-way-to-handle-time-zones-with-pymongo) – jfs Sep 02 '15 at 17:37

2 Answers2

5

No, there's not a way to do that. MongoDB's ISODate is just a wrapper around a Date object, which is just a moment in time represented by an integer corresponding to the number of milliseconds elapsed since Jan 1, 1970 UTC. There is no way for it to retain an offset.

You might consider storing it just as a string, perhaps in a secondary field so you can still query for that moment in time while still knowing the local time and offset.

Also, assuming you're using tzdb time zones from either pytz or dateutil, such as "Europe/London", you should recognize that there's no way to determine a time zone from just an offset. So if you really need to reconstruct a full tz aware datetime, then you'll also have to store the time zone identifier in a separate field.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • moreover, ISODate + "Europe/London" is not enough to restore the local time if the timezone rules have changed between tzdata versions i.e., if you want the local time as is then store the timezone info (utc offset, tzname) explicitly. – jfs Sep 02 '15 at 17:36
  • note: `tz_aware=True` makes the driver return utc time as an aware datetime object. To get the local time: `utc_time.astimezone(pytz.timezone('Europe/London'))` (note: it uses timezone rules corresponding to the install `pytz` version) – jfs Sep 02 '15 at 17:40
  • This makes a lot of sense, thank you guys. I was hoping to be able to perform timezone aware mongodb queries using the Date Aggregation Operators by having a single ISODate field. But it seems now that I have no other choice than storing the offset in a separate field (to be used in the query), and the timezone identifier in another field to keep the datetime object timezone aware once the data are retrieved by the application server. – Romain G Sep 03 '15 at 11:10
0
from datetime import datetime
from dateutil.tz import *

def to_utc(date_time):
    return date_time.replace(tzinfo=tzlocal()).astimezone(tzoffset(None, 0))
tnusraddinov
  • 660
  • 7
  • 13