""" Урок 58. Файлы JSON и модуль datetime — весь код примеров одним файлом. Источник: subjects/python-fundamentals/course/lessons/58-json-datetime/examples.html Файл собран автоматически (tools/build_lesson_examples.py): правьте страницу урока. Запуск: python lesson-58.py """ # ==================================================================== # Пример 1. dumps/loads и соответствие типов # ==================================================================== import json data = { "name": "Alice", "age": 25, "is_student": False, "score": None, "tags": ("python", "beginner"), } text = json.dumps(data, ensure_ascii=False) print(text) # {"name": "Alice", "age": 25, "is_student": false, "score": null, "tags": ["python", "beginner"]} restored = json.loads(text) print(type(data["tags"]), type(restored["tags"])) # print(restored) # {'name': 'Alice', 'age': 25, 'is_student': False, 'score': None, 'tags': ['python', 'beginner']} # ==================================================================== # Пример 2. Форматирование: indent, ensure_ascii, sort_keys # ==================================================================== payload = {"b": 2, "a": 1, "city": "Москва"} print(json.dumps(payload)) # {"b": 2, "a": 1, "city": "\u041c\u043e\u0441\u043a\u0432\u0430"} print(json.dumps(payload, sort_keys=True)) # {"a": 1, "b": 2, "city": "\u041c\u043e\u0441\u043a\u0432\u0430"} print(json.dumps(payload, ensure_ascii=False)) # {"b": 2, "a": 1, "city": "Москва"} print(json.dumps(payload, indent=2, sort_keys=True)) # { # "a": 1, # "b": 2, # "city": "\u041c\u043e\u0441\u043a\u0432\u0430" # } # ==================================================================== # Пример 3. Запись и чтение файла # ==================================================================== from pathlib import Path weather = {"city": "Berlin", "temperature": 22.5} path = Path("weather.json") path.write_text(json.dumps(weather, ensure_ascii=False, indent=2), encoding="utf-8") print(path.read_text(encoding="utf-8")) # { # "city": "Berlin", # "temperature": 22.5 # } with path.open(encoding="utf-8") as f: loaded = json.load(f) print(loaded) # {'city': 'Berlin', 'temperature': 22.5} path.unlink() print(path.exists()) # False # ==================================================================== # Пример 4. JSONDecodeError на битом JSON # ==================================================================== bad_variants = [ '{"name": "Alice", "age": 25,}', # лишняя запятая перед } "{'name': 'Alice'}", # одинарные кавычки ] for variant in bad_variants: try: json.loads(variant) except json.JSONDecodeError as error: print(f"Ошибка: {error}") # Ошибка: Expecting property name enclosed in double quotes: line 1 column 29 (char 28) # Ошибка: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) # ==================================================================== # Пример 5. Что JSON не умеет сериализовать: set # ==================================================================== try: json.dumps({"values": {1, 2, 3}}) except TypeError as error: print(f"TypeError: {error}") # TypeError: Object of type set is not JSON serializable print(json.dumps({"values": list({1, 2, 3})})) # {"values": [1, 2, 3]} print(json.dumps({"values": {1, 2, 3}}, default=list)) # {"values": [1, 2, 3]} # ==================================================================== # Пример 6. Вложенные структуры: конфиг с массивом объектов # ==================================================================== config = { "app": "shop", "servers": [ {"host": "api-1", "port": 8000}, {"host": "api-2", "port": 8001}, ], } text = json.dumps(config, indent=2) print(text) # { # "app": "shop", # "servers": [ # { # "host": "api-1", # "port": 8000 # }, # { # "host": "api-2", # "port": 8001 # } # ] # } parsed = json.loads(text) print(parsed["servers"][1]["host"]) # api-2 # ==================================================================== # Пример 7. Создание даты и strftime # ==================================================================== from datetime import datetime launch = datetime(2025, 6, 15, 9, 30) print(launch) # 2025-06-15 09:30:00 print(launch.strftime("%d.%m.%Y %H:%M")) # 15.06.2025 09:30 print(launch.strftime("%A, %d %B %Y")) # Sunday, 15 June 2025 print(launch.weekday()) # 6 — воскресенье (0 = понедельник) # ==================================================================== # Пример 8. strptime: строка → дата, и что будет при несовпадении формата # ==================================================================== deadline = datetime.strptime("01.12.2025", "%d.%m.%Y") print(deadline) # 2025-12-01 00:00:00 try: datetime.strptime("15-06-2025", "%d/%m/%Y") except ValueError as error: print(f"ValueError: {error}") # ValueError: time data '15-06-2025' does not match format '%d/%m/%Y' # ==================================================================== # Пример 9. timedelta: арифметика и сравнение дат # ==================================================================== from datetime import date, timedelta start = datetime(2025, 6, 15) end = start + timedelta(days=14) print(end.strftime("%Y-%m-%d")) # 2025-06-29 difference = deadline - launch print(difference) # 168 days, 14:30:00 print(difference.days) # 168 today = date(2025, 6, 20) print(today > start.date()) # True # ==================================================================== # Пример 10. Наивные и осведомлённые о часовом поясе даты # ==================================================================== from datetime import timezone naive = datetime(2025, 6, 15, 12, 0) aware = datetime(2025, 6, 15, 12, 0, tzinfo=timezone.utc) print(naive.tzinfo) # None print(aware.tzinfo) # UTC try: print(naive < aware) except TypeError as error: print(f"TypeError: {error}") # TypeError: can't compare offset-naive and offset-aware datetimes # ==================================================================== # Пример 11. Совмещаем темы: datetime внутри JSON # ==================================================================== event = {"title": "Deploy", "when": datetime(2025, 6, 15, 9, 30)} try: json.dumps(event) except TypeError as error: print(f"TypeError: {error}") # TypeError: Object of type datetime is not JSON serializable serializable = {**event, "when": event["when"].isoformat()} text = json.dumps(serializable, ensure_ascii=False) print(text) # {"title": "Deploy", "when": "2025-06-15T09:30:00"} restored = json.loads(text) restored["when"] = datetime.fromisoformat(restored["when"]) print(restored) # {'title': 'Deploy', 'when': datetime.datetime(2025, 6, 15, 9, 30)} print(type(restored["when"])) #