Expiry Date Calculator
Calculate expiration dates and manage product shelf life
What is Expiry Date Calculator?
Expiry Date Calculator is an online tool that helps you quickly calculate product expiration dates or estimate production dates. Simply enter the production date and shelf life days to get the exact expiration time, or enter the expiry date to reverse-calculate the production date. Supports batch adding of multiple products with real-time remaining days reminder, making it easy to manage food, medicine, cosmetics shelf life at home.
This tool runs locally in your browser, no data upload required, protecting your privacy.
For medical, legal, or financial decisions, the result should be treated as guidance and checked against official rules.
How to Use
How to use
- Select calculation mode: Production→Expiry or Expiry→Production
- Enter date and shelf life days
- Click Calculate to see results
- Add to product list for batch management
Result Checks
- Confirm whether shelf life starts from production date, packaging date, opening date, or receipt date; these rules are not interchangeable.
- For food, medicine, or regulated goods, use the printed label and local rules as the final authority.
Use Cases
Technical Principle
Expiry math is integer date arithmetic anchored to the production date. The forward path computes expiry = production + shelf_life_days using Date.setDate(date.getDate() + n), which handles month and year rollover natively (e.g. 2025-01-31 + 30 = 2025-03-02 because February has 28 days). The reverse path computes production = expiry - shelf_life_days the same way. To avoid DST drift around midnight local time, the page anchors arithmetic to UTC via Date.UTC(y, m, d) and adds whole milliseconds (n * 86400000), because Date.setDate in local time crosses DST boundaries with a one-hour offset that can flip the visible date on March and November transitions in the US, October in the EU. Shelf-life units are normalized to days before the addition: 1 month is treated as 30 days and 1 year as 365 days, matching the heuristic used on most consumer packaging math but not the calendar-exact rule used by regulators. The Codex Alimentarius General Standard for the Labelling of Prepackaged Foods (CXS 1-1985, revised) and China's GB 7718-2025 specify shelf life from the date of manufacture or packaging; pharmaceutical expiry follows ICH Q1A (R2) stability testing guidelines and rounds the printed expiry to the last day of the month (so a drug manufactured 2024-08-15 with an 18-month shelf life is labelled 2026-02-28, not 2026-02-15). The remaining-days counter is (expiry_utc - now_utc) / 86400000 rounded with Math.floor for already-elapsed days and Math.ceil for time-until-expiry, and the freshness band is a thresholded comparison: expired when remaining < 0, expiring-soon when 0 ≤ remaining ≤ 30, fresh otherwise. The persistent watch list lives in window.localStorage under a single namespaced key, serialized via JSON.stringify, which most browsers cap at roughly 5-10 MB per origin (Chrome ~10 MB, Safari ~5 MB). When the quota is exceeded the browser throws a DOMException with name 'QuotaExceededError', and the page must fall back to in-memory state because writes after the throw are silently dropped. localStorage is also synchronous and same-origin, so the entries persist across page reloads but never leave the device. The browser Notification API (which the reminder uses) requires Notification.requestPermission(), is granted per origin, and on Chrome on Windows ≥ 86 actually surfaces through the OS notification centre rather than the browser itself.
- Date arithmetic: Date.setDate(d.getDate() + n) handles month/year rollover natively, but in local time it crosses DST boundaries and can flip the date; Date.UTC + integer ms is the safe path.
- Unit normalization: 1 month ≈ 30 days, 1 year ≈ 365 days - simple but not calendar-exact; pharmaceutical labels follow ICH Q1A (R2) and round to the last day of the expiry month.
- Remaining days = Math.floor((expiry_utc - now_utc) / 86400000); thresholds: remaining < 0 → expired, 0 ≤ remaining ≤ 30 → expiring soon, otherwise fresh.
- Regulatory anchors vary: food shelf life follows Codex CXS 1-1985 / GB 7718-2025 (from production or packaging); cosmetics use PAO (Period After Opening) starting at first use; medicines use ICH Q1A stability dating.
- After-opening shelf life is independent of the printed expiry and is shorter (e.g. opened olive oil ~3 months despite 24-month sealed shelf life); track the open date separately.
- localStorage quota is ~5-10 MB per origin and throws QuotaExceededError (DOMException) when full; writes after the throw are silently dropped, so wrap setItem in try/catch and surface a user warning.
- Browser clock skew (a misconfigured system date) shifts the freshness band; the page reads new Date() rather than a remote time source, so it inherits any client-side clock error.
Examples
Production 2026-01-01 + 730 days = 2027-12-31
Mode: Production -> Expiry
Production date: 2026-01-01
Shelf life: 730 days (2 years)
Expiry date: 2027-12-31
Status: still within shelf lifePharmaceutical: 18-month shelf life
Drug batch lot: A26-0215
Production: 2026-02-15
Shelf life: 18 months (approx 548 days)
Expiry: 2027-08-15
Label note - pharma rule of thumb: expire on the last day
of the month, so the printed date may read 2027-08-31Reverse calculation: Expiry -> Production
Mode: Expiry -> Production
Printed expiry on package: 2028-06-30
Shelf life: 36 months
Produced on or before: 2025-06-30
Use this to verify a supplier's claimed production date
against the batch label.Food storage check
Item: Olive oil 500ml
Production: 2025-12-01
Shelf life: 24 months
Expiry: 2027-12-01
Check: within shelf life; rotate stock by FIFO and plan a discount ~30 days before expiryFAQ
How is the expiry date calculated?
Production date + duration = expiry date. Duration accepts days, weeks, months, or years. Months are added by clamping to the last day of the target month (so 31 Jan + 1 month = 28/29 Feb), matching how most regulators interpret 'X months from manufacture'.
Are days remaining counted from today?
Yes. The page shows remaining days, weeks, and months from today's date in your local time zone. Negative numbers indicate the product is past its expiry. The status label (fresh / nearing expiry / expired) helps with quick triage.
What's the difference between best-before and use-by?
Best-before is a quality date - food is still safe after, just may have lost peak flavor or texture. Use-by is a safety date - foods may pose health risks past it. Cosmetics and medicines often have a 'PAO' (period after opening) symbol that overrides the printed expiry once opened.
Does the result account for storage conditions?
No. Printed expiry dates assume the manufacturer's recommended storage (cool, dry, sealed, refrigerated, frozen). Heat, humidity, and light shorten real-world shelf life and the page can't model that. Treat the calculated date as an upper bound.
How should I handle 'expired' food or medicine?
For unopened canned goods and dry staples, slightly past best-before is usually fine - check appearance and smell. Dairy, meat, and fish past use-by should be discarded. Medicines past expiry can lose potency and a few are unsafe; do not rely on them for serious treatment.
Can I track multiple products?
Open additional tabs - each tab is independent. The page does not maintain a saved inventory. For ongoing tracking, an inventory app or a simple spreadsheet is more practical.
Is my data uploaded?
No. The calculation runs in your browser and is not saved between sessions.