Existen distintas maneras para generar calendarios, generalmente aprovechamos
alguna API como la de Google Calendar o alguna biblioteca JS pero...
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.
###################################################################
# 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...)