Search code examples
pythonpython-3.xpython-datetime

Iterate through a dictionary and modify values


I'm trying to change specific datetime values in a dict into strings by recursively iterating through it's keys.

from copy import deepcopy
def datetoStr2(datadict):
if 'dict' in str(type(datadict)):
    newdict = dict()
    newdict.update(datadict)
    for key in datadict:
        if isinstance(datadict[key], dict):
            newdict[key] = datetoStr(datadict[key])
        if isinstance(datadict[key], list):
            mylist = datadict[key]
            for element in mylist:
                element = datetoStr(element)
        if isinstance(datadict[key], datetime):
        #newdict[key] = datadict[key].strftime('%Y-%m-%d %H:%M:%S.%f%z')
            newdict[key] = str(datadict[key])
    return newdict
else:
    return datadict

However, when I run

some_dict = datetoStr(mydict)

I still have datetime objects in the places as they are. What am I doing wrong?

EDIT: Updated function code.

This function was written because this dict is passed through Flask's jsonify which currently strips the Timezone info and replaces it with GMT. (This is scheduled to be fixed in the next update).

I've updated my function keeping in mind some of the feedback, but I am still unable to produce the result.

I'm adding some sample data and my output as well.

Result:

A quick print inserted in the code tells me the datetime remains a datetime, and TZinfo is stripped out by jsonify.

Sample Data:

