Skip to content

About

A modern, responsive, and internationalizable date and time picker plugin built for jQuery and optimized for Bootstrap 5.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

🗓️ Extended DateTimePicker

A jQuery date and time picker styled with Bootstrap 5. Use it as an input dropdown or an always-visible inline control, with single dates, ranges, multiple dates, or birthdays.

🎮 Playground · 📦 npm · 💻 GitHub · 🐛 Report an issue · 📝 Changelog

See the changelog for the changes included in each version.

🧭 Contents

✨ Features

  • 📅 Four selection modes: single date, range, multiple dates, and birthday.
  • 🕒 Optional clock: 12-hour or 24-hour display, with separate start/end times for ranges.
  • 🚫 Date restrictions: minimum/maximum dates, blocked dates, and disabled weekends.
  • 📐 Responsive layouts: vertical or horizontal, with optional two-month calendars.
  • 🌍 Spanish and English: built-in dictionaries, custom labels, and translated accessible controls.
  • ⌨️ Form integration: keyboard navigation, selection callbacks, and native input/change events.

📦 Installation

Requirements

The picker needs jQuery and Bootstrap CSS, plus its own JavaScript and CSS. Bootstrap JavaScript is not required by the picker itself.

The package declares jQuery >=3.0.0 and Bootstrap >=5.0.0 as peer dependencies. Use Bootstrap 5.3.8 for the theme utilities used by the current demo. A clean consumer installation was verified with jQuery 3.7.1 + Bootstrap 5.3.8.

With npm and a bundler

npm install jquery-extended-datetimepicker jquery bootstrap

Add a target to your page:

<label for="my-datepicker">Choose a date</label>
<input id="my-datepicker" type="text" class="form-control" />

Import the plugin and both stylesheets in your JavaScript entry point:

import $ from "jquery";
import "bootstrap/dist/css/bootstrap.min.css";
import "jquery-extended-datetimepicker";
import "jquery-extended-datetimepicker/dist/jquery.extended.datetimepicker.min.css";

$(function () {
  $("#my-datepicker").extendedDateTimePicker({
    lang: "en",
    showClock: false,
  });
});

The package entry is ESM. It imports jQuery from your project; there is no need to create a global $ for this setup.

With browser script tags / CDN

Load jQuery before the plugin. This example pins version 1.5.3; use the release you want to deploy.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Date picker example</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-extended-datetimepicker@1.5.3/dist/jquery.extended.datetimepicker.min.css" />
  </head>
  <body>
    <label for="my-datepicker">Choose a date</label>
    <input id="my-datepicker" type="text" class="form-control" />
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery-extended-datetimepicker@1.5.3/dist/jquery.extended.datetimepicker.min.js"></script>
    <script>
      $("#my-datepicker").extendedDateTimePicker({ lang: "en", showClock: false });
    </script>
  </body>
</html>

For self-hosted files, replace the plugin CDN URLs with paths to the files in dist/. Do not load the ESM file as a classic browser script.

🎛️ Selection modes

Mode Use it for Initial selection
single One appointment or date One ISO date
range A start and end date Up to two ISO dates
multiple Separate dates An array of ISO dates
birthday Day, month, and year controls One ISO date, year 1900 through the current year

📅 Single date

$("#my-datepicker").extendedDateTimePicker({
  mode: "single",
  lang: "en",
  showClock: false,
  selectedDates: ["2026-10-15"],
  dateFormat: "DD/MM/YYYY",
});
// Input: 15/10/2026

↔️ Range with individual times

$("#range-picker").extendedDateTimePicker({
  mode: "range",
  lang: "en",
  doubleMonth: true,
  selectedDates: ["2026-10-15", "2026-10-20"],
  defaultTime: ["09:00", "17:30"],
});
// Input: 2026-10-15 09:00 to 2026-10-20 17:30

🗓️ Multiple dates

$("#multiple-picker").extendedDateTimePicker({
  mode: "multiple",
  showClock: false,
  selectedDates: ["2026-10-15", "2026-10-20", "2026-10-23"],
});

🎂 Birthday

$("#birthday-picker").extendedDateTimePicker({
  mode: "birthday",
  lang: "en",
  showClock: false,
  selectedDates: ["2000-01-01"],
  dateFormat: "DD/MM/YYYY",
});

📌 Inline control

Use a container instead of an input. The same configuration options apply:

<div id="inline-picker"></div>
$("#inline-picker").extendedDateTimePicker({
  showClock: false,
  selectedDates: ["2026-10-15"],
});

An input opens on focus or click. An inline container is visible immediately. Initialization replaces the contents of an inline container; destroying it does not restore those contents.

