Convert datetime.date object into string

Question:

For each symbol, I have a dictionary as value. They are themselves dictionaries. Each keys of those dictionaries are datetime.date objects. I have to dump that dictionary into json file, but it has to be converted into "%Y-%d-%m" format before. I am quite new in python. This is complicated for me. How can I changed those object into strings?

I know there are similar questions, e.g. dump dictionary with datetime key to json file generating TypeError, but it did not help a lot.

Here is the full dictionary:

{'ARBE': {datetime.date(2023, 2, 21): {'close_gte_next_day_open': False,
                                       'fade_off_all_day': True,
                                       'fade_off_morning': True,
                                       'morning_high_price': 7.61,
                                       'morning_high_time': datetime.time(10, 9),
                                       'morning_low_price': 6.33,
                                       'morning_low_time': datetime.time(11, 36),
                                       'percentage_diff_close_next_day_open': 2.8124999999999956,
                                       'percentage_diff_morning_high_morning_low': -16.81997371879107,
                                       'percentage_diff_open_close': -1.990811638591116,
                                       'percentage_diff_open_morning_high': 16.539050535987748,
                                       'percentage_diff_open_next_day_open': 0.7656967840735042}},
 'BAER': {datetime.date(2023, 2, 24): {'close_gte_next_day_open': True,
                                       'fade_off_all_day': True,
                                       'fade_off_morning': True,
                                       'morning_high_price': 12.45,
                                       'morning_high_time': datetime.time(9, 35),
                                       'morning_low_price': 7.15,
                                       'morning_low_time': datetime.time(10, 56),
                                       'percentage_diff_close_next_day_open': -1.8987341772151944,
                                       'percentage_diff_morning_high_morning_low': -42.57028112449799,
                                       'percentage_diff_open_close': -21.155324011696955,
                                       'percentage_diff_open_morning_high': 24.255217222072506,
                                       'percentage_diff_open_next_day_open': -22.652374821601448}},
 'CELZ': {datetime.date(2023, 2, 8): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 1.42,
                                      'morning_high_time': datetime.time(9, 30),
                                      'morning_low_price': 1.03,
                                      'morning_low_time': datetime.time(11, 27),
                                      'percentage_diff_close_next_day_open': -3.8557692307692326,
                                      'percentage_diff_morning_high_morning_low': -27.464788732394364,
                                      'percentage_diff_open_close': -24.087591240875916,
                                      'percentage_diff_open_morning_high': 3.649635036496337,
                                      'percentage_diff_open_next_day_open': -27.01459854014599}},
 'HILS': {datetime.date(2023, 1, 31): {'close_gte_next_day_open': True,
                                       'fade_off_all_day': True,
                                       'fade_off_morning': False,
                                       'morning_high_price': 1.8,
                                       'morning_high_time': datetime.time(10, 2),
                                       'morning_low_price': 1.28,
                                       'morning_low_time': datetime.time(11, 46),
                                       'percentage_diff_close_next_day_open': -18.333333333333332,
                                       'percentage_diff_morning_high_morning_low': -28.888888888888893,
                                       'percentage_diff_open_close': -3.2258064516129057,
                                       'percentage_diff_open_morning_high': 45.16129032258065,
                                       'percentage_diff_open_next_day_open': -20.967741935483872},
          datetime.date(2023, 2, 10): {'close_gte_next_day_open': False,
                                       'fade_off_all_day': True,
                                       'fade_off_morning': True,
                                       'morning_high_price': 2.65,
                                       'morning_high_time': datetime.time(9, 34),
                                       'morning_low_price': 2.02,
                                       'morning_low_time': datetime.time(11, 19),
                                       'percentage_diff_close_next_day_open': 15.723270440251572,
                                       'percentage_diff_morning_high_morning_low': -23.773584905660375,
                                       'percentage_diff_open_close': -29.646017699115035,
                                       'percentage_diff_open_morning_high': 17.2566371681416,
                                       'percentage_diff_open_next_day_open': -18.584070796460168}},
 'HSCS': {datetime.date(2023, 2, 3): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': False,
                                      'fade_off_morning': True,
                                      'morning_high_price': 3.1699,
                                      'morning_high_time': datetime.time(9, 36),
                                      'morning_low_price': 2.0901,
                                      'morning_low_time': datetime.time(11, 7),
                                      'percentage_diff_close_next_day_open': -13.823529411764698,
                                      'percentage_diff_morning_high_morning_low': -34.06416606202088,
                                      'percentage_diff_open_close': 29.277566539923956,
                                      'percentage_diff_open_morning_high': 20.52851711026617,
                                      'percentage_diff_open_next_day_open': 11.406844106463888}},
 'KPRX': {datetime.date(2023, 2, 7): {'close_gte_next_day_open': False,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 5.89,
                                      'morning_high_time': datetime.time(9, 53),
                                      'morning_low_price': 4.49,
                                      'morning_low_time': datetime.time(12, 0),
                                      'percentage_diff_close_next_day_open': 3.51648351648352,
                                      'percentage_diff_morning_high_morning_low': -23.76910016977928,
                                      'percentage_diff_open_close': -15.74074074074075,
                                      'percentage_diff_open_morning_high': 9.07407407407406,
                                      'percentage_diff_open_next_day_open': -12.777777777777786}},
 'LLAP': {datetime.date(2023, 2, 22): {'close_gte_next_day_open': False,
                                       'fade_off_all_day': False,
                                       'fade_off_morning': False,
                                       'morning_high_price': 3.39,
                                       'morning_high_time': datetime.time(11, 46),
                                       'morning_low_price': 3.03,
                                       'morning_low_time': datetime.time(11, 56),
                                       'percentage_diff_close_next_day_open': 6.484641638225254,
                                       'percentage_diff_morning_high_morning_low': -10.619469026548682,
                                       'percentage_diff_open_close': 0.0,
                                       'percentage_diff_open_morning_high': 15.69965870307167,
                                       'percentage_diff_open_next_day_open': 6.484641638225254}},
 'MOB': {datetime.date(2023, 2, 21): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 2.73,
                                      'morning_high_time': datetime.time(9, 30),
                                      'morning_low_price': 2.1,
                                      'morning_low_time': datetime.time(10, 16),
                                      'percentage_diff_close_next_day_open': -5.479452054794526,
                                      'percentage_diff_morning_high_morning_low': -23.076923076923073,
                                      'percentage_diff_open_close': -16.41221374045802,
                                      'percentage_diff_open_morning_high': 4.198473282442743,
                                      'percentage_diff_open_next_day_open': -20.99236641221375}},
 'RNAZ': {datetime.date(2023, 2, 15): {'close_gte_next_day_open': True,
                                       'fade_off_all_day': True,
                                       'fade_off_morning': True,
                                       'morning_high_price': 0.91,
                                       'morning_high_time': datetime.time(9, 30),
                                       'morning_low_price': 0.7016,
                                       'morning_low_time': datetime.time(10, 30),
                                       'percentage_diff_close_next_day_open': -21.328358208955226,
                                       'percentage_diff_morning_high_morning_low': -22.901098901098905,
                                       'percentage_diff_open_close': -25.348189415041777,
                                       'percentage_diff_open_morning_high': 1.3927576601671383,
                                       'percentage_diff_open_next_day_open': -41.27019498607242}},
 'SECO': {datetime.date(2023, 2, 6): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 5.03,
                                      'morning_high_time': datetime.time(10, 28),
                                      'morning_low_price': 3.37,
                                      'morning_low_time': datetime.time(11, 52),
                                      'percentage_diff_close_next_day_open': -12.73209549071618,
                                      'percentage_diff_morning_high_morning_low': -33.00198807157058,
                                      'percentage_diff_open_close': -1.8229166666666625,
                                      'percentage_diff_open_morning_high': 30.989583333333343,
                                      'percentage_diff_open_next_day_open': -14.322916666666663}},
 'SQL': {datetime.date(2023, 2, 7): {'close_gte_next_day_open': True,
                                     'fade_off_all_day': True,
                                     'fade_off_morning': True,
                                     'morning_high_price': 2.4,
                                     'morning_high_time': datetime.time(9, 41),
                                     'morning_low_price': 1.55,
                                     'morning_low_time': datetime.time(11, 55),
                                     'percentage_diff_close_next_day_open': -14.935064935064934,
                                     'percentage_diff_morning_high_morning_low': -35.416666666666664,
                                     'percentage_diff_open_close': -23.0,
                                     'percentage_diff_open_morning_high': 19.999999999999996,
                                     'percentage_diff_open_next_day_open': -34.5},
         datetime.date(2023, 2, 10): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 2.16,
                                      'morning_high_time': datetime.time(9, 37),
                                      'morning_low_price': 1.66,
                                      'morning_low_time': datetime.time(10, 30),
                                      'percentage_diff_close_next_day_open': -24.909090909090914,
                                      'percentage_diff_morning_high_morning_low': -23.148148148148156,
                                      'percentage_diff_open_close': -34.32835820895521,
                                      'percentage_diff_open_morning_high': 7.462686567164198,
                                      'percentage_diff_open_next_day_open': -50.686567164179095}},
 'TNON': {datetime.date(2023, 2, 15): {'close_gte_next_day_open': True,
                                       'fade_off_all_day': False,
                                       'fade_off_morning': True,
                                       'morning_high_price': 1.67,
                                       'morning_high_time': datetime.time(9, 31),
                                       'morning_low_price': 1.25,
                                       'morning_low_time': datetime.time(10, 0),
                                       'percentage_diff_close_next_day_open': -12.844036697247718,
                                       'percentage_diff_morning_high_morning_low': -25.149700598802394,
                                       'percentage_diff_open_close': 37.106918238993714,
                                       'percentage_diff_open_morning_high': 5.031446540880494,
                                       'percentage_diff_open_next_day_open': 19.496855345911936}},
 'VCNX': {datetime.date(2023, 2, 7): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 0.824,
                                      'morning_high_time': datetime.time(9, 30),
                                      'morning_low_price': 0.62,
                                      'morning_low_time': datetime.time(11, 12),
                                      'percentage_diff_close_next_day_open': -9.375000000000009,
                                      'percentage_diff_morning_high_morning_low': -24.757281553398055,
                                      'percentage_diff_open_close': -22.330097087378633,
                                      'percentage_diff_open_morning_high': 0.0,
                                      'percentage_diff_open_next_day_open': -29.611650485436897}},
 'WLDS': {datetime.date(2023, 2, 9): {'close_gte_next_day_open': True,
                                      'fade_off_all_day': True,
                                      'fade_off_morning': True,
                                      'morning_high_price': 1.29,
                                      'morning_high_time': datetime.time(9, 31),
                                      'morning_low_price': 0.8823,
                                      'morning_low_time': datetime.time(10, 8),
                                      'percentage_diff_close_next_day_open': -8.791208791208799,
                                      'percentage_diff_morning_high_morning_low': -31.604651162790702,
                                      'percentage_diff_open_close': -18.750000000000007,
                                      'percentage_diff_open_morning_high': 15.178571428571422,
                                      'percentage_diff_open_next_day_open': -25.89285714285715}}}
