diff --git a/backend/server3.js b/backend/server3.js index 029168d..97b29f5 100644 --- a/backend/server3.js +++ b/backend/server3.js @@ -4069,17 +4069,43 @@ app.post('/api/premium/tasks', authenticatePremiumUser, async (req, res) => { }; /* ───────────────── SMS reminder ───────────────── */ - if (due_date) { // only if task has a due date + // helper: 2:00 PM America/New_York → UTC ISO for a given YYYY-MM-DD + function ny2pmUtcIso(dateStr) { + const m = String(dateStr || '').match(/^(\d{4})-(\d{2})-(\d{2})$/); + if (!m) return new Date(dateStr).toISOString(); + const y = +m[1], mo = +m[2], d = +m[3]; + // iterative align: find the UTC instant that shows as 14:00 in NY on that calendar date + const dtf = new Intl.DateTimeFormat('en-US', { + timeZone: 'America/New_York', + hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', + hour: '2-digit', minute: '2-digit', second: '2-digit' + }); + let utc = Date.UTC(y, mo - 1, d, 19, 0, 0, 0); // good first guess (19:00Z ~= 2pm EST) + for (let i = 0; i < 3; i++) { + const parts = Object.fromEntries(dtf.formatToParts(new Date(utc)).map(p => [p.type, p.value])); + // ensure same calendar day in NY; if drifted, nudge by day difference + const dayDiff = (y - (+parts.year)) * 1440*365 // huge; we correct hour/min next anyway + + (mo - (+parts.month)) * 1440*31 + + (d - (+parts.day)) * 1440; + const hDiff = 14 - (+parts.hour); + const mDiff = 0 - (+parts.minute); + const deltaMin = (dayDiff !== 0 ? dayDiff : 0) + hDiff * 60 + mDiff; + if (deltaMin === 0) break; + utc += deltaMin * 60 * 1000; + } + return new Date(utc).toISOString(); + } + + if (finalDue) { // only if task has a due date (incl. fallback) const [[profile]] = await pool.query( 'SELECT phone_e164, phone_verified_at, sms_reminders_opt_in FROM user_profile WHERE id = ?', [req.id] ); if (profile?.sms_reminders_opt_in && profile.phone_verified_at && profile.phone_e164) { - // If due_date is just YYYY-MM-DD, schedule at 14:00:00Z that day - const isoSend = - /^\d{4}-\d{2}-\d{2}$/.test(String(finalDue)) - ? `${finalDue}T14:00:00.000Z` - : new Date(finalDue).toISOString(); + // If due_date is date-only, schedule at 2:00 PM America/New_York (DST-aware) + const isoSend = /^\d{4}-\d{2}-\d{2}$/.test(String(finalDue)) + ? ny2pmUtcIso(String(finalDue)) + : new Date(finalDue).toISOString(); await createReminder({ userId : req.id,