Prueba pico y placa bogota

BOGOTA PICO Y PLACA

`; } }); const pad2 = (n) => String(n).padStart(2,'0'); function getTZ(root){ return (root.getAttribute('data-tz') || 'America/Bogota').trim() || 'America/Bogota'; } function nowPartsInTZ(tz){ const dtf = new Intl.DateTimeFormat('en-CA', { timeZone: tz, year:'numeric', month:'2-digit', day:'2-digit', hour:'2-digit', minute:'2-digit', second:'2-digit', hour12:false }); const parts = dtf.formatToParts(new Date()); const m = {}; for (const p of parts) if (p.type !== 'literal') m[p.type] = p.value; return { year:+m.year, month:+m.month, day:+m.day, hour:+m.hour, minute:+m.minute, second:+m.second }; } function ymdFromParts(p){ return `${p.year}-${pad2(p.month)}-${pad2(p.day)}`; } function minutesOfDayFromParts(p){ return p.hour*60 + p.minute; } function dateUTCNoonFromYMD(ymd){ const [y,m,d] = ymd.split('-').map(Number); return new Date(Date.UTC(y, m-1, d, 12, 0, 0)); } function addDaysYMD(ymd, delta){ const dt = dateUTCNoonFromYMD(ymd); dt.setUTCDate(dt.getUTCDate() + delta); return `${dt.getUTCFullYear()}-${pad2(dt.getUTCMonth()+1)}-${pad2(dt.getUTCDate())}`; } function fmtTimeNoSeconds(tz){ return new Intl.DateTimeFormat('es-CO', { timeZone: tz, hour:'numeric', minute:'2-digit', hour12:true }).format(new Date()); } function weekdayUpperES(tz, ymd){ const dt = dateUTCNoonFromYMD(ymd); const w = new Intl.DateTimeFormat('es-CO', { timeZone: tz, weekday:'long' }).format(dt); return String(w).toUpperCase(); } function prettyDateES(ymd){ const [y,m,d] = ymd.split('-').map(Number); const meses = ['Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic']; return `${d} de ${meses[m-1]} ${y}`; } function isHHMM(s){ return /^([01]\d|2[0-3]):([0-5]\d)$/.test(String(s||'').trim()); } function toMinutes(hhmm){ if (!isHHMM(hhmm)) return null; const [h,m] = hhmm.split(':').map(Number); return h*60 + m; } function time24to12ES(hhmm){ if (!isHHMM(hhmm)) return String(hhmm||''); const [h,m] = hhmm.split(':').map(Number); const h12 = ((h + 11) % 12) + 1; const suf = h >= 12 ? 'p. m.' : 'a. m.'; return `${h12}:${pad2(m)} ${suf}`; } function scheduleLabel(schedule){ const slots = Array.isArray(schedule) ? schedule : []; const parts = slots .filter(s => s && s.start && s.end) .map(s => `${time24to12ES(String(s.start))} a ${time24to12ES(String(s.end))}`); return parts.length ? parts.join(' · ') : 'Sin restricción'; } function getHorarioEstado(schedule, nowMin){ const slots = (Array.isArray(schedule) ? schedule : []) .map(s => ({ s: toMinutes(String(s.start||'')), e: toMinutes(String(s.end||'')) })) .filter(x => x.s !== null && x.e !== null) .sort((a,b) => a.s - b.s); if (!slots.length) return { kind:'none', endMin:null }; for (const slot of slots){ if (nowMin >= slot.s && nowMin < slot.e) return { kind:'active', endMin: slot.e }; } return { kind:'inactive', endMin:null }; } function countdownHM(endMin, nowMin){ if (endMin === null) return null; const rem = Math.max(0, endMin - nowMin); return { h: Math.floor(rem/60), m: rem % 60 }; } function safeUrl(u){ const s = String(u ?? '').trim(); return /^https?:\/\//i.test(s) ? s : ''; } function dayKeyFromYMD(ymd){ const dt = dateUTCNoonFromYMD(ymd); return ['sun','mon','tue','wed','thu','fri','sat'][dt.getUTCDay()]; } function iconSvg(key){ const common = `width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true"`; const car = ``; const taxi = ``; const shield = ``; const truck = ``; const k = String(key||'').toLowerCase(); if (k.includes('taxi')) return taxi; if (k.includes('especial')) return shield; if (k.includes('carga')) return truck; return car; } function resolveRestriction(city, cat, ymd){ const rule = cat.rule || {}; const dk = dayKeyFromYMD(ymd); if (rule.type === "bogota_particulares_odd_even"){ const ex = rule.exceptions && rule.exceptions[ymd] ? rule.exceptions[ymd] : null; if (ex && ex.kind === "no_aplica") return { value:"NO APLICA", kind:"na", note: ex.note || "", schedule: [] }; if (ex && ex.kind === "regional") return { value: ex.label || "REGIONAL", kind:"info", note: ex.note || "", schedule: ex.schedule || [] }; if (dk === "sat" || dk === "sun") return { value:"NO APLICA", kind:"na", note:"Sin restricción.", schedule: [] }; const day = Number(ymd.slice(-2)); const restricted = (day % 2 === 1) ? "6-7-8-9-0" : "1-2-3-4-5"; return { value: restricted, kind:"digits", note:"", schedule: cat.schedule || [] }; } if (rule.type === "month_map"){ const ym = ymd.slice(0,7); const bucket = rule.months && rule.months[ym] ? rule.months[ym] : null; if (!bucket) return { value:"SIN INFORMACIÓN", kind:"unknown", note:"No hay calendario cargado para esta fecha.", schedule: [] }; const noA = Array.isArray(bucket.no_aplica) ? bucket.no_aplica : []; if (noA.includes(ymd)) return { value:"NO APLICA", kind:"na", note:"No aplica (domingo o festivo).", schedule: [] }; const v = bucket.restricted && bucket.restricted[ymd] ? String(bucket.restricted[ymd]) : ""; if (!v) return { value:"SIN INFORMACIÓN", kind:"unknown", note:"No hay dato cargado para esta fecha.", schedule: [] }; return { value: v, kind:"digits", note:"", schedule: cat.schedule || [] }; } if (rule.type === "bogota_carga_20"){ const noA = Array.isArray(rule.no_aplica) ? rule.no_aplica : []; if (noA.includes(ymd)) return { value:"NO APLICA", kind:"na", note:"Festivo: no aplica.", schedule: [] }; if (dk === "sun") return { value:"NO APLICA", kind:"na", note:"Domingo: no aplica.", schedule: [] }; if (dk === "sat"){ const allowed = rule.saturday_allowed && rule.saturday_allowed[ymd] ? String(rule.saturday_allowed[ymd]) : ""; if (!allowed) return { value:"SIN INFORMACIÓN", kind:"unknown", note:"No hay dato cargado para este sábado.", schedule: [] }; const restricted = (allowed === "1-3-5-7-9") ? "0-2-4-6-8" : "1-3-5-7-9"; return { value: restricted, kind:"digits", note:"Sábado (5:00 a. m. a 9:00 p. m.).", schedule: rule.saturday_schedule || [] }; } if (dk === "mon" || dk === "tue" || dk === "wed" || dk === "thu" || dk === "fri"){ return { value:"TODOS", kind:"all", note:"Entre semana aplica sin importar el dígito.", schedule: cat.schedule || [] }; } return { value:"SIN INFORMACIÓN", kind:"unknown", note:"", schedule: [] }; } return { value:"SIN INFORMACIÓN", kind:"unknown", note:"", schedule: [] }; } function mount(root){ const tz = getTZ(root); const key = String(root.getAttribute("data-key") || "").trim(); const cfg = window.PZ_PYP_DATA && window.PZ_PYP_DATA[key] ? window.PZ_PYP_DATA[key] : null; if (!cfg) throw new Error(`No existe window.PZ_PYP_DATA["${key}"]. Revisa data-key.`); const city = cfg.city; const options = (city.switch && Array.isArray(city.switch.options)) ? city.switch.options : []; root.innerHTML = `
PICO Y PLACA
Hora: --:--
--
--
Si vas a viajar, revisa el pico y placa para la fecha de tu viaje.
`; const $ = (sel) => root.querySelector(sel); const elTitle = $('.pz-title'); const elTime = $('.pz-time'); const elCity = $('.pz-cityselect'); const elWeek = $('.pz-weekday'); const elDate = $('.pz-date'); const elDateInput = $('.pz-dateinput'); const elDateCenter = $('.pz-datecenter'); const elPrevDay = $('.pz-daybtn--left'); const elNextDay = $('.pz-daybtn--right'); const elGrid = $('.pz-grid'); const elFoot = $('.pz-foot'); const elPrevPage = $('.pz-page--prev'); const elNextPage = $('.pz-page--next'); elCity.innerHTML = options .slice() .sort((a,b) => String(a.name||'').localeCompare(String(b.name||''), 'es')) .map(o => ``) .join(''); elCity.value = city.id; let todayTZ = ymdFromParts(nowPartsInTZ(tz)); let selectedYMD = todayTZ; let pageIndex = 0; let pageSize = window.matchMedia('(min-width: 820px)').matches ? 4 : 2; let visibleNodes = new Map(); function getSortedCats(){ return (Array.isArray(city.categories) ? city.categories : []) .slice() .sort((a,b) => (Number(a.priority||99) - Number(b.priority||99)) || String(a.name||'').localeCompare(String(b.name||''), 'es')); } function updateHeader(){ elTitle.textContent = `PICO Y PLACA ${String(city.name || city.id).toUpperCase()}`.trim(); elTime.textContent = `Hora: ${fmtTimeNoSeconds(tz)}`; elWeek.textContent = weekdayUpperES(tz, selectedYMD); elDate.textContent = prettyDateES(selectedYMD); elDateInput.value = selectedYMD; } function updateFooter(){ const srcName = String(city.source && city.source.name ? city.source.name : '').trim(); const srcUrl = safeUrl(city.source && city.source.url ? city.source.url : ''); const verified = String(city.last_verified || '').trim(); const parts = []; if (srcUrl) parts.push(`Fuente: ${srcName || 'Fuente oficial'}`); else if (srcName) parts.push(`Fuente: ${srcName}`); if (verified) parts.push(`Verificado: ${verified}`); elFoot.innerHTML = parts.join(' · '); } function calcPageSize(){ return window.matchMedia('(min-width: 820px)').matches ? 4 : 2; } function renderPage(){ const cats = getSortedCats(); const newSize = calcPageSize(); if (newSize !== pageSize) { pageSize = newSize; pageIndex = 0; } const totalPages = Math.max(1, Math.ceil(cats.length / pageSize)); pageIndex = Math.min(pageIndex, totalPages - 1); const start = pageIndex * pageSize; const pageCats = cats.slice(start, start + pageSize); const showPager = cats.length > pageSize; elPrevPage.style.display = showPager ? 'flex' : 'none'; elNextPage.style.display = showPager ? 'flex' : 'none'; elGrid.innerHTML = pageCats.map(cat => `
${iconSvg(cat.icon || cat.id)}
${String(cat.name || cat.id).toUpperCase()}
Placas terminadas en:
--
Termina en: --
Horario: --
`).join(''); visibleNodes = new Map(); elGrid.querySelectorAll('.pz-card').forEach(card => { const catId = card.getAttribute('data-cat'); visibleNodes.set(catId, { label: card.querySelector('.pz-label'), value: card.querySelector('.pz-value'), cd: card.querySelector('.pz-countdown'), cdText: card.querySelector('.pz-counttext'), band: card.querySelector('.pz-band'), bandText: card.querySelector('.pz-bandtext'), note: card.querySelector('.pz-note') }); }); updateCardsDynamic(); } function updateCardsDynamic(){ const nowP = nowPartsInTZ(tz); todayTZ = ymdFromParts(nowP); const nowMin = minutesOfDayFromParts(nowP); const isTodaySelected = (selectedYMD === todayTZ); const cats = getSortedCats(); for (const cat of cats){ const refs = visibleNodes.get(String(cat.id)); if (!refs) continue; const r = resolveRestriction(city, cat, selectedYMD); const sched = Array.isArray(r.schedule) && r.schedule.length ? r.schedule : (Array.isArray(cat.schedule) ? cat.schedule : []); const schedLabel = scheduleLabel(sched); refs.value.classList.remove('pz-value--na'); if (r.kind === 'na'){ refs.label.textContent = 'Estado hoy:'; refs.value.textContent = 'NO APLICA'; refs.value.classList.add('pz-value--na'); } else if (r.kind === 'all'){ refs.label.textContent = 'Aplica a:'; refs.value.textContent = 'TODOS'; } else if (r.kind === 'unknown'){ refs.label.textContent = 'Estado hoy:'; refs.value.textContent = 'SIN INFORMACIÓN'; } else { refs.label.textContent = 'Placas terminadas en:'; refs.value.textContent = String(r.value); } if (r.kind === 'na' || r.kind === 'unknown'){ refs.band.classList.remove('pz-band--yellow'); refs.band.classList.add('pz-band--gray'); refs.bandText.textContent = 'Sin restricción'; } else { refs.band.classList.remove('pz-band--gray'); refs.band.classList.add('pz-band--yellow'); refs.bandText.textContent = schedLabel; } const note = String(r.note || '').trim(); if (note){ refs.note.style.display = 'block'; refs.note.textContent = note; } else { refs.note.style.display = 'none'; refs.note.textContent = ''; } const canCount = isTodaySelected && r.kind !== 'na' && r.kind !== 'unknown' && r.kind !== 'info' && Array.isArray(sched) && sched.length > 0; if (!canCount){ refs.cd.style.display = 'none'; refs.cdText.textContent = ''; continue; } const st = getHorarioEstado(sched, nowMin); if (st.kind !== 'active'){ refs.cd.style.display = 'none'; refs.cdText.textContent = ''; continue; } const hm = countdownHM(st.endMin, nowMin); refs.cd.style.display = 'flex'; refs.cdText.textContent = `Termina en: ${hm.h}h ${pad2(hm.m)}m`; } elTime.textContent = `Hora: ${fmtTimeNoSeconds(tz)}`; } // Redirección por ciudad elCity.addEventListener('change', () => { const nextId = elCity.value; const target = options.find(o => String(o.id) === String(nextId)); const url = target && target.url ? String(target.url).trim() : ''; if (safeUrl(url)) window.location.href = url; }); elPrevDay.addEventListener('click', () => { selectedYMD = addDaysYMD(selectedYMD, -1); pageIndex = 0; updateHeader(); renderPage(); }); elNextDay.addEventListener('click', () => { selectedYMD = addDaysYMD(selectedYMD, +1); pageIndex = 0; updateHeader(); renderPage(); }); function openPicker(){ if (typeof elDateInput.showPicker === 'function') elDateInput.showPicker(); else elDateInput.focus(); } elDateCenter.addEventListener('click', openPicker); elDateCenter.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' '){ e.preventDefault(); openPicker(); } }); elDateInput.addEventListener('change', () => { if (elDateInput.value){ selectedYMD = elDateInput.value; pageIndex = 0; updateHeader(); renderPage(); } }); elPrevPage.addEventListener('click', () => { const cats = getSortedCats(); const totalPages = Math.max(1, Math.ceil(cats.length / pageSize)); pageIndex = (pageIndex - 1 + totalPages) % totalPages; renderPage(); }); elNextPage.addEventListener('click', () => { const cats = getSortedCats(); const totalPages = Math.max(1, Math.ceil(cats.length / pageSize)); pageIndex = (pageIndex + 1) % totalPages; renderPage(); }); window.addEventListener('resize', renderPage); updateHeader(); updateFooter(); renderPage(); root._pzTimer && clearInterval(root._pzTimer); root._pzTimer = setInterval(() => { updateHeader(); updateCardsDynamic(); }, 30 * 1000); } })();
miguel

Recent Posts

Evite el sedentarismo en vacaciones y priorice su salud

Consejos prácticos para evitar el sedentarismo y cuidar su bienestar físico y mental durante las vacaciones.

6 enero, 2026

Evite el sedentarismo en vacaciones con estos ejercicios

¡Comience el año cuidando su salud! Estos son algunos exámenes de rigor que se debe realizar. ¡Tome lápiz y papel!

6 enero, 2026

¿Cómo saber si tengo multas de tránsito? Le explicamos cómo consultarlas

Le contamos cómo verificar si tiene una multa, comparendo o infracción de tránsito. ¡No deje que estas sorpresas lo tomen…

5 enero, 2026

Pico y placa para en Bogotá y otras ciudades de Colombia

El Pico y Placa busca mejorar el tráfico y la movilidad en las ciudades. Conozca aquí los cambios de esta…

2 enero, 2026

¿Qué es un certificado financiero? Definición y ventajas clave

Descubra qué es un certificado financiero, cómo funciona y por qué es una opción segura para hacer crecer su dinero…

31 diciembre, 2025

Guía para elegir los seguros ideales en 2026

¡Asegure su tranquilidad! Encuentre el seguro ideal para sus planes y disfrute sin preocupaciones con Seguros Bolívar.

29 diciembre, 2025