{'data': {'all': {'count': 2,
                  'data': [{'arrivalby': 'Wed, 20 Jun 2018 09:39:00 GMT',
                            'closesat': 'Wed, 20 Jun 2018 06:05:40 GMT',
                            'doctype': 'general',
                            'geofence': {'coordinates': [[[78.43786473803105,
                                                           17.447430456650043],
                                                          [78.45670406196896,
                                                           17.447430456650043],
                                                          [78.45670406196896,
                                                           17.46540214334996],
                                                          [78.43786473803105,
                                                           17.46540214334996],
                                                          [78.43786473803105,
                                                           17.447430456650043]]],
                                         'type': 'Polygon'},
                            'housecallid': '591ce42e9b53f96ea393934f61fab25d',
                            'lastupdated': 'Fri, 22 Jun 2018 04:32:14 GMT',
                            'requester': {'addr1': 'xxx xxx xx',
                                          'addr2': 'xx xx xx',
                                          'addr3': 'xx xx',
                                          'addrstate': 'xx',
                                          'city': 'xx',
                                          'dob': 'xx/xx/xxxx',
                                          'email': 'xx@xx',
                                          'fname': 'xxx',
                                          'lname': 'xx',
                                          'location': {'coordinates': [78.4472844,
                                                                       17.4564163],
                                                       'type': 'Point'},
                                          'mobile': xxxx,
                                          'sex': 'xxxx'},
                            'requesttime': 'Wed, 20 Jun 2018 00:05:40 GMT',
                            'responder': {'addr1': 'xxx xxxx',
                                          'addr2': 'xx xx xxxx',
                                          'addr3': 'xxx xx',
                                          'addrstate': 'xxxx',
                                          'city': 'xxxx',
                                          'email': 'xx@xxxx',
                                          'fname': 'xxxx',
                                          'lname': 'xxxx',
                                          'location': {'coordinates': [78.4471904,
                                                                       17.456458],
                                                       'type': 'Point'},
                                          'mobile': xxxx,
                                          'sex': 'xxxx'},
                            'responsetime': 'Wed, 20 Jun 2018 00:09:37 GMT',
                            'status': 'missed'},
                           {'arrivalby': 'Sat, 23 Jun 2018 10:13:00 GMT',
                            'closesat': 'Fri, 22 Jun 2018 10:42:11 GMT',
                            'doctype': 'general',
                            'geofence': {'coordinates': [[[78.43784273760974,
                                                           17.44743855664762],
                                                          [78.45668206239024,
                                                           17.44743855664762],
                                                          [78.45668206239024,
                                                           17.465410243352377],
                                                          [78.43784273760974,
                                                           17.465410243352377],
                                                          [78.43784273760974,
                                                           17.44743855664762]]],
                                         'type': 'Polygon'},
                            'housecallid': '998987171790f172b97a7981a8902af1',
                            'lastupdated': 'Fri, 22 Jun 2018 18:36:50 GMT',
                            'requester': {'addr1': 'xx xxx, ',
                                          'addr2': 'xx xx xxxx',
                                          'addr3': 'xxx xxx',
                                          'addrstate': 'xx',
                                          'city': 'xxxx',
                                          'dob': 'xxxx-xx-xx',
                                          'email': 'xxxx@xxxx',
                                          'fname': 'xx',
                                          'lname': 'xx',
                                          'location': {'coordinates': [78.4472624,
                                                                       17.4564244],
                                                       'type': 'Point'},
                                          'mobile': xxxx,
                                          'sex': 'xxxx'},
                            'requesttime': 'Fri, 22 Jun 2018 04:42:11 GMT',
                            'responder': {'addr1': 'xxxx xxxx',
                                          'addr2': 'xx xx xx',
                                          'addr3': 'xxxx xxxx',
                                          'addrstate': 'xxxx',
                                          'city': 'xxxx',
                                          'email': 'xxx@xxxx',
                                          'fname': 'xxxxx',
                                          'lname': 'xxxx',
                                          'location': {'coordinates': [78.4471904,
                                                                       17.456458],
                                                       'type': 'Point'},
                                          'mobile': xxxx,
                                          'sex': 'xx'},
                            'responsetime': 'Fri, 22 Jun 2018 04:43:05 GMT',
                            'status': 'missed'}]},
          'cancelled': {'count': 0, 'data': []},
          'closed': {'count': 0, 'data': []},
          'confirmed': {'count': 0, 'data': []},
          'missed': {'count': 2,
                     'data': [{'arrivalby': 'Wed, 20 Jun 2018 09:39:00 GMT',
                               'closesat': 'Wed, 20 Jun 2018 06:05:40 GMT',
                               'doctype': 'general',
                               'geofence': {'coordinates': [[[78.43786473803105,
                                                              17.447430456650043],
                                                             [78.45670406196896,
                                                              17.447430456650043],
                                                             [78.45670406196896,
                                                              17.46540214334996],
                                                             [78.43786473803105,
                                                              17.46540214334996],
                                                             [78.43786473803105,
                                                              17.447430456650043]]],
                                            'type': 'Polygon'},
                               'housecallid': '591ce42e9b53f96ea393934f61fab25d',
                               'lastupdated': 'Fri, 22 Jun 2018 04:32:14 GMT',
                               'requester': {'addr1': 'xx xx xxx',
                                             'addr2': 'xx xx xxxx',
                                             'addr3': 'xx xx',
                                             'addrstate': 'xxxxxx',
                                             'city': 'xxxxx',
                                             'dob': 'xx/xx/xxxx',
                                             'email': 'xx@xxx',
                                             'fname': 'xx',
                                             'lname': 'xxx',
                                             'location': {'coordinates': [78.4472844,
                                                                          17.4564163],
                                                          'type': 'Point'},
                                             'mobile': xx,
                                             'sex': 'xx'},
                               'requesttime': 'Wed, 20 Jun 2018 00:05:40 GMT',
                               'responder': {'addr1': 'xx xx',
                                             'addr2': 'xx xx xxxx',
                                             'addr3': 'xx xx',
                                             'addrstate': 'xx',
                                             'city': 'xx',
                                             'email': 'xx@xx',
                                             'fname': 'xx',
                                             'lname': 'xx',
                                             'location': {'coordinates': [78.4471904,
                                                                          17.456458],
                                                          'type': 'Point'},
                                             'mobile': xxxx,
                                             'sex': 'xx'},
                               'responsetime': 'Wed, 20 Jun 2018 00:09:37 GMT',
                               'status': 'missed'},
                              {'arrivalby': 'Sat, 23 Jun 2018 10:13:00 GMT',
                               'closesat': 'Fri, 22 Jun 2018 10:42:11 GMT',
                               'doctype': 'general',
                               'geofence': {'coordinates': [[[78.43784273760974,
                                                              17.44743855664762],
                                                             [78.45668206239024,
                                                              17.44743855664762],
                                                             [78.45668206239024,
                                                              17.465410243352377],
                                                             [78.43784273760974,
                                                              17.465410243352377],
                                                             [78.43784273760974,
                                                              17.44743855664762]]],
                                            'type': 'Polygon'},
                               'housecallid': '998987171790f172b97a7981a8902af1',
                               'lastupdated': 'Fri, 22 Jun 2018 18:36:50 GMT',
                               'requester': {'addr1': 'xxx xxx, ',
                                             'addr2': 'xx xx xxxx',
                                             'addr3': 'xx xx',
                                             'addrstate': 'xxx',
                                             'city': 'xxx',
                                             'dob': 'xxxx-xx-xx',
                                             'email': 'xxxx@xxxx',
                                             'fname': 'xx',
                                             'lname': 'xx',
                                             'location': {'coordinates': [78.4472624,
                                                                          17.4564244],
                                                          'type': 'Point'},
                                             'mobile': xxxxx,
                                             'sex': 'xx'},
                               'requesttime': 'Fri, 22 Jun 2018 04:42:11 GMT',
                               'responder': {'addr1': 'xx xx',
                                             'addr2': 'xx xx xxxx',
                                             'addr3': 'xx xx',
                                             'addrstate': 'xx',
                                             'city': 'xxxx',
                                             'email': 'xxxx@xxxx',
                                             'fname': 'xx',
                                             'lname': 'xx',
                                             'location': {'coordinates': [78.4471904,
                                                                          17.456458],
                                                          'type': 'Point'},
                                             'mobile': xx,
                                             'sex': 'xxxx'},
                               'responsetime': 'Fri, 22 Jun 2018 04:43:05 GMT',
                               'status': 'missed'}]}},  'success': True}

