# Shadcn Date Time Picker with Time Zones and Presets

> A shadcn date time picker in one field: calendar, free time slots, presets and a time zone label, a zone select beside it, and a bottom sheet on phones.

- Author: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Published: Nov 5, 2026
- Category: [Component guides](https://wingo-ui.com/blog/category/components)
- Reading time: 9 min
- Canonical: https://wingo-ui.com/blog/shadcn-date-time-picker

## TL;DR

shadcn/ui has no date time picker: its docs pair the Calendar in a popover with a separate input type="time", so you combine the two values and handle time zones yourself. A complete shadcn date time picker keeps one Date value, shows the free time slots for the chosen day beside the calendar, labels the time zone, and opens a bottom sheet on phones. The Wingo UI Date Time Picker does that, and the Timezone Select next to it lets people change the zone.

You want a shadcn date time picker for a booking, a reminder or a scheduled send: one field where someone picks a day and a time, sees which time zone it is in, and gets a value your server can store without guessing. shadcn/ui gives you a Calendar and an input, and you wire up the rest. This guide covers what that wiring has to solve, the props that matter in the Wingo UI [Date Time Picker](https://wingo-ui.com/components/date-time-picker), how to pair it with a [Timezone Select](https://wingo-ui.com/components/timezone-select), and what both turn into on a phone.

## Does shadcn/ui have a date time picker?

No. As of November 2026 the shadcn/ui [Date Picker docs](https://ui.shadcn.com/docs/components/date-picker) include a "Time Picker" example, and its [source](https://github.com/shadcn-ui/ui/blob/main/apps/v4/examples/radix/date-picker-time.tsx) shows the pattern: shadcn's Calendar inside a Popover for the day, and next to it a plain `<Input type="time" step="1" defaultValue="10:30:00" />`. The day lives in React state as a `Date`, the time stays inside the uncontrolled input, and nothing joins the two. That is a fine starting point, and it leaves four jobs to you:

- **One value.** You have a `Date` at local midnight and a `"10:30:00"` string. Somebody has to merge them, in the right time zone.
- **Time zones.** The browser's zone is assumed everywhere. The Calendar underneath is react-day-picker, whose [timeZone prop](https://daypicker.dev/localization/setting-time-zone) renders the days in an IANA zone but does not pick a time of day.
- **Availability.** A native time input accepts any minute. It cannot strike through 10:00 because it is already booked.
- **Phones.** The popover is anchored to a small trigger, and the native time control looks different in every browser.

Community shadcn datetime picker repos fill part of the gap. As of November 5, 2026, [rudrodip/shadcn-date-time-picker](https://github.com/rudrodip/shadcn-date-time-picker) has 310 GitHub stars, an MIT license and a last push in May 2025. It ships 12 and 24 hour variants that put hour and minute button columns next to the calendar in one popover, plus react-hook-form and zod examples; its README does not mention time zones or a phone layout. [maliksidk19/shadcn-datetime-picker](https://github.com/maliksidk19/shadcn-datetime-picker) has 281 stars and a last push in July 2026, and its README lists a lot: a calendar beside a scrollable time list in one popover, a timezone selector with offsets, 15, 30 or 60 minute intervals with min and max times, and a Drawer below 768px. It is free (MIT according to its README) and enough for many forms. Where it stops is per-day availability: the README covers fixed intervals, time limits and disabled dates, but nothing that marks a single slot as taken.

| As of Nov 5, 2026 | shadcn/ui example | rudrodip repo | maliksidk19 repo | Wingo UI Date Time Picker |
|---|---|---|---|---|
| Value | separate `Date` and time string | one `Date` | one `Date` | one `Date`, submitted as ISO |
| Time input | native `type="time"` | hour and minute columns | scrollable slot list | slot list from your availability, taken slots struck through |
| Time zone | browser zone | not mentioned | timezone selector | IANA `timeZone`, label with offset, optional switch |
| Presets | no | not mentioned | not mentioned | In 1 hour, Tomorrow 9:00, Monday 9:00, or your own |
| Phone | same popover | same popover | Drawer below 768px | bottom sheet with 44px chip rails |
| Price | free, MIT | free, MIT | free, MIT (README) | Pro |

## What should a React date time picker do?

A React date time picker is done when the person can answer "when?" in one place. In practice that means:

1. **A calendar and the free times for the chosen day, side by side**, the way booking pages work.
2. **One absolute value**: a `Date` that means the same instant everywhere, never a local date plus a loose time.
3. **A visible time zone.** "2:30 PM" means nothing in a team spread across New York and Berlin. The label belongs in the panel, with the UTC offset for that date, because daylight saving time changes it.
4. **Shortcuts.** Most reminders are "in an hour" or "tomorrow morning".
5. **A layout for thumbs.** Below 768px a popover with two columns does not fit. A bottom sheet with large chips does.

## Which props matter in the Wingo UI Date Time Picker?

Most forms need only the value, `timeZone`, the slot grid or `getTimeSlots`, the limits, `presets` and `name`. Install it with `npx wingo-ui@latest add date-time-picker`. The CLI copies `components/ui/date-time-picker.tsx` into your project and pulls in the [Calendar](https://wingo-ui.com/components/calendar), Select, Drawer, Field and the date and motion helpers it imports.

The value is a `Date | null`, controlled with `value` and `onValueChange` or uncontrolled with `defaultValue`. The props you will reach for:

- `timeZone`: the IANA zone the wall times are picked in (`"America/New_York"`). The calendar and slots show that zone's clock, and wall times skipped by a daylight saving jump are disabled. Leave it empty for the device zone.
- `minuteStep`, `startTime`, `endTime`: the default slot grid, 15 minutes from `"00:00"` to `"23:59"`. Use `startTime="09:00"` and `endTime="17:00"` for business hours.
- `getTimeSlots`: per-day availability that replaces the grid. Return `"HH:mm"` strings or `{ time, disabled, label }` objects, or a Promise of them. Answers are cached per function and day, so define it outside the component.
- `disablePast`, `min`, `max`, `disabledDays`: limits. `disabledDays={{ dayOfWeek: [0, 6] }}` closes weekends.
- `presets`: `true` for In 1 hour (rounded up to the step), Tomorrow 9:00 and Monday 9:00, or your own `{ label, value }` list.
- `showTimeZone` and `timeZones`: the zone label in the footer is on by default; a `timeZones` array turns it into a select.
- `name`: submits `value.toISOString()` through a hidden input, so a plain form or a Server Action gets a UTC string.

Open the field below, try a preset, then pick a day and a time. Taken slots are struck through, and the footer names the zone.

> Live demo (Date Time Picker): Click the field, try a preset chip, then pick a weekday and a free slot: taken times are struck through, the footer shows the time zone, and at phone width the panel opens as a bottom sheet. Try it at [Date Time Picker](https://wingo-ui.com/components/date-time-picker) and install it with `npx wingo-ui@latest add date-time-picker`.

Keyboard: arrows move by day and week, Tab moves to the time list, typing `14` jumps to 2:00 PM, Enter picks and closes, Escape returns focus to the field.

## How do I add a time zone picker next to it?

Put a React timezone select above the picker and pass its value to `timeZone`. You need one when the zone is a choice the person makes, such as a host scheduling a call for a client abroad. The Wingo UI [Timezone Select](https://wingo-ui.com/components/timezone-select) lists every zone the browser knows, grouped by region, with live UTC offsets. People can search by city ("tokyo"), abbreviation ("CET") or offset ("+5:30"), and a first row picks their own zone. Install it with `npx wingo-ui@latest add timezone-select`.

> Live demo (Timezone Select): Focus the field and type tokyo, EST or +2: the list filters as you type, each row shows its offset and local time, and the first row picks your own zone. Try it at [Timezone Select](https://wingo-ui.com/components/timezone-select) and install it with `npx wingo-ui@latest add timezone-select`.

The Date Time Picker follows its `timeZone` prop, so a new zone redraws the calendar and the slots in that zone's clock. The Timezone Select also takes a `name`, so the zone id goes out with the form.

## How do I build a booking field with a time zone?

Here is a complete React date time picker with timezone support: a client form with the zone select above the picker, availability from a stable function, and a Server Action that receives the ISO string and the zone id.

```tsx
"use client";

import { useState } from "react";
import { Globe } from "lucide-react";
import { Button } from "@/components/ui/button";
import { DateTimePicker, buildTimeSlots, type DateTimeSlot } from "@/components/ui/date-time-picker";
import { TimeZoneSelect } from "@/components/ui/timezone-select";
import { bookCall } from "./actions";

// 30 minute calls on weekdays, the last one ending at 5 PM; 12:00 is the team lunch
function freeSlots(day: Date): DateTimeSlot[] {
  if (day.getDay() === 0 || day.getDay() === 6) return [];
  return buildTimeSlots({ step: 30, start: "09:00", end: "16:30" }).map((time) => ({
    time,
    disabled: time === "12:00",
  }));
}

export function BookCallForm() {
  const [timeZone, setTimeZone] = useState("America/New_York");
  const [startsAt, setStartsAt] = useState<Date | null>(null);

  return (
    <form action={bookCall} className="flex max-w-sm flex-col gap-4">
      <TimeZoneSelect
        label="Time zone"
        leftIcon={<Globe />}
        value={timeZone}
        onValueChange={setTimeZone}
        suggested={["America/New_York", "America/Chicago", "America/Los_Angeles", "Europe/London"]}
        name="time_zone"
      />
      <DateTimePicker
        label="Call with Emma Carter"
        description="30 minutes on a video call."
        value={startsAt}
        onValueChange={setStartsAt}
        getTimeSlots={freeSlots}
        disabledDays={{ dayOfWeek: [0, 6] }}
        disablePast
        presets
        timeZone={timeZone}
        locale="en-US"
        required
        name="starts_at"
      />
      <Button type="submit" tone="brand" disabled={!startsAt}>
        Book the call
      </Button>
    </form>
  );
}
```

```ts
// actions.ts
"use server";

function isTimeZone(zone: string) {
  try {
    new Intl.DateTimeFormat("en-US", { timeZone: zone });
    return true;
  } catch {
    return false;
  }
}

export async function bookCall(formData: FormData) {
  const startsAt = new Date(String(formData.get("starts_at")));
  const timeZone = String(formData.get("time_zone"));
  if (Number.isNaN(startsAt.getTime())) throw new Error("Pick a date and time");
  if (!isTimeZone(timeZone)) throw new Error("Pick a time zone");
  // check the slot is still free, then store startsAt as UTC and timeZone next to it
}
```

`getTimeSlots` receives a local midnight `Date` for the wall day in the chosen zone, so `day.getDay()` is the weekday the person sees. Keep the function at module scope or wrap it in `useMemo`, because the picker caches its answers per function and day. The client never has the last word on availability: two guests can open the same free slot, so the action checks it again before saving.

### Should the time stay the same when the zone changes?

The picker keeps the moment: a 2:30 PM call in New York reads 11:30 AM after switching to Los Angeles. That is right for "when does this meeting happen for me". For "9 AM wherever I am", keep the wall time and move the moment with the helpers the file exports:

```ts
import { getZonedParts, zonedTimeToDate } from "@/components/ui/date-time-picker";

function keepWallTime(value: Date, from: string, to: string) {
  const { date, time } = getZonedParts(value, from);
  return zonedTimeToDate(date, time, to);
}
```

Call it in the select's `onValueChange` before you update the zone. `zonedTimeToDate` handles daylight saving: a repeated hour gives its first occurrence, and `formatTimeZoneLabel(zone, date, "en-US")` prints the zone with the offset for that date ("Eastern Time (UTC−04:00)" in July, "Eastern Time (UTC−05:00)" in December).

## What does it look like on a phone?

With `responsive` on (the default), below 768px the field opens a bottom sheet instead of a popover. The calendar takes the full width, presets and times become horizontal rails of 44px chips, and the chosen time scrolls to the center. The pick is a draft until the big Done button commits it, so dragging the sheet away keeps the old value. The Timezone Select does the same on its side: a tap opens a full-height search sheet with 48px rows and a Cancel button. We picked a sheet because a popover anchored to a field near the bottom of the screen opens under the keyboard or the thumb that tapped it. The [responsive dialog guide](https://wingo-ui.com/blog/shadcn-responsive-dialog-on-mobile) explains the same trade-off for dialogs.

The `inline` prop renders the panel in the page without a trigger, which suits a booking page. Below 640px it puts the times in a grid under the calendar.

> Live demo (Date Time Picker): The inline panel: pick a weekday, then a time. Narrow the frame below 640px and the times move into a grid under the calendar. Try it at [Date Time Picker](https://wingo-ui.com/components/date-time-picker) and install it with `npx wingo-ui@latest add date-time-picker`.

The [demo booking page template](https://wingo-ui.com/templates/demo-booking-page) shows a whole book-a-demo screen built around a Calendar and a time step, if you want the page as well as the field.

## When should I use a different picker?

- Only a time of day, like opening hours or a daily reminder: the [Time Picker](https://wingo-ui.com/components/time-picker) stores `"HH:mm"` and accepts typed input such as "2p". The [React time picker guide](https://wingo-ui.com/blog/react-time-picker) covers it.
- A start and an end date: the [React date range picker guide](https://wingo-ui.com/blog/react-date-range-picker).
- Only a day, with typing: the [Date Picker](https://wingo-ui.com/components/date-picker).
- A calendar of existing events with drag to reschedule: the [React calendar with events guide](https://wingo-ui.com/blog/react-calendar-component-with-events).

## What are the common pitfalls?

- **Building the Date on the server.** `new Date("2026-11-12 14:30")` uses the server's zone. Convert in the person's zone instead.
- **Storing local time without the zone.** Save the UTC instant and the IANA id. An offset like `-05:00` is not enough, because it changes in March.
- **A new `getTimeSlots` on every render** resets the cache and refetches.
- **Hydration.** "Now" differs between the server and the browser. The picker reads the clock after hydration, so presets and `disablePast` settle on the client; pass `now` in tests and screenshots.

## How do I get it?

Run `npx wingo-ui@latest add date-time-picker timezone-select` and the CLI copies both into `components/ui` with everything they import. They are Pro components: $8 a month, $80 a year or $150 once ([pricing](https://wingo-ui.com/pricing)). Open the [Date Time Picker docs](https://wingo-ui.com/components/date-time-picker) to try every prop in the playground first. More single-component deep dives live in the [component guides category](https://wingo-ui.com/blog/category/components), and the [React form components guide](https://wingo-ui.com/blog/react-form-components-guide) shows how the fields fit together.

## Components in this post

- [Date Time Picker](https://wingo-ui.com/components/date-time-picker) (Pro): A React date time picker: a calendar beside a column of free time slots, presets and a time zone label in one field, a sheet on phones. Install: `npx wingo-ui@latest add date-time-picker`
- [Timezone Select](https://wingo-ui.com/components/timezone-select) (Pro): A searchable time zone picker with live UTC offsets, optional local times, region groups and a one-tap Use my time zone row. Install: `npx wingo-ui@latest add timezone-select`
- [Calendar](https://wingo-ui.com/components/calendar) (Pro): A React calendar to pick one day, several days or a range, with disabled days, event dots, several months and a quick month / year jump. Install: `npx wingo-ui@latest add calendar`
- [Time Picker](https://wingo-ui.com/components/time-picker) (Pro): A React time picker to type a time or pick it from columns, with 12 / 24 hours by locale, minute steps, limits and wheels on phones. Install: `npx wingo-ui@latest add time-picker`

## FAQ

### Does shadcn/ui have a date time picker?

Not as of November 2026. The Date Picker docs include a Time Picker example that puts a Calendar popover next to a separate input type="time", with the date and the time kept in two different pieces of state.

### How do I combine a date and a time into one Date in React?

Build the moment in the time zone the person meant, not in the server's: take the day as "YYYY-MM-DD" and the time as "HH:mm" and convert them together. The Wingo UI helper zonedTimeToDate("2026-11-12", "14:30", "America/New_York") returns the absolute Date and handles daylight saving changes.

### What should a React date time picker with timezone submit to the server?

An ISO string in UTC for the moment and the IANA zone id next to it, such as 2026-11-12T19:30:00.000Z and America/New_York. The ISO string is unambiguous, and the zone lets you show the time later the way the person picked it.

### What happens to the picked time when the time zone changes?

In the Wingo UI Date Time Picker the moment stays and the wall clock moves, so a 2:30 PM New York call reads 11:30 AM in Los Angeles. If you want to keep 2:30 PM and move the moment instead, convert it with getZonedParts and zonedTimeToDate.

### Is the Wingo UI Date Time Picker free?

No. The Date Time Picker, Timezone Select, Calendar and Time Picker are Pro components; Pro costs $8 a month, $80 a year or $150 once. The Button, Field, Select and Drawer they build on are free.

---

Source: https://wingo-ui.com/blog/shadcn-date-time-picker
