^
Update this timeline entry
Time calculator
Source: Amy and ChatGPT #1356
Project ID
Chapter
No chapter
Timeline title
Start date
End date
Filename received
Filename assigned
Content
Enable editor
Use plain text
Code entry
Skip to content Chat history You said: write a script for a time calculator that allows me to enter a start and stop time and yield hours and minutes as well as decimal quantity. I will put it on my wordpress blog ChatGPT said: Thought Got it. Here are two drop-in options. Pick one: Option A — paste in a Gutenberg “Custom HTML” block <div class="ppv-timecalc" data-widget="timecalc"> <form> <div style="display:grid;gap:.5rem;grid-template-columns:repeat(2,minmax(0,1fr));max-width:560px"> <label>Start <input type="time" id="ppv-start" required step="60"> </label> <label>Stop <input type="time" id="ppv-stop" required step="60"> </label> <label>Break (minutes) <input type="number" id="ppv-break" min="0" step="1" value="0" inputmode="numeric"> </label> <label>Rounding <select id="ppv-round"> <option value="none">None</option> <option value="0.25">Quarter hours (0.25)</option> <option value="0.1">Tenths (0.1)</option> <option value="0.01">Hundredths (0.01)</option> <option value="1/6">6-min (0.1h=6m)</option> </select> </label> </div> <div style="margin:.75rem 0;display:flex;gap:.5rem;flex-wrap:wrap"> <button type="button" id="ppv-calc">Calculate</button> <button type="reset" id="ppv-reset">Reset</button> </div> <div id="ppv-output" aria-live="polite" style="border:1px solid #ddd;padding:1rem;border-radius:.5rem;max-width:560px"> <strong>Result:</strong> <div id="ppv-result-text">—</div> </div> <small style="display:block;margin-top:.5rem;max-width:560px;opacity:.8"> Notes: crosses midnight automatically (e.g., 22:30 → 02:15). Break is subtracted. “Rounding” applies to decimal hours only. </small> </form> </div> <script> (function(){ const $ = sel => document.querySelector(sel); function parseTimeToMinutes(t){ if(!t) return NaN; const [h,m] = t.split(':').map(Number); return h*60 + (m||0); } function roundDecimalHours(h, mode){ if(mode === 'none') return h; if(mode === '1/6') { // 6-minute increments = 0.1h return Math.round(h/0.1)*0.1; } const step = Number(mode); return Math.round(h/step)*step; } function fmt(h, m){ const pad = n => String(n).padStart(2,'0'); return `${h}:${pad(m)}`; } function calc(){ const start = parseTimeToMinutes($('#ppv-start').value); const stop = parseTimeToMinutes($('#ppv-stop').value); const brk = Number($('#ppv-break').value||0); const mode = $('#ppv-round').value; if(Number.isNaN(start) || Number.isNaN(stop)){ $('#ppv-result-text').textContent = 'Enter start and stop times.'; return; } // handle overnight let minutes = stop - start; if(minutes < 0) minutes += 24*60; // subtract break minutes -= Math.max(0, brk); if(minutes < 0){ $('#ppv-result-text').textContent = 'Break exceeds worked time.'; return; } const hoursInt = Math.floor(minutes/60); const minsInt = minutes % 60; const decimal = minutes/60; const decimalRounded = roundDecimalHours(decimal, mode); const decimalRoundedStr = decimalRounded.toFixed( mode==='none' ? 3 : mode==='0.25' ? 2 : mode==='0.1' ? 1 : mode==='1/6' ? 1 : 2 ); $('#ppv-result-text').innerHTML = `<div><b>Hours:Minutes</b> = ${fmt(hoursInt, minsInt)}</div> <div><b>Decimal hours</b> = ${decimal.toFixed(3)} (rounded: ${decimalRoundedStr})</div> <div><b>Total minutes</b> = ${minutes}</div>`; } $('#ppv-calc').addEventListener('click', calc); // auto-calc on input ['#ppv-start','#ppv-stop','#ppv-break','#ppv-round'].forEach(sel=>{ $(sel).addEventListener('input', calc); }); $('#ppv-reset').addEventListener('click', ()=>{ setTimeout(()=>{$('#ppv-result-text').textContent='—';},0); }); })(); </script> <style> .ppv-timecalc label{display:flex;flex-direction:column;font-weight:600;font-size:.95rem} .ppv-timecalc input, .ppv-timecalc select, .ppv-timecalc button{ font:inherit; padding:.5rem .6rem; border:1px solid #ccc; border-radius:.5rem; } .ppv-timecalc button{cursor:pointer} .ppv-timecalc button:hover{filter:brightness(.98)} </style> Option B — WordPress shortcode (drop into your child theme’s functions.php) This gives you a [timecalc] shortcode you can place anywhere. // === Paperless Ponte Vedra: Time Calculator Shortcode === function ppv_timecalc_shortcode($atts){ ob_start(); ?> <div class="ppv-timecalc" data-widget="timecalc"> <form> <div style="display:grid;gap:.5rem;grid-template-columns:repeat(2,minmax(0,1fr));max-width:560px"> <label>Start <input type="time" id="ppv-start" required step="60"> </label> <label>Stop <input type="time" id="ppv-stop" required step="60"> </label> <label>Break (minutes) <input type="number" id="ppv-break" min="0" step="1" value="0" inputmode="numeric"> </label> <label>Rounding <select id="ppv-round"> <option value="none">None</option> <option value="0.25">Quarter hours (0.25)</option> <option value="0.1">Tenths (0.1)</option> <option value="0.01">Hundredths (0.01)</option> <option value="1/6">6-min (0.1h=6m)</option> </select> </label> </div> <div style="margin:.75rem 0;display:flex;gap:.5rem;flex-wrap:wrap"> <button type="button" id="ppv-calc">Calculate</button> <button type="reset" id="ppv-reset">Reset</button> </div> <div id="ppv-output" aria-live="polite" style="border:1px solid #ddd;padding:1rem;border-radius:.5rem;max-width:560px"> <strong>Result:</strong> <div id="ppv-result-text">—</div> </div> <small style="display:block;margin-top:.5rem;max-width:560px;opacity:.8"> Notes: crosses midnight automatically (e.g., 22:30 → 02:15). Break is subtracted. “Rounding” applies to decimal hours only. </small> </form> </div> <style> .ppv-timecalc label{display:flex;flex-direction:column;font-weight:600;font-size:.95rem} .ppv-timecalc input,.ppv-timecalc select,.ppv-timecalc button{font:inherit;padding:.5rem .6rem;border:1px solid #ccc;border-radius:.5rem} .ppv-timecalc button{cursor:pointer} .ppv-timecalc button:hover{filter:brightness(.98)} </style> <script> (function(){ const root = document.currentScript.closest('.ppv-timecalc'); const $ = sel => root.querySelector(sel); function parseTimeToMinutes(t){ if(!t) return NaN; const [h,m]=t.split(':').map(Number); return h*60+(m||0); } function roundDecimalHours(h, mode){ if(mode==='none') return h; if(mode==='1/6') return Math.round(h/0.1)*0.1; const step = Number(mode); return Math.round(h/step)*step; } function fmt(h,m){ const pad=n=>String(n).padStart(2,'0'); return h+':'+pad(m); } function calc(){ const start=parseTimeToMinutes($('#ppv-start').value); const stop=parseTimeToMinutes($('#ppv-stop').value); const brk=Number($('#ppv-break').value||0); const mode=$('#ppv-round').value; if(Number.isNaN(start)||Number.isNaN(stop)){ $('#ppv-result-text').textContent='Enter start and stop times.'; return; } let minutes=stop-start; if(minutes<0) minutes+=24*60; minutes-=Math.max(0,brk); if(minutes<0){ $('#ppv-result-text').textContent='Break exceeds worked time.'; return; } const hInt=Math.floor(minutes/60), mInt=minutes%60, dec=minutes/60; const decR=roundDecimalHours(dec, mode); const decRstr=decR.toFixed(mode==='none'?3:mode==='0.25'?2:mode==='0.1'||mode==='1/6'?1:2); $('#ppv-result-text').innerHTML = '<div><b>Hours:Minutes</b> = '+fmt(hInt,mInt)+'</div>'+ '<div><b>Decimal hours</b> = '+dec.toFixed(3)+' (rounded: '+decRstr+')</div>'+ '<div><b>Total minutes</b> = '+minutes+'</div>'; } root.querySelector('#ppv-calc').addEventListener('click', calc); ['#ppv-start','#ppv-stop','#ppv-break','#ppv-round'].forEach(sel=>$(sel).addEventListener('input', calc)); root.querySelector('#ppv-reset').addEventListener('click', ()=>{ setTimeout(()=>{ $('#ppv-result-text').textContent='—'; },0); }); })(); </script> <?php return ob_get_clean(); } add_shortcode('timecalc','ppv_timecalc_shortcode'); How to use Option A: paste the HTML block where you want the calculator. Option B: add the PHP to your child theme (or a small “Code Snippets” plugin), then put [timecalc] in any post/page. Behavior you get (no surprises) Accepts 24-hour or your browser’s AM/PM time picker. Handles overnight shifts cleanly (e.g., 22:30 → 02:15). Subtracts an optional break in minutes. Shows HH:MM, total minutes, raw decimal hours (3 d.p.), and a rounded decimal (tenths, quarters, hundredths, or 6-minute billing). Live updates as you type + a Calculate button for mouse first users. Accessible: labeled fields, results announced via aria-live. Want me to skin it to your site palette and Divi classes? Give me your hex codes and I’ll wire it up. You said: nothing happens when I click calculate ChatGPT said: Thought You’re hitting a JS-scope/ordering issue. Fix it by scoping the code to the widget container and waiting for DOM ready. Replace just your <script>…</script> with this version: <script> document.addEventListener('DOMContentLoaded', function(){ // Support multiple calculators on one page + avoid ID collisions document.querySelectorAll('.ppv-timecalc[data-widget="timecalc"]').forEach(function(root){ const $ = sel => root.querySelector(sel); function parseTimeToMinutes(t){ if(!t) return NaN; const [h,m] = t.split(':').map(Number); return h*60 + (m||0); } function roundDecimalHours(h, mode){ if(mode === 'none') return h; if(mode === '1/6') return Math.round(h/0.1)*0.1; // 6-min increments const step = Number(mode); return Math.round(h/step)*step; } function fmt(h, m){ const pad = n => String(n).padStart(2,'0'); return `${h}:${pad(m)}`; } function calc(){ const start = parseTimeToMinutes($('#ppv-start')?.value); const stop = parseTimeToMinutes($('#ppv-stop')?.value); const brk = Number($('#ppv-break')?.value || 0); const mode = $('#ppv-round')?.value || 'none'; if(Number.isNaN(start) || Number.isNaN(stop)){ $('#ppv-result-text').textContent = 'Enter start and stop times.'; return; } let minutes = stop - start; if(minutes < 0) minutes += 24*60; // overnight minutes -= Math.max(0, brk); // subtract break if(minutes < 0){ $('#ppv-result-text').textContent = 'Break exceeds worked time.'; return; } const hoursInt = Math.floor(minutes/60); const minsInt = minutes % 60; const decimal = minutes/60; const decimalRounded = roundDecimalHours(decimal, mode); const decimalRoundedStr = decimalRounded.toFixed( mode==='none' ? 3 : mode==='0.25' ? 2 : mode==='0.1' ? 1 : mode==='1/6' ? 1 : 2 ); $('#ppv-result-text').innerHTML = `<div><b>Hours:Minutes</b> = ${fmt(hoursInt, minsInt)}</div> <div><b>Decimal hours</b> = ${decimal.toFixed(3)} (rounded: ${decimalRoundedStr})</div> <div><b>Total minutes</b> = ${minutes}</div>`; } // Wire up events inside this widget only root.querySelector('#ppv-calc')?.addEventListener('click', calc); ['#ppv-start','#ppv-stop','#ppv-break','#ppv-round'].forEach(sel=>{ root.querySelector(sel)?.addEventListener('input', calc); }); root.querySelector('#ppv-reset')?.addEventListener('click', ()=>{ setTimeout(()=>{ root.querySelector('#ppv-result-text').textContent='—'; },0); }); }); }); </script> Why this works: Waits for DOMContentLoaded so the button exists before we attach listeners. Scopes all queries to the .ppv-timecalc container, so other IDs/plugins won’t collide. Safe-guards (?.) prevent a silent failure if a field is missing. If you’d rather not rely on inline scripts (some themes/plugins defer/strip them), use the shortcode version I gave earlier (Option B). It already scopes to the widget via document.currentScript.closest(...) and avoids the global-ID trap. You said: excellent. thank you ChatGPT said: You’re very welcome, Amy — glad it’s working now! That script should keep running reliably no matter how your theme handles scripts. If you later want it styled to look like a native Divi module (matching your brand colors and buttons), just let me know your hex codes and I’ll drop in a tailored CSS layer so it feels seamless on Paperless Ponte Vedra. draw a picture of an old-fashioned timeclock for the time calculator you just made for me
Replace existing data with this data