Compare commits
2 Commits
b233c6caf4
...
c4a7901fcf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4a7901fcf | ||
|
|
a663f47b96 |
103
test_s/csv_to_ics.py
Normal file
103
test_s/csv_to_ics.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import csv
|
||||||
|
import hashlib
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
|
def generate_uid(full_name: str, domain: str = "mupts.local") -> str:
|
||||||
|
"""
|
||||||
|
Генерирует стабильный уникальный идентификатор (UID) на основе ФИО.
|
||||||
|
"""
|
||||||
|
if not full_name:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# 1. Нормализация: нижний регистр и удаление двойных пробелов
|
||||||
|
clean_name = " ".join(full_name.strip().lower().split())
|
||||||
|
|
||||||
|
# 2. Хеширование: используем MD5 (он быстрый и короткий)
|
||||||
|
# Берем первые 16 символов хеша — этого более чем достаточно для избежания коллизий в рамках компании
|
||||||
|
name_hash = hashlib.md5(clean_name.encode('utf-8')).hexdigest()[:16]
|
||||||
|
|
||||||
|
# 3. Формирование формата UID (по стандарту RFC 5545 рекомендуется формат id@domain)
|
||||||
|
return f"{name_hash}@{domain}"
|
||||||
|
|
||||||
|
def csv_to_ics(csv_file_path, ics_file_path):
|
||||||
|
ics_content = [
|
||||||
|
"BEGIN:VCALENDAR",
|
||||||
|
"VERSION:2.0",
|
||||||
|
"PRODID:-//MUT_TS//Birthdays//RU",
|
||||||
|
"CALSCALE:GREGORIAN"
|
||||||
|
]
|
||||||
|
|
||||||
|
# with open(csv_file_path, mode='r', encoding='utf-8') as file:
|
||||||
|
with open(csv_file_path, mode='r', encoding='windows-1251') as file:
|
||||||
|
# Предполагаем, что разделитель - запятая. Если точка с запятой, измените на delimiter=';'
|
||||||
|
reader = csv.DictReader(file, delimiter=';')
|
||||||
|
|
||||||
|
for row in reader:
|
||||||
|
# Извлекаем данные (замените ключи на названия ваших колонок в CSV)
|
||||||
|
name = row.get('Subject', '').strip()
|
||||||
|
date_str = row.get('Start Date', '').strip().rstrip('.') # убираем случайные точки на конце
|
||||||
|
desckription = row.get('Description', '').strip()
|
||||||
|
location = row.get('Location', '').strip()
|
||||||
|
# phone = row.get('Телефон', '').strip()
|
||||||
|
# address = row.get('Адрес', '').strip()
|
||||||
|
|
||||||
|
if not name or not date_str:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Парсим оригинальную дату (например, 18.06.1964)
|
||||||
|
start_date = datetime.strptime(date_str, "%d.%m.%Y")
|
||||||
|
# Для событий на весь день дата окончания должна быть следующим днем
|
||||||
|
end_date = start_date + timedelta(days=1)
|
||||||
|
|
||||||
|
dtstart = start_date.strftime("%Y%m%d")
|
||||||
|
dtend = end_date.strftime("%Y%m%d")
|
||||||
|
|
||||||
|
# Формируем блок события
|
||||||
|
ics_content.append("BEGIN:VEVENT")
|
||||||
|
ics_content.append(f"UID:{generate_uid(name)}")
|
||||||
|
ics_content.append(f"SUMMARY:День рождения: {name}")
|
||||||
|
ics_content.append(f"DTSTART;VALUE=DATE:{dtstart}")
|
||||||
|
ics_content.append(f"DTEND;VALUE=DATE:{dtend}")
|
||||||
|
ics_content.append("RRULE:FREQ=YEARLY")
|
||||||
|
ics_content.append(f"DESCRIPTION:{desckription}")
|
||||||
|
ics_content.append(f"LOCATION:{location}")
|
||||||
|
ics_content.append("TRANSP:TRANSPARENT")
|
||||||
|
ics_content.append("STATUS:CONFIRMED")
|
||||||
|
ics_content.append("CLASS:PUBLIC")
|
||||||
|
ics_content.append("CATEGORIES:Дни рождения,МУП ТС")
|
||||||
|
ics_content.append("CLASS:PUBLIC")
|
||||||
|
# Первое напоминание: за 1 день (в стандартное время календаря, обычно 09:00 или 18:00 предыдущего дня)
|
||||||
|
ics_content.append("BEGIN:VALARM")
|
||||||
|
ics_content.append("ACTION:DISPLAY")
|
||||||
|
ics_content.append("DESCRIPTION:Завтра день рождения коллеги!")
|
||||||
|
ics_content.append("TRIGGER:-P1D")
|
||||||
|
ics_content.append("END:VALARM")
|
||||||
|
|
||||||
|
# Второе напоминание: в сам день в 07:30 (через 7 часов 30 минут после полуночи)
|
||||||
|
ics_content.append("BEGIN:VALARM")
|
||||||
|
ics_content.append("ACTION:DISPLAY")
|
||||||
|
ics_content.append("DESCRIPTION:Сегодня день рождения!")
|
||||||
|
ics_content.append("TRIGGER:PT7H30M")
|
||||||
|
ics_content.append("END:VALARM")
|
||||||
|
|
||||||
|
ics_content.append("END:VEVENT")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
# Пропускаем строки с некорректным форматом даты
|
||||||
|
print(f"Ошибка парсинга даты для: {name} ({date_str})")
|
||||||
|
continue
|
||||||
|
|
||||||
|
ics_content.append("END:VCALENDAR")
|
||||||
|
|
||||||
|
# Записываем всё в .ics файл
|
||||||
|
with open(ics_file_path, mode='w', encoding='utf-8', newline='') as ics_file:
|
||||||
|
ics_file.write("\n".join(ics_content))
|
||||||
|
|
||||||
|
|
||||||
|
# Запуск конвертации
|
||||||
|
csv_to_ics('1.csv', 'birthdays.ics')
|
||||||
|
print("Файл birthdays.ics успешно создан!")
|
||||||
24
test_s/test.py
Normal file
24
test_s/test.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import csv
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
|
def csv_to_ics(csv_file_path):
|
||||||
|
ics_content = [
|
||||||
|
"BEGIN:VCALENDAR",
|
||||||
|
"VERSION:2.0",
|
||||||
|
"PRODID:-//MUT_TS//Birthdays//RU",
|
||||||
|
"CALSCALE:GREGORIAN"
|
||||||
|
]
|
||||||
|
|
||||||
|
with open(csv_file_path, mode='r', encoding='utf-8') as file:
|
||||||
|
# Предполагаем, что разделитель - запятая. Если точка с запятой, измените на delimiter=';'
|
||||||
|
reader = csv.DictReader(file, delimiter=';')
|
||||||
|
|
||||||
|
|
||||||
|
return reader
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Запуск конвертации
|
||||||
|
print(list(csv_to_ics('1.csv')))
|
||||||
|
print("Файл birthdays.ics успешно создан!")
|
||||||
Reference in New Issue
Block a user