calendary-co 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alejandro Galicia
4
+
5
+ Se reservan los derechos de autor del titular. En virtud de esta licencia MIT,
6
+ cualquier persona puede usar, copiar, modificar, fusionar, publicar, distribuir,
7
+ sublicenciar y/o vender copias del software, sujeto a las condiciones siguientes.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ include calendary_co/data/*.json
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: calendary_co
3
+ Version: 0.1.0
4
+ Summary: Calendario de festivos oficiales y eventos culturales de Colombia (Ley Emiliani)
5
+ Author: Alejandro Galicia
6
+ Author-email: Alejandro Galicia <iglesiag1908@gmail.com>
7
+ License: MIT
8
+ Keywords: colombia,holidays,festivos,calendario,cultural-events
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: colombian-holidays>=1.0.0
22
+ Requires-Dist: python-dateutil>=2.8.2
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Dynamic: author
26
+ Dynamic: license-file
27
+ Dynamic: requires-python
28
+
29
+ # calendary_co
30
+
31
+ Calendario de festivos oficiales y eventos culturales de Colombia, con soporte para la **Ley Emiliani** (vía `colombian-holidays`) y ventana rodante de **3 años** (año actual + 2 siguientes).
32
+
33
+ ## Instalación
34
+
35
+ ```powershell
36
+ pip install calendary_co
37
+ ```
38
+
39
+ Desarrollo local:
40
+
41
+ ```powershell
42
+ pip install -e "ruta/a/LIBRERIAS py/calendary_co"
43
+ ```
44
+
45
+ Con dependencias de desarrollo (pytest):
46
+
47
+ ```powershell
48
+ pip install -e "ruta/a/LIBRERIAS py/calendary_co[dev]"
49
+ ```
50
+
51
+ ## Ventana rodante de años
52
+
53
+ El paquete precalienta automáticamente el año en curso y los dos siguientes. No hace falta añadir años manualmente cada enero:
54
+
55
+ ```python
56
+ from datetime import date
57
+ from calendary_co import get_active_years, get_full_calendar
58
+
59
+ # Con fecha de referencia (útil en tests)
60
+ ref = date(2026, 7, 2)
61
+ print(list(get_active_years(ref))) # [2026, 2027, 2028]
62
+
63
+ calendario = get_full_calendar(ref) # {2026: [...], 2027: [...], 2028: [...]}
64
+ ```
65
+
66
+ Consultas fuera de la ventana activa siguen funcionando (cálculo bajo demanda).
67
+
68
+ ## Demo rápido
69
+
70
+ Script de prueba incluido en el repositorio:
71
+
72
+ ```powershell
73
+ cd "LIBRERIAS py/calendary_co"
74
+ pip install -e .
75
+ python demo_calendary.py
76
+ ```
77
+
78
+ Muestra festivos y eventos culturales entre dos fechas (edita `FECHA_INICIO` y `FECHA_FIN` en el archivo).
79
+
80
+ ## API principal
81
+
82
+ ### Festivos oficiales
83
+
84
+ ```python
85
+ from datetime import date
86
+ from calendary_co import is_holiday, get_holiday_name, get_holidays_for_year
87
+
88
+ d = date(2026, 7, 20)
89
+ is_holiday(d) # True (festivo o domingo)
90
+ get_holiday_name(d) # "Día de la Independencia (Independence Day)"
91
+ get_holidays_for_year(2026) # lista de (fecha, nombre), 18 festivos legales
92
+ ```
93
+
94
+ ### Consulta por rango (recomendado)
95
+
96
+ Solo festivos nombrados y eventos culturales entre dos fechas, con día de la semana en español:
97
+
98
+ ```python
99
+ from datetime import date
100
+ from calendary_co import consultar_festividades, format_consulta_festividades
101
+
102
+ inicio = date(2026, 6, 1)
103
+ fin = date(2026, 6, 30)
104
+
105
+ resultados = consultar_festividades(inicio, fin)
106
+
107
+ # Filtrar por nivel (opcional):
108
+ # consultar_festividades(inicio, fin, niveles=["nacional"])
109
+ # consultar_festividades(inicio, fin, niveles=["municipal", "regional"])
110
+ # consultar_festividades(inicio, fin, niveles=["municipal"])
111
+
112
+ # resultados["festivos_oficiales"] -> festivos legales (siempre, independiente del filtro niveles)
113
+ # resultados["eventos_culturales_rangos"] -> culturales agrupados por fechas
114
+ # resultados["niveles_aplicados"] -> niveles usados en la consulta
115
+ # resultados["dias"] -> detalle por dia (uso avanzado)
116
+
117
+ print(format_consulta_festividades(resultados, inicio, fin))
118
+ ```
119
+
120
+ No incluye días vacíos (sin festivo nombrado ni evento cultural). Los domingos sin actividad cultural no aparecen.
121
+
122
+ ### Contexto detallado para un día o rango
123
+
124
+ ```python
125
+ from datetime import date
126
+ from calendary_co import get_calendar_context, get_calendar_contexts, format_context_for_prompt
127
+
128
+ ctx = get_calendar_context(date(2026, 12, 27), segment_id="21701_CALI_SEGMENTO")
129
+ # ctx.is_holiday_or_sunday, ctx.holiday_name, ctx.cultural_events, ctx.season
130
+
131
+ contextos = get_calendar_contexts(date(2026, 7, 14), date(2026, 7, 20), segment_id="21701_CALI_SEGMENTO")
132
+ texto_xml = format_context_for_prompt(contextos)
133
+ ```
134
+
135
+ ### Validación de temporalidad
136
+
137
+ Evita mensajes incoherentes (por ejemplo, “Feliz Navidad” en julio):
138
+
139
+ ```python
140
+ from datetime import date
141
+ from calendary_co import validar_temporalidad_mensaje
142
+
143
+ validar_temporalidad_mensaje("Feliz Navidad", date(2026, 7, 20)) # False
144
+ validar_temporalidad_mensaje("Recuerda tu pago", date(2026, 7, 20)) # True
145
+ ```
146
+
147
+ ## Eventos incluidos
148
+
149
+ **Festivos oficiales:** 18 festivos legales + domingos (Ley Emiliani, Pascua, traslados).
150
+
151
+ **Culturales nacionales:** Velitas, Novena de Aguinaldos, Amor y Amistad, Día de la Madre/Padre, Halloween, Semana Santa, etc.
152
+
153
+ **Municipales:** ferias y fiestas patronales por municipio (referencia MINCIT), incluyendo **San Juan** (24 de junio) y **Fiestas de San Juan y San Pedro** en Tolima y Huila. **San Pedro y San Pablo** es festivo oficial (Ley Emiliani).
154
+
155
+ **Ferias regionales:** Carnaval de Barranquilla, Feria de Cali, Feria de las Flores, Leyenda Vallenata, Carnaval de Negros y Blancos, Feria de Manizales, y más en `municipal_events.py`.
156
+
157
+ **colombia.co:** eventos adicionales desde [colombia.co/eventos](https://colombia.co/eventos) (API `/mark-events/events/{año}/{mes}/es`), empaquetados en `calendary_co/data/colombia_co_events.json`. Actualizar con `python scripts/sync_colombia_co_events.py`.
158
+
159
+ Los eventos municipales y regionales se filtran por `segment_id` con tokens como `_CALI_`, `_IBAGUÉ_`, `_NEIVA_`, `_EL_ESPINAL_`, etc.
160
+
161
+ ## Integración (agente 4)
162
+
163
+ Instalar `calendary_co` como dependencia del proyecto agente. En el prompt dinámico:
164
+
165
+ ```python
166
+ from datetime import date
167
+ from calendary_co import get_calendar_contexts, format_context_for_prompt
168
+
169
+ fechas = [date.fromisoformat(d) for d in dias_bloque]
170
+ contexto_text = format_context_for_prompt(
171
+ get_calendar_contexts(fechas[0], fechas[-1], segmento_id)
172
+ )
173
+ # Inyectar en <contexto_temporal>{contexto_text}</contexto_temporal>
174
+ ```
175
+
176
+ En validación post-LLM:
177
+
178
+ ```python
179
+ from datetime import date
180
+ from calendary_co import validar_temporalidad_mensaje
181
+
182
+ for item in plan:
183
+ fecha = date.fromisoformat(item["fecha"])
184
+ if not validar_temporalidad_mensaje(item["mensaje"], fecha, segmento_id):
185
+ raise ValueError("Mensaje temporalmente incoherente")
186
+ ```
187
+
188
+ ## Tests
189
+
190
+ ```powershell
191
+ cd "LIBRERIAS py/calendary_co"
192
+ python -m pytest tests/ -v
193
+ ```
194
+
195
+ ## Publicación en PyPI
196
+
197
+ ```powershell
198
+ pip install --upgrade build twine
199
+ python -m build
200
+ python -m twine upload dist/*
201
+ ```
202
+
203
+ Paquete: `pip install calendary_co`
204
+
205
+ ## Licencia
206
+
207
+ **MIT** — Copyright (c) 2026 Alejandro Galicia. Derechos de autor reservados al titular; la licencia permite uso, modificación y distribución libre en proyectos personales, comerciales y de código abierto, con inclusión del aviso de copyright. Ver [LICENSE](LICENSE).
208
+
209
+ ## Dependencias
210
+
211
+ - `colombian-holidays>=1.0.0` — festivos oficiales Colombia (Ley Emiliani)
212
+ - `python-dateutil>=2.8.2` — cálculo de Pascua y eventos móviles
213
+
214
+ ## Relación con `contact_co`
215
+
216
+ `contact_co` usa `holidays.Colombia()` para validación legal de contacto. `calendary_co` es independiente y está orientado al contexto temporal de mensajes (prompts y validación). Una migración futura de `contact_co` a `calendary_co` es opcional.
@@ -0,0 +1,188 @@
1
+ # calendary_co
2
+
3
+ Calendario de festivos oficiales y eventos culturales de Colombia, con soporte para la **Ley Emiliani** (vía `colombian-holidays`) y ventana rodante de **3 años** (año actual + 2 siguientes).
4
+
5
+ ## Instalación
6
+
7
+ ```powershell
8
+ pip install calendary_co
9
+ ```
10
+
11
+ Desarrollo local:
12
+
13
+ ```powershell
14
+ pip install -e "ruta/a/LIBRERIAS py/calendary_co"
15
+ ```
16
+
17
+ Con dependencias de desarrollo (pytest):
18
+
19
+ ```powershell
20
+ pip install -e "ruta/a/LIBRERIAS py/calendary_co[dev]"
21
+ ```
22
+
23
+ ## Ventana rodante de años
24
+
25
+ El paquete precalienta automáticamente el año en curso y los dos siguientes. No hace falta añadir años manualmente cada enero:
26
+
27
+ ```python
28
+ from datetime import date
29
+ from calendary_co import get_active_years, get_full_calendar
30
+
31
+ # Con fecha de referencia (útil en tests)
32
+ ref = date(2026, 7, 2)
33
+ print(list(get_active_years(ref))) # [2026, 2027, 2028]
34
+
35
+ calendario = get_full_calendar(ref) # {2026: [...], 2027: [...], 2028: [...]}
36
+ ```
37
+
38
+ Consultas fuera de la ventana activa siguen funcionando (cálculo bajo demanda).
39
+
40
+ ## Demo rápido
41
+
42
+ Script de prueba incluido en el repositorio:
43
+
44
+ ```powershell
45
+ cd "LIBRERIAS py/calendary_co"
46
+ pip install -e .
47
+ python demo_calendary.py
48
+ ```
49
+
50
+ Muestra festivos y eventos culturales entre dos fechas (edita `FECHA_INICIO` y `FECHA_FIN` en el archivo).
51
+
52
+ ## API principal
53
+
54
+ ### Festivos oficiales
55
+
56
+ ```python
57
+ from datetime import date
58
+ from calendary_co import is_holiday, get_holiday_name, get_holidays_for_year
59
+
60
+ d = date(2026, 7, 20)
61
+ is_holiday(d) # True (festivo o domingo)
62
+ get_holiday_name(d) # "Día de la Independencia (Independence Day)"
63
+ get_holidays_for_year(2026) # lista de (fecha, nombre), 18 festivos legales
64
+ ```
65
+
66
+ ### Consulta por rango (recomendado)
67
+
68
+ Solo festivos nombrados y eventos culturales entre dos fechas, con día de la semana en español:
69
+
70
+ ```python
71
+ from datetime import date
72
+ from calendary_co import consultar_festividades, format_consulta_festividades
73
+
74
+ inicio = date(2026, 6, 1)
75
+ fin = date(2026, 6, 30)
76
+
77
+ resultados = consultar_festividades(inicio, fin)
78
+
79
+ # Filtrar por nivel (opcional):
80
+ # consultar_festividades(inicio, fin, niveles=["nacional"])
81
+ # consultar_festividades(inicio, fin, niveles=["municipal", "regional"])
82
+ # consultar_festividades(inicio, fin, niveles=["municipal"])
83
+
84
+ # resultados["festivos_oficiales"] -> festivos legales (siempre, independiente del filtro niveles)
85
+ # resultados["eventos_culturales_rangos"] -> culturales agrupados por fechas
86
+ # resultados["niveles_aplicados"] -> niveles usados en la consulta
87
+ # resultados["dias"] -> detalle por dia (uso avanzado)
88
+
89
+ print(format_consulta_festividades(resultados, inicio, fin))
90
+ ```
91
+
92
+ No incluye días vacíos (sin festivo nombrado ni evento cultural). Los domingos sin actividad cultural no aparecen.
93
+
94
+ ### Contexto detallado para un día o rango
95
+
96
+ ```python
97
+ from datetime import date
98
+ from calendary_co import get_calendar_context, get_calendar_contexts, format_context_for_prompt
99
+
100
+ ctx = get_calendar_context(date(2026, 12, 27), segment_id="21701_CALI_SEGMENTO")
101
+ # ctx.is_holiday_or_sunday, ctx.holiday_name, ctx.cultural_events, ctx.season
102
+
103
+ contextos = get_calendar_contexts(date(2026, 7, 14), date(2026, 7, 20), segment_id="21701_CALI_SEGMENTO")
104
+ texto_xml = format_context_for_prompt(contextos)
105
+ ```
106
+
107
+ ### Validación de temporalidad
108
+
109
+ Evita mensajes incoherentes (por ejemplo, “Feliz Navidad” en julio):
110
+
111
+ ```python
112
+ from datetime import date
113
+ from calendary_co import validar_temporalidad_mensaje
114
+
115
+ validar_temporalidad_mensaje("Feliz Navidad", date(2026, 7, 20)) # False
116
+ validar_temporalidad_mensaje("Recuerda tu pago", date(2026, 7, 20)) # True
117
+ ```
118
+
119
+ ## Eventos incluidos
120
+
121
+ **Festivos oficiales:** 18 festivos legales + domingos (Ley Emiliani, Pascua, traslados).
122
+
123
+ **Culturales nacionales:** Velitas, Novena de Aguinaldos, Amor y Amistad, Día de la Madre/Padre, Halloween, Semana Santa, etc.
124
+
125
+ **Municipales:** ferias y fiestas patronales por municipio (referencia MINCIT), incluyendo **San Juan** (24 de junio) y **Fiestas de San Juan y San Pedro** en Tolima y Huila. **San Pedro y San Pablo** es festivo oficial (Ley Emiliani).
126
+
127
+ **Ferias regionales:** Carnaval de Barranquilla, Feria de Cali, Feria de las Flores, Leyenda Vallenata, Carnaval de Negros y Blancos, Feria de Manizales, y más en `municipal_events.py`.
128
+
129
+ **colombia.co:** eventos adicionales desde [colombia.co/eventos](https://colombia.co/eventos) (API `/mark-events/events/{año}/{mes}/es`), empaquetados en `calendary_co/data/colombia_co_events.json`. Actualizar con `python scripts/sync_colombia_co_events.py`.
130
+
131
+ Los eventos municipales y regionales se filtran por `segment_id` con tokens como `_CALI_`, `_IBAGUÉ_`, `_NEIVA_`, `_EL_ESPINAL_`, etc.
132
+
133
+ ## Integración (agente 4)
134
+
135
+ Instalar `calendary_co` como dependencia del proyecto agente. En el prompt dinámico:
136
+
137
+ ```python
138
+ from datetime import date
139
+ from calendary_co import get_calendar_contexts, format_context_for_prompt
140
+
141
+ fechas = [date.fromisoformat(d) for d in dias_bloque]
142
+ contexto_text = format_context_for_prompt(
143
+ get_calendar_contexts(fechas[0], fechas[-1], segmento_id)
144
+ )
145
+ # Inyectar en <contexto_temporal>{contexto_text}</contexto_temporal>
146
+ ```
147
+
148
+ En validación post-LLM:
149
+
150
+ ```python
151
+ from datetime import date
152
+ from calendary_co import validar_temporalidad_mensaje
153
+
154
+ for item in plan:
155
+ fecha = date.fromisoformat(item["fecha"])
156
+ if not validar_temporalidad_mensaje(item["mensaje"], fecha, segmento_id):
157
+ raise ValueError("Mensaje temporalmente incoherente")
158
+ ```
159
+
160
+ ## Tests
161
+
162
+ ```powershell
163
+ cd "LIBRERIAS py/calendary_co"
164
+ python -m pytest tests/ -v
165
+ ```
166
+
167
+ ## Publicación en PyPI
168
+
169
+ ```powershell
170
+ pip install --upgrade build twine
171
+ python -m build
172
+ python -m twine upload dist/*
173
+ ```
174
+
175
+ Paquete: `pip install calendary_co`
176
+
177
+ ## Licencia
178
+
179
+ **MIT** — Copyright (c) 2026 Alejandro Galicia. Derechos de autor reservados al titular; la licencia permite uso, modificación y distribución libre en proyectos personales, comerciales y de código abierto, con inclusión del aviso de copyright. Ver [LICENSE](LICENSE).
180
+
181
+ ## Dependencias
182
+
183
+ - `colombian-holidays>=1.0.0` — festivos oficiales Colombia (Ley Emiliani)
184
+ - `python-dateutil>=2.8.2` — cálculo de Pascua y eventos móviles
185
+
186
+ ## Relación con `contact_co`
187
+
188
+ `contact_co` usa `holidays.Colombia()` para validación legal de contacto. `calendary_co` es independiente y está orientado al contexto temporal de mensajes (prompts y validación). Una migración futura de `contact_co` a `calendary_co` es opcional.
@@ -0,0 +1,40 @@
1
+ from .calendar_service import (
2
+ NIVELES_EVENTO,
3
+ agrupar_eventos_culturales,
4
+ consultar_festividades,
5
+ format_consulta_festividades,
6
+ format_context_for_prompt,
7
+ get_active_years,
8
+ get_calendar_context,
9
+ get_calendar_contexts,
10
+ get_calendar_for_year,
11
+ get_full_calendar,
12
+ is_in_active_window,
13
+ nombre_dia_semana,
14
+ validar_temporalidad_mensaje,
15
+ )
16
+ from .colombia_holidays import get_holiday_name, get_holidays_for_year, is_holiday
17
+ from .municipal_events import get_municipal_events_for_year
18
+ from .types import CalendarContext, CalendarEvent
19
+
20
+ __all__ = [
21
+ "CalendarContext",
22
+ "CalendarEvent",
23
+ "NIVELES_EVENTO",
24
+ "agrupar_eventos_culturales",
25
+ "consultar_festividades",
26
+ "format_consulta_festividades",
27
+ "format_context_for_prompt",
28
+ "get_active_years",
29
+ "get_calendar_context",
30
+ "get_calendar_contexts",
31
+ "get_calendar_for_year",
32
+ "get_full_calendar",
33
+ "get_holiday_name",
34
+ "get_holidays_for_year",
35
+ "get_municipal_events_for_year",
36
+ "is_holiday",
37
+ "is_in_active_window",
38
+ "nombre_dia_semana",
39
+ "validar_temporalidad_mensaje",
40
+ ]