Search code examples
pythondatetimetimezonepymongobson

How to ignore timezone when using bson.json_util.loads in python?


I'm dumping and loading bson to text files and my datetimes are having time zone info added to them. I do not want the time zone info added.

import bson, datetime
d1 = datetime.datetime.now()
d2 = bson.json_util.loads(bson.json_util.dumps(d1))

Results in d1:

datetime.datetime(2016, 8, 16, 14, 38, 41, 984544)

and d2 :

datetime.datetime(2016, 8, 16, 14, 56, 10, 155000, tzinfo=<bson.tz_util.FixedOffset object at 0x1042ca050>)

In this particular case I can do

d3 = d2.replace(tzinfo=None)

to remove the timezone. However, I'm doing this for a larger object with times all over the place among other types. Is there a way to instruct bson.json_util.loads to always set tzinfo=None when it tries to parse a datetime?


Solution

  • Interesting. The bson source directly overwrites object_hook so you can't pass in a custom one.

    From the source here:

    def loads(s, *args, **kwargs):
        """Helper function that wraps :class:`json.loads`.
        Automatically passes the object_hook for BSON type conversion.
        """
        kwargs['object_hook'] = lambda dct: object_hook(dct)
        return json.loads(s, *args, **kwargs)
    

    Their source (inside object_hook) is also explicitly setting the timezone, which is causing the behavior that you're seeing:

    aware = datetime.datetime.strptime(
                dt, "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=utc)
    
    if not offset or offset == 'Z':
        # UTC
        return aware
    

    I think you're going to have to do another pass over your resulting data set to remove the time zones, if you absolutely can't have a time zone set.

    EDIT: It looks like there is a pending change to add a JsonOptions class that would allow you to pass tz_aware=False. So if you can wait until the python driver updates to 3.4, you should be able to get your desired behavior.