¿Cómo generar calendarios con Python?
Categoría: Python
Autor: Ing. Gustavo Gómez Macías (Goz)
Publicado: 10 de Febrero de 2025
Existen distintas maneras para generar calendarios, generalmente aprovechamos alguna API como la de Google Calendar o alguna biblioteca JS pero...
Te muestro otra opción muy muy sencilla que puede ayudarte en algún proyecto: Calendar View.
https://github.com/sakhnevych/calendar-view
Desarrollada por Oleksandr Sakhnevych
Calendar View practicamente funciona de la siguiente manera:
1. Instalamos Calendar View: pip install calendar-view
2. Importamos nuestra biblioteca
3. Configuramos un objeto Calendario
4. Creamos una lista de "n" objetos Evento
5. Validamos la configuración del Calendario y los objetos Evento
5. Creamos el objeto Calendario
6. Agregamos nuestros objetos Evento al objeto Calendario
7. Guardamos el resultado en formato .png
Hice una prueba con mi actividades para la siguiente semana y no quedó nada mal.
Además podemos configurar el calendario con los siguientes parámetros:
lang(str) - Idioma para el nombre del día: en, es, de, us, ru, pt
title(str) - Título de la vista, puede estár vacío
dates(str) - El rango de días a mostrar. Default 'Mo-Su'
days(int) - Si days no existe entonces el número de días a mostrar puede ser configurado para iniciar desde el lunes
hours(str) - Rango de horas a mostrar
mode(str) - Mode cambia algunos parámetros:
week: muestra la semana actual
day_hours: muestra horas en el rango '8:00-22:00'
working_hours: muestra horas en el rango '8:00-19:00'
auto: odos 'week'+'day_hours'
show_date(bool) - Define como la fecha debe ser mostrada. Formato 'dd.mm' o 'dd.mm.YYY' si show_year=True
legend(bool) - Si es falso presenta el nombre del evento dentro del bloque. Si es verdadero presenta el nombre del legend.
title_vertical_align(str) - La alineación vertical del title y anotado en el evento del calendario: top, center, bottom
Podemos configurar los eventos con los siguientes parámetros:
title(str) - Título del evento
notes(str) - Las notas que son impresas debajo del título
day(str/date/datetime) - Día del evento puede ser definido con cualquiera de los tres tipos o se puede usar day_of_week
day_of_week(int) - El rango de días a mostrar, no se puede usar con day
start(str/time/datetime) - Inicio del evento puede ser HH:mm o HH
end(str/time/datetime) - Fin del evento puede ser HH:mm o HH
Les dejo mi ejemplo de script para que puedan probar la biblioteca.
###################################################################
# Programa para generar calendarios con Calendar View
# Autor: Gustavo Gómez Macías (Goz)
# Tutoriales Code With Goz
###################################################################

# Importamos todo lo que necesitamos de Calendar View
from calendar_view.calendar import Calendar
from calendar_view.core import data
from calendar_view.core.event import Event
from calendar_view.core.event import EventStyles
from calendar_view.config import style

# Configuración de nuestro calendario
style.hour_height = 80
style.event_notes_color = '#000'
config = data.CalendarConfig(
    lang = 'es',
    title = 'Code With Goz (2025-1)',
    dates = '2025-02-17 - 2025-02-23',
    show_year = True,
    legend = False,
    mode = 'day_hours',
    title_vertical_align = 'top',
)

