nb-date-picker

This is a date picker component for Vue.js 3+.

Loading component...

Installation

Yarn
yarn add @vlalg-nimbus/nb-inputs
NPM
npm install @vlalg-nimbus/nb-inputs

Usage

Vue 3
import { createApp } from 'vue'
import App from './App.vue'

import NbInputComponents from '@vlalg-nimbus/nb-inputs'
import "@vlalg-nimbus/nb-inputs/dist/style.css";

// Import the Calendar component from the npm package to use in the nb-date-picker component
import { Calendar } from '@vlalg-nimbus/nb-calendar';
import "@vlalg-nimbus/nb-calendar/dist/style.css"

const app = createApp(App)
app.use(NbInputComponents)
app.component('Calendar', Calendar); // Register the Calendar component globally
app.mount('#app')
Nuxt 3
import NbInputComponents from '@vlalg-nimbus/nb-inputs'
import "@vlalg-nimbus/nb-inputs/dist/style.css";

// Import the Calendar component from the npm package to use in the nb-date-picker component
import { Calendar } from '@vlalg-nimbus/nb-calendar';
import "@vlalg-nimbus/nb-calendar/dist/style.css"

export default defineNuxtPlugin(context => {
  context.vueApp.use(NbInputComponents)
  context.vueApp.component('Calendar', Calendar); // Register the Calendar component globally
})

To use, simply call the component, in this case it will be NbDatePicker or nb-date-picker.

Mode 1
<template>
  <NbDatePicker />
</template>
Mode 2
<template>
  <nb-date-picker />
</template>
Mode 3
<template>
  <nb-date-picker></nb-date-picker>
</template>

Preview & Playground

Select the component you want to edit/test

Loading Sandbox...

Props

Items with an (*) mean they are required

To set initial value, use the inputText prop.

Important: The inputText prop accepts different formats depending on the inputType. Invalid formats will be automatically cleared (set to empty string). See the Accepted Formats section below for details.

nameValue typeDefaultDescription
inputTextString/Date''Defines the initial date value. Accepts different formats depending on inputType. See Accepted Formats section for details.

Other props

nameValue typeDefaultDescription
nbId (*)StringSets the id attribute to differentiate from other components
inputName (*)StringSets the name attribute for the input element
displayString'b'Defines the display type. Accepts ib and b.
tabIndexNumber0Defines the tab index. Set this property to make the input focusable by the keyboard.
hasTabIndexEnterBooleantrueDefines if pressing Enter should trigger the entered event.
ariaLabelString'Alternate Text Button'Defines the aria-label attribute for screen readers.
ariaAttrsObject{}Allows passing custom aria attributes as an object. Keys will automatically receive the aria- prefix. Example: { 'describedby': 'help-id', 'invalid': 'false' }
titleString''Tooltip text shown when hovering over the component.
themeString'light'Defines the theme. Accepts light and dark.
disabledBooleanfalseDefines if the input is disabled
requiredBooleanfalseDefines if the input is required
inputReadonlyBooleanfalseDefines if the input is readonly
blockPasteBooleanfalseWhen set to true, prevents pasting content into the input field.
inputTypeString'date'Defines the input type. Accepts date, month, time, datetime-local, week.
inputTextString''Defines the initial input value. Accepts String in ISO format (YYYY-MM-DD, YYYY-MM-DDTHH:mm, YYYY-MM-DDTHH:mm:ss, YYYY-MM, YYYY-Www) or JSON string for ranges.
localeString'en-US'Defines the locale. Accepts pt-BR and en-US.
allowRangeBooleanfalseDefines if date range selection is allowed. When enabled, the input accepts ranges in format "DD/MM/YYYY - DD/MM/YYYY".
calendarZIndexNumber10000Defines the z-index of the calendar popup when using custom calendar. Useful when the calendar needs to appear above modals or other elements.
calendarWidthNumber350Defines the width of the calendar popup in pixels. Minimum value is 280.
blockClicksWithoutEventsBooleanfalseWhen set to true, prevents clicking on dates that don't have events in the calendar. Only dates with events can be selected. This prop is passed to the Calendar component. Useful for date pickers where only specific dates should be selectable.
minString''Defines the minimum selectable date. Accepts String (YYYY-MM-DD). For time types, accepts String (HH:mm or HH:mm:ss).
maxString''Defines the maximum selectable date. Accepts String (YYYY-MM-DD). For time types, accepts String (HH:mm or HH:mm:ss).
stepString/Number''Defines the step for date selection. For inputType="date", step is in days. For inputType="time" or inputType="datetime-local", step is in seconds.
hasSecondsBooleannullDefines if the time input includes seconds. When null, detected automatically from the value/format. Only applies to inputType="time" and inputType="datetime-local".
hasTrimBooleanfalseDefines if the input value should be trimmed (spaces removed from start and end).
fontFamilyString"'Lato', sans-serif"Defines the font-family for the input
fontSizeStringnull (default: 1.4em)Defines the font-size for the input. If null, uses 1.4em as default size. Pass a string with the font-size and the unit (e.g., "1.2em").
fontWeightNumber400Defines the font-weight for the input
textColorString'#ffffff'Defines the text color for the input
caretColorString''Defines the caret (cursor) color. If empty, uses theme default.
selectionBgColorString''Defines the background color for selected text. If empty, uses theme default.
selectionTextColorString''Defines the text color for selected text. If empty, uses theme default.
hasBorderRadiusBooleanfalseDefines if the input should have border radius
borderRadiusNumber0.5Defines the border radius in rem units. Only applies if hasBorderRadius is true and inputStyle is not 'line'.
inputWidthNumber200Defines the input width in pixels. Only applies when display is not 'b'.
inputStyleString'background'Defines the input style. Accepts background, line, and border.
activeTextStyleString'normal'Defines the text style when input is active. Accepts normal, italic, and oblique.
inputUppercaseBooleanfalseDefines if the input text should be displayed in uppercase
inputAutocompleteString'on'Defines the autocomplete attribute. Accepts on and off.
textAlignString'left'Defines the text alignment. Accepts left, center, and right.
showLabelBooleanfalseDefines if the label should be displayed
labelString'Label text'Defines the label text
labelBackgroundString'transparent'Defines the background color for the label when active (floating)
labelPaddingString'1px 5px'Defines the padding for the label when active (floating)
labelBorderRadiusNumber0Defines the border radius for the label when active (floating)
labelLeftNumber5Defines the left position of the label when inactive (inside input)
labelRightNumber0Defines the right position of the label when inactive (inside input)
inputLabelMarginActiveNumber15Defines the top margin of the input when label is active (floating)
labelActiveTopNumber-13Defines the top position of the label when active (floating)
labelActiveLeftNumber5Defines the left position of the label when active (floating)
labelActiveRightNumber0Defines the right position of the label when active (floating)
labelBreakOnActiveBooleantrueDefines if the label text should break or use ellipsis when active
fontFamilyLabelString"'Lato', sans-serif"Defines the font-family for the label
fontSizeLabelString'1em'Defines the font-size for the label when inactive
fontSizeLabelActiveString'0.8em'Defines the font-size for the label when active (floating)
fontWeightLabelNumber400Defines the font-weight for the label
lightTextColorLabelString'#333333'Defines the text color for the label in light theme
lightTextColorLabelActiveString'#333333'Defines the text color for the label when active in light theme
darkTextColorLabelString'#ffffff'Defines the text color for the label in dark theme
darkTextColorLabelActiveString'#ffffff'Defines the text color for the label when active in dark theme
lightBgColorString'#f8f8f2'Defines the background color for the input in light theme
lightBgColorFocusString'#eaeaea'Defines the background color for the input when focused in light theme
lightDisabledBgColorString'#dfdfd9'Defines the background color for the input when disabled in light theme
lightTextColorString'#000000'Defines the text color for the input in light theme
darkBgColorString'#353734'Defines the background color for the input in dark theme
darkBgColorFocusString'#272936'Defines the background color for the input when focused in dark theme
darkDisabledBgColorString'rgba(40, 42, 54, 1)'Defines the background color for the input when disabled in dark theme
darkTextColorString'#000000'Defines the text color for the input in dark theme
fontFamilyMsgString"'Lato', sans-serif"Defines the font-family for the message
fontSizeMsgString'1em'Defines the font-size for the message
fontWeightMsgNumber400Defines the font-weight for the message
textMessageColorString'#f15574'Defines the text color for the message
showMsgBooleanfalseDefines if the message should be displayed
hasMsgBooleanfalseDefines if there is a message to display
messageString'Default message text'Defines the message text
hasCustomMsgBooleanfalseDefines if the message uses custom styling
extraContendAbsoluteBooleanfalseControls whether the auxiliary message is in normal flow (false, default) or position: absolute under the field (true). The calendar popup (Teleport) is unchanged. In templates: extra-contend-absolute. (Prop name keeps the Contend spelling.)
sizeMediaQueryString'sm'Defines the size media query. Accepts xs, sm, md, and lg. Currently always uses 'sm'.
tabindexString/Number0Defines the tabindex attribute for the input