UPDATE - 24 Jun 2018

Thank you, Patrick, for the answer. I have accepted it as the right one.

However, in my edit, I talked about the idea of a list being an element and so I have added the following code (for those looking for a way around the jsonify bug).

def datetoStr(datadict):
    from copy import deepcopy
    # deepcopy before data manipulation
    if 'dict' in str(type(datadict)):
        newdict = deepcopy(datadict)

        for key,value in datadict.items():
            # recurse into nested dicts
            if isinstance(value, dict):
                newdict[key] = datetoStr(datadict[key])
            # convert to string
            elif isinstance(value, datetime):
                newdict[key] = str(datadict[key])
            # if list, iterate through elements and replace
            elif isinstance(datadict[key], list):
                newlist = datadict[key].copy()
                counter = 0
                for element in datadict[key]:
                    newlist[counter] = datetoStr(datadict[key][counter])
                    counter += 1
                newdict[key] = newlist
        return newdict
    else:
        return datadict

Solution

  • You can simplify your code a bit if you use dict.items() which gives you keys and values for iteration directly:

    from copy import deepcopy
    import datetime 
    
    def datetoStr(datadict):
        # deepcopy before data manipulation
        newdict = deepcopy(datadict)
    
        for key,value in datadict.items():
            # recurse into nested dicts
            if isinstance(value, dict):
                newdict[key] = datetoStr(datadict[key])
            # convert to string
            elif isinstance(value, datetime.datetime): 
                newdict[key] = str(datadict[key])
    
        return newdict
    
    
    before = { "a date": datetime.datetime.now(),
               "a dict": { "another": datetime.datetime.now() + datetime.timedelta(hours=2)}}
    
    print(before)
    
    # get the modified copy of before
    transformedDict = datetoStr(before) 
    print(transformedDict)
    

    Output:

    # before        
    {'a date': datetime.datetime(2018, 6, 23, 21, 54, 12, 806419), 
     'a dict': {'another': datetime.datetime(2018, 6, 23, 23, 54, 12, 806421)}}
    
    # transformedDict
    {'a date': '2018-06-23 21:54:12.806419', 
     'a dict': {'another': '2018-06-23 23:54:12.806421'}}