Compare commits

..

1 Commits

Author SHA1 Message Date
Дедов Егор Сергеевич
816c9f1cda Add calendar implementation: models, storage, CLI 2026-05-18 14:51:05 +03:00
6 changed files with 228 additions and 0 deletions

Binary file not shown.

Binary file not shown.

141
calendar_cli.py Normal file
View File

@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""
Personal Calendar - CLI приложение для управления событиями
"""
import sys
from datetime import datetime
from models import Event
from storage import load_events, add_event, remove_event, get_events_by_date
try:
from prettytable import PrettyTable
except ImportError:
print("Ошибка: установите prettytable: pip install prettytable")
sys.exit(1)
def show_menu():
"""Показывает главное меню"""
print("\n" + "=" * 40)
print(" 📅 PERSONAL CALENDAR")
print("=" * 40)
print("1. Добавить событие")
print("2. Показать все события")
print("3. Показать события на дату")
print("4. Удалить событие")
print("5. Выйти")
print("=" * 40)
def add_event_interactive():
"""Интерактивное добавление события"""
print("\n--- Добавление события ---")
title = input("Название: ").strip()
if not title:
print("Ошибка: название не может быть пустым")
return
date = input("Дата (ГГГГ-ММ-ДД): ").strip()
try:
datetime.strptime(date, "%Y-%m-%d")
except ValueError:
print("Ошибка: неверный формат даты")
return
time = input("Время (ЧЧ:ММ) - необязательно: ").strip()
description = input("Описание: ").strip()
event = Event(title, date, time, description)
add_event(event)
print(f"✅ Событие добавлено: {event}")
def show_all_events():
"""Показывает все события в виде таблицы"""
events = load_events()
if not events:
print("\n📭 Нет сохранённых событий")
return
table = PrettyTable()
table.field_names = ["", "Дата", "Время", "Название", "Описание"]
table.align = "l"
for i, event in enumerate(events, 1):
table.add_row([
i,
event.date,
event.time if event.time else "-",
event.title[:30],
event.description[:40] if event.description else "-"
])
print("\n" + str(table))
def show_events_by_date():
"""Показывает события на конкретную дату"""
date = input("\nВведите дату (ГГГГ-ММ-ДД): ").strip()
try:
datetime.strptime(date, "%Y-%m-%d")
except ValueError:
print("Ошибка: неверный формат даты")
return
events = get_events_by_date(date)
if not events:
print(f"\n📭 Нет событий на {date}")
return
print(f"\n📅 События на {date}:")
for i, event in enumerate(events, 1):
print(f" {i}. {event}")
def remove_event_interactive():
"""Интерактивное удаление события"""
show_all_events()
events = load_events()
if not events:
return
try:
index = int(input("\nВведите номер события для удаления: ")) - 1
if remove_event(index):
print("✅ Событие удалено")
else:
print("❌ Неверный номер")
except ValueError:
print("Ошибка: введите число")
def main():
"""Основная функция"""
print("Добро пожаловать в Personal Calendar!")
while True:
show_menu()
choice = input("\nВыберите действие (1-5): ").strip()
if choice == "1":
add_event_interactive()
elif choice == "2":
show_all_events()
elif choice == "3":
show_events_by_date()
elif choice == "4":
remove_event_interactive()
elif choice == "5":
print("\n👋 До свидания!")
break
else:
print("❌ Неверный выбор. Попробуйте снова.")
if __name__ == "__main__":
main()

8
calendar_data.json Normal file
View File

@@ -0,0 +1,8 @@
[
{
"title": "Встреча",
"date": "2026-05-20",
"time": "15:00",
"description": "Созвон с командой"
}
]

35
models.py Normal file
View File

@@ -0,0 +1,35 @@
import json
from datetime import datetime
from typing import List, Optional
class Event:
"""Класс события календаря"""
def __init__(self, title: str, date: str, time: str = "", description: str = ""):
self.title = title
self.date = date # формат YYYY-MM-DD
self.time = time # формат HH:MM
self.description = description
def to_dict(self) -> dict:
"""Преобразует событие в словарь для JSON"""
return {
"title": self.title,
"date": self.date,
"time": self.time,
"description": self.description
}
@classmethod
def from_dict(cls, data: dict) -> 'Event':
"""Создаёт событие из словаря"""
return cls(
title=data["title"],
date=data["date"],
time=data.get("time", ""),
description=data.get("description", "")
)
def __str__(self) -> str:
time_str = f" в {self.time}" if self.time else ""
return f"{self.date}{time_str}: {self.title} - {self.description}"

44
storage.py Normal file
View File

@@ -0,0 +1,44 @@
import json
import os
from typing import List
from models import Event
DATA_FILE = "calendar_data.json"
def load_events() -> List[Event]:
"""Загружает события из JSON файла"""
if not os.path.exists(DATA_FILE):
return []
try:
with open(DATA_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return [Event.from_dict(item) for item in data]
except (json.JSONDecodeError, FileNotFoundError):
return []
def save_events(events: List[Event]) -> None:
"""Сохраняет события в JSON файл"""
with open(DATA_FILE, 'w', encoding='utf-8') as f:
data = [event.to_dict() for event in events]
json.dump(data, f, ensure_ascii=False, indent=2)
def add_event(event: Event) -> None:
"""Добавляет новое событие"""
events = load_events()
events.append(event)
save_events(events)
def remove_event(index: int) -> bool:
"""Удаляет событие по индексу (начиная с 0)"""
events = load_events()
if 0 <= index < len(events):
del events[index]
save_events(events)
return True
return False
def get_events_by_date(date: str) -> List[Event]:
"""Возвращает события на конкретную дату"""
events = load_events()
return [e for e in events if e.date == date]