📅 Dates, times, and restrictions

Input values versus display format

  • Always pass dates as YYYY-MM-DD strings, including selectedDates, minDate, maxDate, and disabledDates. Do not pass Date objects to these options.
  • dateFormat changes the displayed output, not the format of configuration values. Supported tokens are YYYY, YY, MM, M, DD, and D.
  • Pass defaultTime in 24-hour HH:mm format, even when format24h is false. A range accepts either one time for both ends or an array of two times.
  • Without defaultTime, the clock starts at 06:00 for single/multiple/birthday modes, or 00:00 and 23:59 for a range. Invalid time strings use those defaults.
  • Date objects returned by callbacks represent local dates, not UTC timestamps.

Restrict selectable dates

$("#my-datepicker").extendedDateTimePicker({
  minDate: "2026-10-01",
  maxDate: "2026-10-31",
  disableWeekends: true,
  disabledDates: ["2026-10-12"],
  showClock: false,
});

Restrictions apply to initial selections, calendar clicks, birthdays, and Today. Invalid or blocked initial dates are ignored. For ranges, restrictions apply to the endpoints; blocked dates inside a selected range are permitted.

A blocked birthday edit clears the submitted input value until a valid date is selected again. Invalid date limits, reversed limits, unsupported modes, and malformed translations throw before replacing an existing picker.

Use only the clock

$("#time-picker").extendedDateTimePicker({
  showCalendar: false,
  showClock: true,
  format24h: false,
  defaultTime: "14:30",
});
// Input: 02:30 PM

⚙️ Configurable Options Table

Option Type Default Description / Allowed Values
mode string 'single' 'single', 'range', 'multiple', or 'birthday'.
layout string 'vertical' 'vertical' or 'horizontal'. Horizontal applies when both calendar and clock are visible outside birthday mode.
showCalendar boolean true Show the calendar; birthday mode uses its own date controls.
showClock boolean true Show the clock. Set to false for date-only selection.
themeColor string 'success' Bootstrap color name, such as 'primary', 'success', or 'danger'.
format24h boolean true Use 24-hour display; false shows 12-hour time with AM/PM.
defaultTime string/array/null null Initial HH:mm time, or two times for a range. Configuration always uses 24-hour format.
selectedDates array [] Initial ISO dates. Single/birthday use one; range uses up to two; multiple accepts several.
minDate string/null null Earliest selectable ISO date, inclusive.
maxDate string/null null Latest selectable ISO date, inclusive.
disableWeekends boolean false Disable Saturdays and Sundays.
disabledDates array [] Specific ISO dates that cannot be selected.
doubleMonth boolean false Display two consecutive calendar months.
dateFormat string 'YYYY-MM-DD' Output format, for example 'DD/MM/YYYY'.
lang string/object 'es' 'es', 'en', or a partial/custom translation object.
actions array ['close', 'today', 'now', 'clear'] Footer buttons in the supplied order; [] hides them. Today requires the calendar; Now requires the clock; Close closes input dropdowns.

🔄 Callbacks / Events

Callback Default Parameters and behavior
onOpen No-op function No arguments. Runs when a picker opens; this is the target element.
onClose No-op function No arguments. Runs when a picker closes, including when another input picker opens; this is the target element.
onSelectDate null (dateObj, formattedDates): a Date for single/birthday, an array of dates for range/multiple, and an array of formatted strings. Clear or a blocked birthday edit returns (null, []). Today also invokes this callback.
onSelectTime null (timeState): { hour, minute }, plus ampm in 12-hour mode. Range mode returns an array of start/end time objects.
$("#my-datepicker").extendedDateTimePicker({
  onSelectDate(date, formattedDates) {
    console.log("Selected dates:", formattedDates);
  },
  onSelectTime(time) {
    console.log("Selected time:", time);
  },
});

$("#my-datepicker").on("change", function () {
  console.log("Form value:", this.value);
});

Form behavior:

  • Initialization does not emit selection callbacks or input/change events.
  • User edits emit input and change when the input value changes.
  • An existing input value is preserved when no initial date selection is supplied, except in clock-only mode, which initializes the time. Existing text is not parsed into a selection.
  • Clear empties the input and controls. Editing again restores the controls from their last valid state.

🛠️ Public methods

$("#my-datepicker").extendedDateTimePicker("open");
$("#my-datepicker").extendedDateTimePicker("close");
$("#my-datepicker").extendedDateTimePicker("destroy");

Methods preserve jQuery chaining. Supported methods do nothing on uninitialized elements; unknown names throw an error.