Calendar Customization Props

All props prefixed with calendar are passed directly to the underlying NbCalendar component. These props allow you to customize the calendar appearance, behavior, and text labels.

Note: All calendar props use the calendar prefix to differentiate them from the DatePicker's own props.

Calendar Font Props

nameValue typeDefaultDescription
calendarFontFamilyString"'Lato', sans-serif"Defines the font-family for the calendar.
calendarFontSizeString'1.6em'Defines the font-size for the calendar.
calendarFontWeightNumber400Defines the font-weight for the calendar.

Calendar Color Props

nameValue typeDefaultDescription
calendarPrimaryColorString'#007bff'Defines the primary color. Accepts Hex format.
calendarSelectionColorString'#1976d2'Defines the background color for selected dates. Accepts Hex format.
calendarEventColorString'#4caf50'Defines the color for event indicators. Accepts Hex format.
calendarTodayColorString'#007bff'Defines the color for today's date. Accepts Hex format.
calendarHoverTextColorStringnullDefines the text color for month/year picker items on hover. If null, uses theme default. Accepts Hex format.
calendarNormalTextColorStringnullDefines the text color for month/year picker items. If null, uses theme default. Accepts Hex format.
calendarMonthYearItemBgStringnullDefines the background color for month/year picker items. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarMonthYearItemBgHoverStringnullDefines the background color for month/year picker items on hover. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarDayHoverBgStringnullDefines the background color for days on hover. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarDayHoverTextColorStringnullDefines the text color for days on hover. If null, uses theme default. Accepts Hex format.
calendarTimeDisplayTextColorStringnullDefines the text color for the time display section. If null, uses theme default. Accepts Hex format.

Calendar Button Props - Time Edit Button

nameValue typeDefaultDescription
calendarTimeEditButtonBgStringnullDefines the background color for the time edit button. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarTimeEditButtonTextColorStringnullDefines the text color for the time edit button. If null, uses theme default. Accepts Hex format.
calendarTimeEditButtonBgHoverStringnullDefines the background color for the time edit button on hover. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarTimeEditButtonTextColorHoverStringnullDefines the text color for the time edit button on hover. If null, uses theme default. Accepts Hex format.
calendarTimeEditButtonFontFamilyString"'Lato', sans-serif"Defines the font-family for the time edit button.
calendarTimeEditButtonFontSizeString'14px'Defines the font-size for the time edit button.
calendarTimeEditButtonPaddingStringnullDefines the padding for the time edit button. If null, uses default.
calendarTimeEditButtonBorderRadiusStringnullDefines the border-radius for the time edit button. If null, uses default.
calendarTimeEditButtonFontWeightNumber500Defines the font-weight for the time edit button.
calendarTimeEditButtonBorderStringnullDefines the border for the time edit button. If null, uses default.
calendarTimeEditButtonTextString'Edit'Defines the text for the time edit button.

Calendar Button Props - Today Button

nameValue typeDefaultDescription
calendarTodayButtonBgStringnullDefines the background color for the "Today" button. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarTodayButtonTextColorStringnullDefines the text color for the "Today" button. If null, uses theme default. Accepts Hex format.
calendarTodayButtonBgHoverStringnullDefines the background color for the "Today" button on hover. If null, uses theme default. Accepts Hex or RGB/RGBA format.
calendarTodayButtonTextColorHoverStringnullDefines the text color for the "Today" button on hover. If null, uses theme default. Accepts Hex format.
calendarTodayButtonFontFamilyString"'Lato', sans-serif"Defines the font-family for the "Today" button.
calendarTodayButtonFontSizeString'1.1rem'Defines the font-size for the "Today" button.
calendarTodayButtonPaddingStringnullDefines the padding for the "Today" button. If null, uses default.
calendarTodayButtonBorderRadiusStringnullDefines the border-radius for the "Today" button. If null, uses default.
calendarTodayButtonFontWeightNumber400Defines the font-weight for the "Today" button.
calendarTodayButtonBorderStringnullDefines the border for the "Today" button. If null, uses default.
calendarTodayButtonTextString'Today'Defines the text for the "Today" button (used in calendar/month view).
calendarNowButtonTextString'Now'Defines the text for the "Now" button (used in time picker view).

Calendar Configuration Props

nameValue typeDefaultDescription
calendarShowClearButtonBooleanfalseDefines if the clear button (×) should be displayed. When clicked, clears the current selection and emits appropriate events.
calendarShowTodayButtonBooleanfalseDefines if the "Today" / "Now" button should be displayed. When clicked, selects the current date/time and navigates to the current month/year.
calendarClearButtonKeepCurrentMonthBooleanfalseDefines if the calendar should stay on the current month/year when clearing selection. If false, navigates to the current system month/year after clearing.
calendarStartWeekOnMondayBooleanfalseDefines if the week should start on Monday instead of Sunday.
calendarEditRangeBooleantrueDefines if the range can be edited by dragging the start or end dates. Only works when allowRange is true.
calendarMaxRangeDaysNumbernullDefines the maximum number of days that can be selected in a range. If null, there is no limit.
calendarMinYearNumber1900Defines the minimum year available in the year picker.
calendarMaxYearNumber2100Defines the maximum year available in the year picker.
calendarGoToDateDate/StringnullNavigates the calendar to a specific date. Accepts Date or String (YYYY-MM-DD).
calendarIsRequiredBooleanfalseDefines if the calendar is required.
calendarWidthFullBooleanfalseDefines if the calendar should occupy 100% of its parent container width.
calendarBorderRadiusNumber0Defines the border radius of the calendar in pixels.
calendarScrollClassString''Defines a custom CSS class for the scrollable content area (useful for custom scrollbar styling).
calendarEventsArrayDefines an array of events to display on the calendar. Each event should have a date property (Date or String) and optionally a color property (Hex format).
calendarIsoStringTimezoneFormatString'Z'Defines the timezone format for isoString in events. Accepts Z (e.g., "2024-01-15T17:30:00.000Z") or +00:00 (e.g., "2024-01-15T17:30:00.000+00:00"). Both represent UTC. This prop affects the isoString field in @date-selected, @changed-complete, and @current-value-complete events.

Calendar Text Customization Props

All text labels and button texts can be customized via props. Defaults are in English.

nameValue typeDefaultDescription
calendarSelectMonthTextString'Select month'Defines the text displayed when selecting a month.
calendarSelectYearTextString'Select year'Defines the text displayed when selecting a year.
calendarSelectTimeTextString'Select time'Defines the text displayed when selecting a time.
calendarTimeDisplayLabelTextString'Time:'Defines the label text for the time display section.
calendarClearButtonTitleString'Clear selection'Defines the title (tooltip) text for the clear button.
calendarClearButtonSymbolString'×'Defines the symbol/text displayed in the clear button.

Note: Month names and weekday names are automatically controlled by the locale prop ('pt-BR' or 'en-US'). They do not need individual props.

Accepted Formats

The inputText prop accepts different value formats depending on the inputType. The component validates and normalizes these values automatically. Invalid formats are cleared (set to empty string).

Understanding "Cleared" Values

When a value is cleared, it means the component detected an invalid format and automatically set the internal value to an empty string (''). This is different from passing an empty value intentionally.

Key differences:

  • Empty values (null, undefined, ''): Accepted as valid empty values, treated as intentional empty state
  • Cleared values: Invalid formats that are automatically converted to empty string

When values are cleared:

  • Invalid date strings (e.g., "2026-13-45" - invalid month/day)
  • Wrong format strings (e.g., passing "hello world" to a date input)
  • Numbers or objects (except Date objects for date type)
  • Invalid ISO strings that cannot be parsed

Example - Testing cleared behavior:

<template>
  <NbDatePicker
    nb-id="datepicker-test"
    input-name="test"
    input-type="date"
    :input-text="invalidValue"
    @changed="onValueChanged"
  />
</template>

<script setup>
import { ref } from 'vue'

// Invalid format - will be cleared
const invalidValue = ref('invalid-date-string')

const onValueChanged = (value) => {
  console.log('Value:', value)
  // If invalidValue was 'invalid-date-string', 
  // value will be '' (cleared)
  // If invalidValue was null or '', 
  // value will be '' (accepted as empty, not cleared)
}
</script>

Example - Comparing empty vs cleared:

<template>
  <div>
    <!-- This will be accepted as empty (not cleared) -->
    <NbDatePicker
      nb-id="datepicker-empty"
      input-name="empty"
      input-type="date"
      :input-text="null"
      @changed="(v) => console.log('Empty:', v)"
    />
    
    <!-- This will be cleared (invalid format) -->
    <NbDatePicker
      nb-id="datepicker-invalid"
      input-name="invalid"
      input-type="date"
      input-text="not-a-date"
      @changed="(v) => console.log('Cleared:', v)"
    />
  </div>
</template>

Practical use case:

If you're binding inputText to a reactive value that might come from an API or user input, invalid formats will be automatically cleared, ensuring the component always has a valid state:

<template>
  <NbDatePicker
    nb-id="datepicker-api"
    input-name="api-date"
    input-type="datetime-local"
    :input-text="apiResponse.date"
    @changed="handleDateChange"
  />
</template>

<script setup>
import { ref } from 'vue'

const apiResponse = ref({
  date: '2026-01-09T21:07:50.624+00:00' // Valid ISO - will be normalized
  // date: 'invalid' // Invalid - will be cleared to ''
  // date: null // Valid empty - will be accepted as ''
})

const handleDateChange = (value) => {
  // value will always be a valid format or empty string
  // Never an invalid format
  if (value) {
    // Process valid date
    console.log('Valid date:', value)
  } else {
    // Handle empty state
    console.log('Empty or cleared')
  }
}
</script>

For inputType="date"

Accepted formats:

  1. Native date format (recommended):
    • Format: YYYY-MM-DD
    • Example: "2026-01-09"
    • Behavior: Used as-is, no conversion
  2. ISO string with timezone:
    • Format: YYYY-MM-DDTHH:mm:ss.SSSZ or YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mmZ
    • Examples:
      • "2026-01-09T00:00:00.000Z"
      • "2026-01-09T21:07:50.624+00:00"
      • "2026-01-09T00:00:00-03:00"
    • Behavior: Converted to local timezone and normalized to YYYY-MM-DD
  3. Date object:
    • Type: Date
    • Example: new Date('2026-01-09')
    • Behavior: Converted to YYYY-MM-DD format using local date values

Accepted as empty (not cleared, treated as valid empty value):

  • Empty strings ("") ->is default value
  • null
  • undefined

Not accepted (will be cleared):

  • Strings not matching the formats above
  • Numbers
  • Objects (except Date)
  • Invalid dates (e.g., "2026-13-45") with day or month greater than 31 or 12

For inputType="datetime-local"

Accepted formats:

  1. Native datetime-local format (recommended):
    • Format: YYYY-MM-DDTHH:mm or YYYY-MM-DDTHH:mm:ss
    • Examples:
      • "2026-01-09T21:07"
      • "2026-01-09T21:07:50"
    • Behavior: Used as-is, no conversion
  2. ISO string with timezone:
    • Format: YYYY-MM-DDTHH:mm(:ss[.SSS])?(Z|+/-HH:mm)
    • Examples:
      • "2026-01-09T21:07:50.624+00:00"
      • "2026-01-09T21:07Z"
      • "2026-01-09T21:07:50-03:00"
    • Behavior: Converted to local timezone and normalized to YYYY-MM-DDTHH:mm or YYYY-MM-DDTHH:mm:ss (preserves seconds if present in original)

Accepted as empty (not cleared, treated as valid empty value):

  • Empty strings ("") ->is default value
  • null
  • undefined

Not accepted (will be cleared):

  • Strings not matching the formats above
  • Numbers
  • Objects (including Date objects)
  • Invalid dates/times

For inputType="time"

Accepted formats:

  1. Native time format:
    • Format: HH:mm or HH:mm:ss
    • Examples: "21:07" or "21:07:50"
    • Behavior: Used as-is

Not accepted (will be cleared):

  • ISO strings with date
  • Date objects
  • Invalid time strings
  • Other formats

For inputType="month"

Accepted formats:

  1. Native month format:
    • Format: YYYY-MM
    • Example: "2026-01"
    • Behavior: Used as-is

Not accepted (will be cleared):

  • Other formats

For inputType="week"

Accepted formats:

  1. ISO week format:
    • Format: YYYY-Www
    • Example: "2026-W03"
    • Behavior: Used as-is

Not accepted (will be cleared):

  • Other formats

For Range Mode (allowRange="true")

Accepted formats:

  1. JSON string with ISO dates:
    • Format: {"startDate":"YYYY-MM-DD","endDate":"YYYY-MM-DD"}
    • Example: '{"startDate":"2026-01-01","endDate":"2026-01-31"}'
    • Behavior: Parsed and converted to Date objects

Not accepted (will be cleared):

  • Invalid JSON
  • Missing startDate or endDate properties
  • Invalid date formats within JSON

Working with Timezones

By default, when you pass ISO strings with timezone information (e.g., "2026-01-09T21:07:50.624+00:00"), the component automatically converts them to the local timezone of the user's browser. This ensures that dates and times are displayed correctly for the user's location.

However, if you need to work with specific timezones or preserve the original timezone without conversion, you can use timezone libraries. Here are some common approaches:

Understanding Default Behavior

What happens by default:

  • ISO strings with timezone are converted to local timezone
  • Example: "2026-01-09T21:07:50.624+00:00" (UTC) → converted to user's local time
  • The component always stores values in datetime-local format (no timezone info)

When you might need timezone libraries:

  • Displaying dates in a specific timezone (not user's local)
  • Preserving original timezone information
  • Converting between different timezones
  • Working with UTC explicitly

Using date-fns-tz

date-fns-tz is a timezone extension for date-fns.

Installation:

npm install date-fns date-fns-tz
# or
yarn add date-fns date-fns-tz

Example - Converting to specific timezone before passing to component:

<template>
  <NbDatePicker
    nb-id="datepicker-timezone"
    input-name="datetime"
    input-type="datetime-local"
    :input-text="localDateTime"
    @changed="handleDateTimeChange"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import { format, parseISO } from 'date-fns'
import { zonedTimeToUtc, utcToZonedTime, format as formatTz } from 'date-fns-tz'

// Example: You have a UTC datetime from API
const utcDateTime = ref('2026-01-09T21:07:50.624Z')

// Convert UTC to a specific timezone (e.g., 'America/Sao_Paulo')
const timezone = 'America/Sao_Paulo'
const zonedDate = computed(() => {
  if (!utcDateTime.value) return null
  return utcToZonedTime(parseISO(utcDateTime.value), timezone)
})

// Format for datetime-local (no timezone info)
const localDateTime = computed(() => {
  if (!zonedDate.value) return null
  return format(zonedDate.value, "yyyy-MM-dd'T'HH:mm:ss")
})

const handleDateTimeChange = (value) => {
  // value is in datetime-local format (user's local timezone)
  // If you need to convert back to UTC or specific timezone:
  if (value) {
    const date = parseISO(value)
    const utcDate = zonedTimeToUtc(date, timezone)
    console.log('UTC:', utcDate.toISOString())
  }
}
</script>

Example - Displaying in specific timezone:

<template>
  <div>
    <NbDatePicker
      nb-id="datepicker-utc"
      input-name="datetime"
      input-type="datetime-local"
      :input-text="localValue"
      @changed="handleChange"
    />
    <p>Display in UTC: {{ displayInUTC }}</p>
    <p>Display in São Paulo: {{ displayInSP }}</p>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { parseISO } from 'date-fns'
import { format as formatTz, utcToZonedTime } from 'date-fns-tz'

const localValue = ref('2026-01-09T21:07:50')

const displayInUTC = computed(() => {
  if (!localValue.value) return ''
  const date = parseISO(localValue.value)
  return formatTz(date, 'yyyy-MM-dd HH:mm:ss', { timeZone: 'UTC' })
})

const displayInSP = computed(() => {
  if (!localValue.value) return ''
  const date = parseISO(localValue.value)
  return formatTz(date, 'yyyy-MM-dd HH:mm:ss', { timeZone: 'America/Sao_Paulo' })
})

const handleChange = (value) => {
  localValue.value = value
}
</script>

Using dayjs with timezone plugin

dayjs with timezone plugin is a lightweight alternative.

Installation:

npm install dayjs
npm install dayjs/plugin/timezone
npm install dayjs/plugin/utc
# or
yarn add dayjs
yarn add dayjs/plugin/timezone
yarn add dayjs/plugin/utc

Example:

<template>
  <NbDatePicker
    nb-id="datepicker-dayjs"
    input-name="datetime"
    input-type="datetime-local"
    :input-text="localDateTime"
    @changed="handleChange"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'

dayjs.extend(utc)
dayjs.extend(timezone)

// Example: UTC datetime from API
const utcDateTime = ref('2026-01-09T21:07:50.624Z')

// Convert to specific timezone and format for datetime-local
const localDateTime = computed(() => {
  if (!utcDateTime.value) return null
  return dayjs(utcDateTime.value)
    .tz('America/Sao_Paulo')
    .format('YYYY-MM-DDTHH:mm:ss')
})

const handleChange = (value) => {
  if (value) {
    // Convert back to UTC
    const utcValue = dayjs(value).tz('America/Sao_Paulo').utc().toISOString()
    console.log('UTC:', utcValue)
  }
}
</script>

Using moment-timezone

moment-timezone is a popular timezone library (though moment.js is in maintenance mode).

Installation:

npm install moment-timezone
# or
yarn add moment-timezone

Example:

<template>
  <NbDatePicker
    nb-id="datepicker-moment"
    input-name="datetime"
    input-type="datetime-local"
    :input-text="localDateTime"
    @changed="handleChange"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import moment from 'moment-timezone'

// Example: UTC datetime from API
const utcDateTime = ref('2026-01-09T21:07:50.624Z')

// Convert to specific timezone and format for datetime-local
const localDateTime = computed(() => {
  if (!utcDateTime.value) return null
  return moment(utcDateTime.value)
    .tz('America/Sao_Paulo')
    .format('YYYY-MM-DDTHH:mm:ss')
})

const handleChange = (value) => {
  if (value) {
    // Convert back to UTC
    const utcValue = moment(value)
      .tz('America/Sao_Paulo')
      .utc()
      .toISOString()
    console.log('UTC:', utcValue)
  }
}
</script>

Best Practices

  1. Store UTC in your backend/database: Always store dates/times in UTC format
  2. Convert to local timezone for display: Convert UTC to user's timezone or specific timezone when displaying
  3. Use datetime-local format for input: The component expects datetime-local format (no timezone), so convert before passing
  4. Convert back to UTC on save: When user selects a date/time, convert it back to UTC before sending to backend

Complete example workflow:

<template>
  <NbDatePicker
    nb-id="datepicker-workflow"
    input-name="datetime"
    input-type="datetime-local"
    :input-text="displayDateTime"
    @changed="handleDateTimeChange"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import { format, parseISO } from 'date-fns'
import { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz'

// 1. UTC datetime from API/backend
const apiDateTime = ref('2026-01-09T21:07:50.624Z')
const userTimezone = 'America/Sao_Paulo'

// 2. Convert UTC to user's timezone for display
const displayDateTime = computed(() => {
  if (!apiDateTime.value) return null
  const utcDate = parseISO(apiDateTime.value)
  const zonedDate = utcToZonedTime(utcDate, userTimezone)
  return format(zonedDate, "yyyy-MM-dd'T'HH:mm:ss")
})

// 3. Handle user selection and convert back to UTC
const handleDateTimeChange = async (value) => {
  if (value) {
    // Parse the datetime-local value (assumed to be in user's timezone)
    const localDate = parseISO(value)
    
    // Convert back to UTC
    const utcDate = zonedTimeToUtc(localDate, userTimezone)
    
    // Send to backend
    const utcISOString = utcDate.toISOString()
    console.log('Sending to backend:', utcISOString)
    
    // await saveToBackend(utcISOString)
  }
}
</script>

Events

changed

Fired when the input value changes, returns the current value in different formats depending on the inputType:

For inputType="date":

  • Returns: String (format: YYYY-MM-DD)
  • Example: "2024-01-15"

For inputType="month":

  • Returns: String (format: YYYY-MM)
  • Example: "2024-01"

For inputType="time":

  • Returns: String (format: HH:mm or HH:mm:ss)
  • Example: "14:30" or "14:30:45"

For inputType="datetime-local":

  • Returns: String (format: YYYY-MM-DDTHH:mm or YYYY-MM-DDTHH:mm:ss)
  • Example: "2024-01-15T14:30" or "2024-01-15T14:30:45"

For inputType="week":

  • Returns: String (format: YYYY-Www - ISO 8601 week format)
  • Example: "2024-W03"

For range mode (allowRange="true"):

  • Returns: Object with startDate and endDate properties (Date objects)
  • Example: { startDate: Date, endDate: Date } or { startDate: null, endDate: null } when cleared

When input is cleared:

  • Returns: '' (empty string) for single date or { startDate: null, endDate: null } for range mode

Detailed Return Formats

The changed event returns values in different formats based on the inputType. Here are the detailed return formats:

Single Date Selection (inputType="date")

Returns: String in format YYYY-MM-DD

Example:

"2024-01-15"

When selection is cleared:

""

Date Range Selection (allowRange="true")

Returns: Object with startDate and endDate properties

{
  startDate: Date,               // Start date of the range (or null)
  endDate: Date                  // End date of the range (or null)
}

Example:

{
  startDate: new Date('2024-01-15'),
  endDate: new Date('2024-01-20')
}

When range is cleared:

{
  startDate: null,
  endDate: null
}

When only start date is selected (partial range):

{
  startDate: new Date('2024-01-15'),
  endDate: null
}

Week Selection (inputType="week")

Returns: String in ISO 8601 week format YYYY-Www

Example:

"2024-W03"  // Week 3 of year 2024

When selection is cleared:

""

Month Selection (inputType="month")

Returns: String in format YYYY-MM

Example:

"2024-01"  // January 2024

When selection is cleared:

""

Time Selection (inputType="time")

Returns: String in format HH:mm or HH:mm:ss

Example:

"14:30"        // 2:30 PM
"14:30:45"     // 2:30:45 PM (if seconds are included)

When selection is cleared:

""

DateTime Selection (inputType="datetime-local")

Returns: String in format YYYY-MM-DDTHH:mm or YYYY-MM-DDTHH:mm:ss

Example:

"2024-01-15T14:30"        // January 15, 2024 at 2:30 PM
"2024-01-15T14:30:45"     // January 15, 2024 at 2:30:45 PM (if seconds are included)

When selection is cleared:

""

current-value

Fired whenever the input value changes (same as changed but with a different name for compatibility). Returns the same format as changed.


changed-complete

Fired when a date is selected via the calendar component. Returns the complete data structure from NbCalendar's @date-selected event, including detailed information about the selection.

Returns: Complete data object from NbCalendar (same format as NbCalendar's @date-selected event)

Format varies by inputType:

Single Date Selection (inputType="date")

When a date is selected:

{
  date: Date,                    // Date object of the selected date
  dateString: String,            // Date in YYYY-MM-DD format (e.g., "2024-01-15")
  isoString: String,             // ISO 8601 string with timezone in UTC. Format depends on `calendarIsoStringTimezoneFormat` prop:
                                 //   - If `calendarIsoStringTimezoneFormat="Z"`: "2024-01-15T00:00:00.000Z"
                                 //   - If `calendarIsoStringTimezoneFormat="+00:00"`: "2024-01-15T00:00:00.000+00:00"
  isoStringLocal: String,        // ISO 8601 string without timezone (e.g., "2024-01-15T00:00:00")
  day: {                         // Day object with additional information
    date: Number,                // Day of month (1-31)
    fullDate: Date,              // Full date object
    isOtherMonth: Boolean,       // Whether the day belongs to another month
    isToday: Boolean,            // Whether the day is today
    isSelected: Boolean,        // Whether the day is selected
    isInRange: Boolean,         // Whether the day is in a range (if range mode)
    isRangeStart: Boolean,      // Whether the day is the start of a range
    isRangeEnd: Boolean,        // Whether the day is the end of a range
    isDisabled: Boolean,         // Whether the day is disabled
    events: Array                // Array of events for this day
  }
}

When selection is cleared:

{
  date: null,                    // null when cleared
  dateString: null,              // null when cleared
  isoString: null,               // null when cleared
  isoStringLocal: null,          // null when cleared
  day: null                      // null when cleared
}

Date Range Selection (allowRange="true")

When a range is selected:

{
  startDate: Date,               // Start date of the range
  endDate: Date,                 // End date of the range
  isRange: true,                 // Indicates this is a range selection
  isoString: {                   // ISO strings for start and end dates
    start: String,               // ISO string for start date (format depends on `calendarIsoStringTimezoneFormat`)
    end: String                  // ISO string for end date (format depends on `calendarIsoStringTimezoneFormat`)
  },
  isoStringLocal: {              // Local ISO strings without timezone
    start: String,               // Local ISO string for start date
    end: String                  // Local ISO string for end date
  }
}

When range is cleared:

{
  startDate: null,
  endDate: null,
  isRange: true,
  isoString: null,
  isoStringLocal: null
}

Time Selection (inputType="time")

{
  hour: Number,                  // Selected hour (0-23)
  minute: Number,                // Selected minute (0-59)
  second: Number,                // Selected second (0-59, only if hasSeconds is true)
  timeString: String             // Time in HH:mm or HH:mm:ss format (e.g., "14:30" or "14:30:45")
}

DateTime Selection (inputType="datetime-local")

When date/time is selected:

{
  date: Date,                    // Date object of the selected date
  hour: Number,                  // Selected hour (0-23)
  minute: Number,                // Selected minute (0-59)
  second: Number,                // Selected second (0-59, only if hasSeconds is true)
  datetimeString: String,       // Combined date and time in YYYY-MM-DDTHH:mm format (e.g., "2024-01-15T14:30")
  isoString: String,             // ISO 8601 string with timezone in UTC. Format depends on `calendarIsoStringTimezoneFormat` prop:
                                 //   - If `calendarIsoStringTimezoneFormat="Z"`: "2024-01-15T17:30:00.000Z"
                                 //   - If `calendarIsoStringTimezoneFormat="+00:00"`: "2024-01-15T17:30:00.000+00:00"
  isoStringLocal: String,        // Local ISO 8601 string without timezone (e.g., "2024-01-15T14:30:00")
  day: {                         // Day object (same structure as single date selection)
    date: Number,
    fullDate: Date,
    isOtherMonth: Boolean,
    isToday: Boolean,
    isSelected: Boolean,
    isInRange: Boolean,
    isRangeStart: Boolean,
    isRangeEnd: Boolean,
    isDisabled: Boolean,
    events: Array
  }
}

When selection is cleared:

{
  date: null,
  hour: 0,
  minute: 0,
  second: 0,
  datetimeString: null,
  isoString: null,
  isoStringLocal: null,
  day: null
}

Week Selection (inputType="week")

{
  date: Date,                    // Date object of the first day of the selected week
  dateString: String,            // Date in YYYY-MM-DD format of the first day
  isoString: String,             // ISO 8601 string with timezone (format depends on `calendarIsoStringTimezoneFormat`)
  isoStringLocal: String         // Local ISO 8601 string of first day of week
}

Month Selection (inputType="month")

{
  date: Date,                     // Date object of the first day of the selected month
  dateString: String,             // Date in YYYY-MM-DD format of the first day
  isoString: String,              // ISO 8601 string with timezone (format depends on `calendarIsoStringTimezoneFormat`)
  isoStringLocal: String          // Local ISO 8601 string of first day of month
}

Example:

@changed-complete="handleChangedComplete"

const handleChangedComplete = (data) => {
  console.log('Complete data:', data)
  // For date: { date: Date, dateString: "2024-01-15", isoString: "2024-01-15T00:00:00.000Z", ... }
  // For datetime-local: { date: Date, hour: 14, minute: 30, isoString: "2024-01-15T17:30:00.000Z", ... }
  // For range: { startDate: Date, endDate: Date, isoString: { start: "...", end: "..." }, ... }
}

Note: This event fires when:

  • A date is clicked/selected in the calendar
  • The "Today/Now" button is clicked
  • The "Clear" button is clicked (returns null values)
  • Time values are changed (hour/minute/second)
  • A month or week is selected
  • A date range is selected or cleared
  • The inputText prop is set programmatically (e.g., when loading data from database)

It does NOT fire when:

  • The user types directly in the input field
  • The value changes via native browser input controls

current-value-complete

Fired when a date is selected via the calendar component (same as changed-complete but with a different name for compatibility). Returns the complete data structure from NbCalendar's @date-selected event.

Returns: Same format as changed-complete (complete data object from NbCalendar)


focused

Fired when the input receives focus.

Returns: No return value

Example:

@focused="onInputFocused"

const onInputFocused = () => {
  console.log('Input focused')
}

blurred

Fired when the input loses focus.

Returns: No return value

Example:

@blurred="onInputBlurred"

const onInputBlurred = () => {
  console.log('Input blurred')
}

clicked

Fired when the input or its container is clicked. Receives the native DOM event as first argument.

Returns: No return value

Example:

@clicked="onInputClicked"

const onInputClicked = () => {
  console.log('Input clicked')
}

entered

Fired when the user presses Enter while the input is focused. Only fires if hasTabIndexEnter is true and the input is not disabled or readonly.

Returns: The current input value (same format as changed)

Example:

@entered="onEnterPressed"

const onEnterPressed = (value) => {
  console.log('Enter pressed with value:', value)
}

paste

Fired when content is pasted into the input. Always fired, even when blockPaste is true (in which case the paste action is blocked but the event is still emitted).

Returns: String - The pasted value from the clipboard

Example:

@paste="onPaste"

const onPaste = (value) => {
  console.log('Pasted value:', value)
}

valid

Fired to indicate whether the current value is valid according to format validation and min/max constraints. This event is emitted:

  • When the component is mounted with an initial value
  • When the inputText prop changes
  • When the value changes (via user interaction or programmatically)
  • When min or max props change
  • When the calendar component emits a validation event

Returns: Boolean - true if the value is valid, false if invalid

Validation Rules:

  1. Format Validation:
    • The value must match the expected format for the inputType:
      • date: YYYY-MM-DD
      • time: HH:mm or HH:mm:ss
      • datetime-local: YYYY-MM-DDTHH:mm or YYYY-MM-DDTHH:mm:ss
      • month: YYYY-MM
      • week: YYYY-Www
    • Invalid formats return false
  2. Empty Values:
    • If required is true: Empty values ('', null, undefined) return false (invalid)
    • If required is false: Empty values return true (valid, as the field is optional)
  3. Range Validation (min/max):
    • If min is set, values before the minimum return false
    • If max is set, values after the maximum return false
    • Both format and range must be valid for the value to be considered valid

Example:

<template>
  <NbDatePicker
    nb-id="datepicker-validation"
    input-name="validation-test"
    input-type="date"
    :input-text="dateValue"
    :min="'2024-01-01'"
    :max="'2024-12-31'"
    :required="true"
    @valid="handleValidation"
  />
  <p>Is Valid: {{ isValid ? 'Yes' : 'No' }}</p>
</template>

<script setup>
import { ref } from 'vue'

const dateValue = ref('2024-06-15')
const isValid = ref(true)

const handleValidation = (valid) => {
  isValid.value = valid
  console.log('Value is valid:', valid)
  
  if (!valid) {
    console.log('Current value is invalid. Check format and min/max constraints.')
  }
}
</script>

Example - Required Field:

<template>
  <NbDatePicker
    nb-id="datepicker-required"
    input-name="required-date"
    input-type="date"
    :input-text="dateValue"
    :required="true"
    @valid="handleValidation"
  />
</template>

<script setup>
import { ref } from 'vue'

const dateValue = ref('') // Empty value

const handleValidation = (valid) => {
  // When required=true and value is empty, valid will be false
  console.log('Is valid:', valid) // false
}
</script>

Example - Optional Field:

<template>
  <NbDatePicker
    nb-id="datepicker-optional"
    input-name="optional-date"
    input-type="date"
    :input-text="dateValue"
    :required="false"
    @valid="handleValidation"
  />
</template>

<script setup>
import { ref } from 'vue'

const dateValue = ref('') // Empty value

const handleValidation = (valid) => {
  // When required=false and value is empty, valid will be true (optional field)
  console.log('Is valid:', valid) // true
}
</script>

Example - Real-time Validation:

<template>
  <div>
    <NbDatePicker
      nb-id="datepicker-realtime"
      input-name="realtime-date"
      input-type="datetime-local"
      :input-text="dateTimeValue"
      :min="'2024-01-01T00:00'"
      :max="'2024-12-31T23:59'"
      @valid="handleValidation"
    />
    <div v-if="!isValid" style="color: red;">
      Invalid date/time. Please select a value between {{ min }} and {{ max }}.
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const dateTimeValue = ref('2024-06-15T12:00')
const isValid = ref(true)
const min = ref('2024-01-01T00:00')
const max = ref('2024-12-31T23:59')

const handleValidation = (valid) => {
  isValid.value = valid
}
</script>

date-selected

Fired when a date is selected via the calendar component. This event is repassed from the underlying NbCalendar component's @date-selected event.

Returns: Complete data object from NbCalendar (same format as changed-complete and current-value-complete)

Note: This event provides the same data as changed-complete and current-value-complete, but with a different name for semantic clarity. Use this event when you specifically want to handle date selection events separately from other change events.

Format varies by inputType: Same format as changed-complete (see changed-complete section for detailed formats)

Example:

<template>
  <NbDatePicker
    nb-id="datepicker-selection"
    input-name="date"
    input-type="date"
    @date-selected="handleDateSelected"
  />
</template>

<script setup>
const handleDateSelected = (data) => {
  console.log('Date selected:', data)
  // For date: { date: Date, dateString: "2024-01-15", isoString: "2024-01-15T00:00:00.000Z", ... }
  // For datetime-local: { date: Date, hour: 14, minute: 30, isoString: "2024-01-15T17:30:00.000Z", ... }
}
</script>

month-changed

Fired when the calendar month/year is changed through navigation (e.g., clicking previous/next month buttons, selecting a month from the month picker, or selecting a year from the year picker). This event is repassed from the underlying NbCalendar component's @month-changed event.

Returns: Object with the following structure:

{
  year: Number,           // The year (e.g., 2024)
  month: Number,          // The month index (0-11, where 0 = January, 11 = December)
  monthName: String       // The localized month name (e.g., "January" or "Janeiro" depending on locale)
}

Example:

<template>
  <NbDatePicker
    nb-id="datepicker-month-nav"
    input-name="date"
    input-type="date"
    @month-changed="handleMonthChanged"
  />
</template>

<script setup>
const handleMonthChanged = (data) => {
  console.log('Month changed:', data)
  // Example output: { year: 2024, month: 0, monthName: "January" }
  // or: { year: 2024, month: 0, monthName: "Janeiro" } (if locale="pt-BR")
}
</script>

When this event fires:

  • User clicks the previous month button (◀)
  • User clicks the next month button (▶)
  • User selects a month from the month picker
  • User selects a year from the year picker
  • Programmatic navigation via calendarGoToDate prop

When this event does NOT fire:

  • User selects a date (use @date-selected or @changed-complete instead)
  • User changes time values (hour/minute/second)
  • User clears the selection

Slots

message

Custom slot for the message area. Allows custom HTML/content to be displayed as the message.

Example:

<nb-date-picker nb-id="datepicker-1" input-name="date">
  <template #message>
    <span>Custom error message</span>
  </template>
</nb-date-picker>

Examples

Basic Date Selection

<template>
  <NbDatePicker
    nb-id="datepicker-basic"
    input-name="date"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

Date Range Selection

<template>
  <NbDatePicker
    nb-id="datepicker-range"
    input-name="date-range"
    :allow-range="true"
    :use-custom-calendar="true"
    @changed="onRangeChanged"
  />
</template>

<script setup>
const onRangeChanged = (value) => {
  console.log('Selected range:', value)
  // value will be: { startDate: Date, endDate: Date }
}
</script>

Week Selection

<template>
  <NbDatePicker
    nb-id="datepicker-week"
    input-name="week"
    input-type="week"
    @changed="onWeekChanged"
  />
</template>

<script setup>
const onWeekChanged = (value) => {
  console.log('Selected week:', value) // Format: YYYY-Www
}
</script>

Month Selection

<template>
  <NbDatePicker
    nb-id="datepicker-month"
    input-name="month"
    input-type="month"
    @changed="onMonthChanged"
  />
</template>

<script setup>
const onMonthChanged = (value) => {
  console.log('Selected month:', value) // Format: YYYY-MM
}
</script>

Time Selection

<template>
  <NbDatePicker
    nb-id="datepicker-time"
    input-name="time"
    input-type="time"
    @changed="onTimeChanged"
  />
</template>

<script setup>
const onTimeChanged = (value) => {
  console.log('Selected time:', value) // Format: HH:mm or HH:mm:ss
}
</script>

DateTime Selection

<template>
  <NbDatePicker
    nb-id="datepicker-datetime"
    input-name="datetime"
    input-type="datetime-local"
    @changed="onDateTimeChanged"
  />
</template>

<script setup>
const onDateTimeChanged = (value) => {
  console.log('Selected datetime:', value) // Format: YYYY-MM-DDTHH:mm
}
</script>

DatePicker with Label

<template>
  <NbDatePicker
    nb-id="datepicker-label"
    input-name="date"
    :show-label="true"
    label="Select a date"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

Dark Theme DatePicker

<template>
  <NbDatePicker
    nb-id="datepicker-dark"
    input-name="date"
    theme="dark"
    :input-width="300"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

DatePicker with Min/Max Dates

<template>
  <NbDatePicker
    nb-id="datepicker-limited"
    input-name="date"
    min="2024-01-01"
    max="2024-12-31"
    :step="7"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

DatePicker with Custom Calendar Disabled

<template>
  <NbDatePicker
    nb-id="datepicker-native"
    input-name="date"
    :use-custom-calendar="false"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

DatePicker with Custom Styling

<template>
  <NbDatePicker
    nb-id="datepicker-custom"
    input-name="date"
    :has-border-radius="true"
    :border-radius="0.8"
    input-style="border"
    :input-width="250"
    text-align="center"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

DatePicker with Message

<template>
  <NbDatePicker
    nb-id="datepicker-message"
    input-name="date"
    :show-msg="true"
    :has-msg="true"
    message="Please select a valid date"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>

DatePicker with Custom Locale

<template>
  <NbDatePicker
    nb-id="datepicker-locale"
    input-name="date"
    locale="en-US"
    @changed="onDateChanged"
  />
</template>

<script setup>
const onDateChanged = (value) => {
  console.log('Selected date:', value)
}
</script>