# Creamos una lista de objetos Event
events = [
    Event('Curso Web Scraping Python', day='2025-02-17', 
          start='19:00', end='21:00', 
          style=EventStyles.BLUE, 
          notes='Primera Clase del Curso'),
    Event('Curso Python desde Cero', day='2025-02-18', 
          start='19:00', end='21:00', 
          style=EventStyles.GREEN, 
          notes='Primera Clase del Curso'),
    Event('Curso Web Scraping Python', day='2025-02-19', 
          start='19:00', end='21:00', 
          style=EventStyles.BLUE, 
          notes='Segunda Clase del Curso'),
    Event('Curso Python desde Cero', day='2025-02-20', 
          start='19:00', end='21:00', 
          style=EventStyles.GREEN, 
          notes='Segunda Clase del Curso'),
    Event('Desarrollo Freelance y Proyectos', day='2025-02-17', 
          start='9:00', end='14:00', style=EventStyles.RED),
    Event('Desarrollo Freelance y Proyectos', day='2025-02-18', 
          start='9:00', end='14:00', style=EventStyles.RED),
    Event('Desarrollo Freelance y Proyectos', day='2025-02-19', 
          start='9:00', end='14:00', style=EventStyles.RED),
    Event('Desarrollo Freelance y Proyectos', day='2025-02-20', 
          start='9:00', end='14:00', style=EventStyles.RED),
    Event('Desarrollo Freelance y Proyectos', day='2025-02-21', 
          start='9:00', end='14:00', style=EventStyles.RED),
    Event('Comida/Descanso/Familia', day='2025-02-17', 
          start='14:00', end='17:00', style=EventStyles.GRAY),
    Event('Comida/Descanso/Familia', day='2025-02-18', 
          start='14:00', end='17:00', style=EventStyles.GRAY),
    Event('Comida/Descanso/Familia', day='2025-02-19', 
          start='14:00', end='17:00', style=EventStyles.GRAY),
    Event('Comida/Descanso/Familia', day='2025-02-20', 
          start='14:00', end='17:00', style=EventStyles.GRAY),
    Event('Comida/Descanso/Familia', day='2025-02-21', 
          start='14:00', end='17:00', style=EventStyles.GRAY),
    Event('Descanso/Familia', day='2025-02-17', 
          start='21:00', end='22:00', style=EventStyles.GRAY),
    Event('Descanso/Familia', day='2025-02-18', 
          start='21:00', end='22:00', style=EventStyles.GRAY),
    Event('Descanso/Familia', day='2025-02-19', 
          start='21:00', end='22:00', style=EventStyles.GRAY),
    Event('Descanso/Familia', day='2025-02-20', 
          start='21:00', end='22:00', style=EventStyles.GRAY),
    Event('Descanso/Familia', day='2025-02-21', 
          start='19:00', end='22:00', style=EventStyles.GRAY),
    Event('Juntas, Correos y Redes Sociales', day='2025-02-17', 
          start='17:00', end='19:00', style=EventStyles.RED),
    Event('Juntas, Correos y Redes Sociales', day='2025-02-18', 
          start='17:00', end='19:00', style=EventStyles.RED),
    Event('Juntas, Correos y Redes Sociales', day='2025-02-19', 
          start='17:00', end='19:00', style=EventStyles.RED),
    Event('Juntas, Correos y Redes Sociales', day='2025-02-20', 
          start='17:00', end='19:00', style=EventStyles.RED),
    Event('Juntas, Correos y Redes Sociales', day='2025-02-21', 
          start='17:00', end='19:00', style=EventStyles.RED),
    Event('Curso SQL desde Cero y más...', day='2025-02-22', 
          start='10:00', end='14:00', style=EventStyles.BLUE, 
          notes='Primera Clase del Curso'),
    Event('Comida/Descanso/Familia', day='2025-02-22', 
          start='14:00', end='22:00', style=EventStyles.GRAY),
    Event('Reposar la carnes como indica el Señor / Familia', day='2025-02-23', 
          start='8:00', end='22:00', style=EventStyles.GRAY),
]

# Validamos la configuración de nuestro calendario así como los eventos
data.validate_config(config)
data.validate_events(events, config)

# Construimos el calendario
calendar = Calendar.build(config)

# Agregamos los eventos al calendario
calendar.add_events(events)

# Guardamos la imagen de nuestro calendario
calendar.save("calendario_code_with_goz.png")

Observen que la parte más extensa del código corresponde a los eventos, pero éstos podríamos traerlos de una base de datos o crear unos iteradores para las fechas que necesitamos. No es una solución que sirva para todo pero sin duda puede ser interesante para varios casos por ejemplo cuando se tengan calendarios en los que pase un periodo de tiempo considerable en ser modificados (meses o más). Ya sea que se presente la imágen desde web o algo más cotidiano como ver el calendario impreso en alguna puerta. Algunos ejemplos que se me ocurren son:
1. Horarios para estudiantes, que la escuela genere esto de manera automática y los entregue a los padres de familia.
2. Horarios de salas/salones, esas clásicas hojas que pegan afuera de cada salón cada semestre.
3. Horarios de atención (consultorios médicos, veterinarias, etc...)
Por mencionar algunos
Ojalá a alguien le sirva y como siempre... si usted llegó hasta aca y no entendió nada jajaja por aca le dejo mis cursos da click aquí
Un abrazo
Goz