Asked By: David

||

Answers:

The default= argument to json.dumps doesn’t do anything for object keys, so we’ll need to do that ourselves.

Happily, though, we can use a function with the same signature as default expects to transform keys, we’ll just have to write a recursive function for walking a dict and applying it to the keys:

import datetime
import json

data = {
    "HSCS": {
        datetime.date(2023, 2, 3): {
            "close_gte_next_day_open": True,
            "fade_off_all_day": False,
            "fade_off_morning": True,
            "morning_high_price": 3.1699,
            "morning_high_time": datetime.time(9, 36),
            "morning_low_price": 2.0901,
            "morning_low_time": datetime.time(11, 7),
        },
    },
}


def recursive_key_transform(value, key_transform):
    if isinstance(value, dict):
        return {
            key_transform(k): recursive_key_transform(
                v, key_transform
            )
            for k, v in value.items()
        }
    if isinstance(value, list):
        return [
            recursive_key_transform(v, key_transform)
            for v in value
        ]
    return value


def transform(value):
    if isinstance(value, (datetime.date, datetime.time)):
        return value.isoformat()
    return value


print(
    json.dumps(
        recursive_key_transform(data, transform),
        indent=4,
        sort_keys=True,
        default=transform,
    )
)

prints out

{
    "HSCS": {
        "2023-02-03": {
            "close_gte_next_day_open": true,
            "fade_off_all_day": false,
            "fade_off_morning": true,
            "morning_high_price": 3.1699,
            "morning_high_time": "09:36:00",
            "morning_low_price": 2.0901,
            "morning_low_time": "11:07:00"
        }
    }
}
Answered By: AKX
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.