Linked JavaScript Calendars for Start and End Dates

Two linked calendar pickers are useful when a form needs a start date and end date. Once a start date is selected, the end-date picker should disable earlier dates; if an end date already exists, the start picker should disable later dates. The form should still validate the relationship before submission.

if (startDate && candidate < startDate) {
  endDayButton.disabled = true;
}

if (endDate && candidate > endDate) {
  startDayButton.disabled = true;
}

This builds on the single date-to-input picker, the month/year navigation picker, and the two independent picker demo.

Define the Start and End Date Rules Top ↑

  • The end date may equal the start date or come later.
  • The start date may equal the end date or come earlier.
  • Changing one value should re-check the other value.
  • The end picker can open at the selected start month when that helps the user.
  • Disabled dates should be truly disabled, not merely displayed in another color.

Parse Date-Only Values without UTC Surprises Top ↑

For a value such as 2026-09-10, split the components and construct a local Date explicitly. This avoids relying on ambiguous display parsing and makes validation possible.

function toLocalDate(value) {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return null;
  const [year, month, day] = value.split("-").map(Number);
  const date = new Date(year, month - 1, day);
  return date.getFullYear() === year &&
         date.getMonth() === month - 1 &&
         date.getDate() === day ? date : null;
}

Disable Dates Outside the Allowed Range Top ↑

When rendering the end calendar, compare each candidate date with the selected start date. Reverse the comparison when rendering the start calendar.

function isAllowed(candidate, role, startDate, endDate) {
  if (role === "end" && startDate && candidate < startDate) return false;
  if (role === "start" && endDate && candidate > endDate) return false;
  return true;
}

Keep Both Pickers Synchronized Top ↑

If the start date changes to a value later than the existing end date, either clear the now-invalid end date or ask the user to correct it. Do not silently keep an invalid range.

startInput.addEventListener("change", () => {
  if (endInput.value && startInput.value > endInput.value) {
    endInput.value = "";
  }
});

The linked demo opens the end-date calendar at the start-date month when a start date exists. This reduces unnecessary navigation for common booking/range workflows.

Validate the Range Even When the UI Disables Dates Top ↑

Client-side disabling improves the experience, but it is not a security boundary. A user can alter request values, so validate the date syntax and the start/end relationship again on the server when the range affects a query, booking, report, or transaction.

if (startInput.value && endInput.value < startInput.value) {
  endInput.setCustomValidity(
    "End date must be on or after the start date."
  );
} else {
  endInput.setCustomValidity("");
}

Use the Selected Range in a Database Query Top ↑

The original project demonstrated a SQL BETWEEN expression generated in the browser. That is useful for understanding the intended range, but application code should never concatenate untrusted form values directly into SQL. Send the dates to the server, validate them, and use parameters/prepared statements.

// Conceptual SQL after server-side validation
SELECT *
FROM dt_tb
WHERE dt BETWEEN ? AND ?

Demo: preview a date-range query pattern

Accessibility and User Experience Top ↑

Use labeled controls, real buttons for calendar actions, aria-expanded/aria-controls for popup state, and native disabled for unavailable days. Do not communicate the range restriction with color alone. Native <input type="date"> with min/max may be simpler when a custom calendar is not required.

Demo and Download Top ↑

Demo: linked start and end date calendars

Download the linked JavaScript date range calendar example

Date Reference All Date Projects




Subscribe to our YouTube Channel here



plus2net.com










✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer