The subscription renewal and trial conversion reminder emails render the date as MM/DD/YYYY (e.g. 07/11/2026), which is ambiguous for non-US readers (could read as 11 July or 7 November).
Audited all 37 email templates under server/emails/src/emails/ plus shared components: this is the only ambiguous date format in any customer-facing email. Every other template either renders no date, or already uses an unambiguous long format (toLocaleDateString('en-US', { month: 'long', ... }), e.g. "March 17, 2026").
Where it happens:
server/polar/subscription/service.py: send_renewal_reminder_email sets renewal_date = subscription.current_period_end.strftime("%m/%d/%Y"), send_trial_conversion_reminder_email sets conversion_date = subscription.trial_end.strftime("%m/%d/%Y")
server/emails/src/emails/subscription_renewal_reminder.tsx and subscription_trial_conversion_reminder.tsx just echo the pre-formatted string (PreviewProps show '04/15/2026' / '03/17/2026')
server/polar/subscription/repository.py has matching to_char(..., "MM/DD/YYYY") SQL clauses in get_subscriptions_needing_renewal_reminder and get_subscriptions_needing_trial_conversion_reminder, used for a duplicate-send idempotency check, coupled to this format
Fix: format with the existing unambiguous long-date helper (format_date in server/polar/invoice/generator.py, using babel.dates.format_date(..., format="long", locale="en_US"), already used for invoices/receipts) instead of strftime("%m/%d/%Y"), e.g. "November 7, 2026". Update the two to_char clauses in repository.py to match, or refactor those idempotency checks to compare against the raw timestamp instead of a formatted string. Update the PreviewProps mock values in the two .tsx templates for consistency.
Sent by @emilwidlund from Date normalization task.
The subscription renewal and trial conversion reminder emails render the date as
MM/DD/YYYY(e.g.07/11/2026), which is ambiguous for non-US readers (could read as 11 July or 7 November).Audited all 37 email templates under
server/emails/src/emails/plus shared components: this is the only ambiguous date format in any customer-facing email. Every other template either renders no date, or already uses an unambiguous long format (toLocaleDateString('en-US', { month: 'long', ... }), e.g. "March 17, 2026").Where it happens:
server/polar/subscription/service.py:send_renewal_reminder_emailsetsrenewal_date = subscription.current_period_end.strftime("%m/%d/%Y"),send_trial_conversion_reminder_emailsetsconversion_date = subscription.trial_end.strftime("%m/%d/%Y")server/emails/src/emails/subscription_renewal_reminder.tsxandsubscription_trial_conversion_reminder.tsxjust echo the pre-formatted string (PreviewProps show'04/15/2026'/'03/17/2026')server/polar/subscription/repository.pyhas matchingto_char(..., "MM/DD/YYYY")SQL clauses inget_subscriptions_needing_renewal_reminderandget_subscriptions_needing_trial_conversion_reminder, used for a duplicate-send idempotency check, coupled to this formatFix: format with the existing unambiguous long-date helper (
format_dateinserver/polar/invoice/generator.py, usingbabel.dates.format_date(..., format="long", locale="en_US"), already used for invoices/receipts) instead ofstrftime("%m/%d/%Y"), e.g. "November 7, 2026". Update the twoto_charclauses inrepository.pyto match, or refactor those idempotency checks to compare against the raw timestamp instead of a formatted string. Update the PreviewProps mock values in the two.tsxtemplates for consistency.Sent by @emilwidlund from Date normalization task.