Calling the plugin again with options replaces the current instance. destroy removes plugin controls/listeners and restores the input's original attributes. It does not restore content previously removed from an inline container.

🌍 Languages

Spanish is the default. Select English with lang: "en", or customize individual labels:

$("#my-datepicker").extendedDateTimePicker({
  lang: {
    actions: { clear: "Reset selection", close: "Close picker" },
  },
});

Partial custom dictionaries and unknown language codes fall back to Spanish. To customize English labels without Spanish fallbacks, start from the complete English dictionary:

import en from "jquery-extended-datetimepicker/langs/en.json";

en.actions.clear = "Reset selection";
$("#my-datepicker").extendedDateTimePicker({ lang: en });

JSON imports require bundler support; direct Node.js JSON imports may require import attributes. Dictionary exports are available starting with version 1.5.3.

Custom dictionary rules:

  • calendar, clock, birthday, and actions must be objects when supplied.
  • Labels must be strings; translations are displayed as plain text, not HTML.
  • Month arrays require 12 strings; weekday arrays require 7 strings.
  • Calendar weekday labels use calendar.weekdaysShort.
  • Accessible labels use calendar.title, calendar.previous, calendar.next, and clock/birthday keys increase and decrease.
  • Range clock headings use clock.start and clock.end.

For contributors, src/js/modules/i18n.js is the single editable source. Run npm run langs:sync to regenerate langs/es.json and langs/en.json; do not edit the generated JSON files by hand. The build also regenerates them.

⌨️ Keyboard and layout

Key Action
Tab / Shift+Tab Move between controls.
Arrow keys on calendar days Move one day left/right or one week up/down within the rendered calendar, skipping disabled dates.
Enter / Space Select a focused calendar day.
Escape Close an input dropdown and return focus to its input.

The horizontal layout switches to vertical when the component's available width is small. Two-month calendars can scroll horizontally in narrow containers. Clock buttons have larger targets on touch devices, and clock-only mode omits the date/clock separator.

The component uses Bootstrap CSS variables and CSS container queries. Keep the viewport meta tag in mobile pages and use browsers with container-query support.

🧑‍💻 Local development

Use npm; package-lock.json is the dependency lockfile. The current test dependencies require Node.js ^22.22.2, ^24.15.0, or >=26.0.0.

git clone https://github.com/PinedaMB/extended_datetimepicker.git
cd extended_datetimepicker
npm ci
npm run dev

Open the local URL printed in the terminal (normally http://127.0.0.1:5173/). Changes to src/, docs/index.html, and docs/playground.css update the demo automatically. Stop the server with Ctrl+C.

The local demo uses source modules and local jQuery. Bootstrap is loaded from its CDN, so the playground still needs internet access for those assets. Development does not refresh dist/; run the build when you need distribution files.

Command Purpose
npm run dev Start the local playground with automatic updates.
npm test Run regression tests.
npm run build Generate translation JSON, build ESM/browser bundles and CSS, copy assets to the demo, and synchronize its reference tables.
npm run langs:sync Regenerate JSON dictionaries from the source translations.
npm run langs:check Verify that generated dictionaries match the source.
npm run docs:sync Update the playground's options/callbacks tables from this README.
npm run docs:check Verify that those tables are synchronized.
npm audit Check installed dependency advisories.
npm pack --dry-run Inspect the package contents without publishing.

Only the options and callbacks tables synchronize automatically from the README. Other playground documentation is maintained separately. The playground applies settings to both previews; applying with an empty initial-date field removes its previous preselection and input value.

Before preparing a release, run the build, tests, documentation/translation checks, and package inspection. Record changes under Unreleased in CHANGELOG.md, then assign the release version when publishing.

🩺 Troubleshooting

Symptom Check
extendedDateTimePicker is not a function Load jQuery before the classic plugin script; with a bundler, import both from the same project.
The picker has no styling or the layout looks wrong Include both Bootstrap CSS and the plugin CSS.
A configured date is missing Use valid ISO strings and check limits, weekends, blocked dates, and birthday year bounds.
The output is in Spanish Set lang: "en"; partial custom dictionaries fall back to Spanish.
Source edits do not appear in the published demo npm run dev previews source; run npm run build to refresh distributable/demo assets before deployment.
Translation JSON checks fail after editing labels Run npm run langs:sync and include the regenerated JSON files in the change.

👤 Author and license

Created and maintained by Brayan Pineda Méndez / PinedaMB.

📄 Licensed under MIT. Contributions and reproducible bug reports are welcome through GitHub Issues.

About

A modern, responsive, and internationalizable date and time picker plugin built for jQuery and optimized for Bootstrap 5.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages