# Date Picker

Date Pickers allow users to select a Date and Time from a pop up Calendar.

## Example

```python
from deephaven import ui

dp = ui.date_picker(
    label="Date Picker",
    default_value="2024-01-02T10:30:00 UTC",
    on_change=print,
)
```

## Date types

The date picker accepts the following date types as inputs:<br />
\\\\
`None`, `LocalDate`, `ZoneDateTime`, `Instant`, `int`, `str`, `datetime.datetime`, `numpy.datetime64`, `pandas.Timestamp`

The input will be converted to one of three Java date types:

1. `LocalDate`: A LocalDate is a date without a time zone in the ISO-8601 system, such as “2007-12-03” or “2057-01-28”.
   This will create a date picker with a granularity of days.
2. `Instant`: An Instant represents an unambiguous specific point on the timeline, such as 2021-04-12T14:13:07 UTC.
   This will create a date picker with a granularity of seconds in UTC. The time zone will be rendered as the time zone in user settings.
3. `ZonedDateTime`: A ZonedDateTime represents an unambiguous specific point on the timeline with an associated time zone, such as 2021-04-12T14:13:07 America/New_York.
   This will create a date picker with a granularity of seconds in the specified time zone. The time zone will be rendered as the specified time zone.

The input is coverted according to the following rules:

1. If the input is one of the three Java date types, use that type.
2. A date string such as “2007-12-03” will parse to a `LocalDate`
3. A string with a date, time, and timezone such as “2021-04-12T14:13:07 America/New_York” will parse to a `ZonedDateTime`
4. All other types will attempt to convert in this order: `Instant`, `ZonedDateTime`, `LocalDate`

The format of the date picker and the type of the value passed to the `on_change` handler
is determined by the type of the following props in order of precedence:

1. `value`
2. `default_value`
3. `placeholder_value`

If none of these are provided, the `on_change` handler will be passed an `Instant`.

## Controlled mode with value

Setting the `value` prop will put the date_picker in controlled mode. Selecting a new date will call the `on_change` callback.
Then `value` must be updated programatically to render the new value. This can be done using the `use_state` hook.

```python
from deephaven import ui
from deephaven.time import to_j_local_date, dh_today, to_j_instant, to_j_zdt

zoned_date_time = to_j_zdt("1995-03-22T11:11:11.23142 America/New_York")
instant = to_j_instant("2022-01-01T00:00:00 ET")
local_date = to_j_local_date(dh_today())


@ui.component
def date_picker_test(value):
    date, set_date = ui.use_state(value)
    return [ui.date_picker(on_change=set_date, value=date), ui.text(str(date))]


zoned_date_picker = date_picker_test(zoned_date_time)
instant_date_picker = date_picker_test(instant)
local_date_picker = date_picker_test(local_date)
```

## Uncontrolled mode with default_value

If the `value` prop is omitted, the date_picker will be in uncontrolled mode. It will store its state internally and automatically update when a new date is selected.
In this mode, setting the `default_value` prop will determine the initial value displayed by the date_picker.

```python
from deephaven.time import dh_now
from deephaven import ui

dp = ui.date_picker(
    label="Date Picker",
    default_value=dh_now(),
    on_change=print,
)
```

## Uncontrolled mode with placeholder_value

If both `value` and `default_value` are omitted, the date_picker will be in uncontrolled mode displaying no date selected. When opened, the date picker will suggest the date from the `placeholder_value` prop.
Omitting `placeholder_value` will default it to today at the current time on the server machine time zone.

```python
from deephaven import ui

dp1 = ui.date_picker(
    label="Date Picker",
    placeholder_value="2022-10-01T08:30:00 ET",
    on_change=print,
)

dp2 = ui.date_picker(
    label="Date Picker",
    on_change=print,
)
```

## Events

Date Pickers accept a value to display and can trigger actions based on events such as setting state when changed. See the [API Reference]() for a full list of available events.

## Variants

Date Pickers can have different variants to indicate their purpose.

```python
from deephaven import ui


@ui.component
def date_picker_variants():
    return [
        ui.date_picker(description="description"),
        ui.date_picker(error_message="error", validation_state="valid"),
        ui.date_picker(error_message="error", validation_state="invalid"),
        ui.date_picker(min_value="2024-01-01", max_value="2024-01-05"),
        ui.date_picker(value="2024-07-27T16:10:10 America/New_York", hour_cycle=24),
        ui.date_picker(granularity="YEAR"),
        ui.date_picker(granularity="MONTH"),
        ui.date_picker(granularity="DAY"),
        ui.date_picker(granularity="HOUR"),
        ui.date_picker(granularity="MINUTE"),
        ui.date_picker(granularity="SECOND"),
    ]


date_picker_variants_example = date_picker_variants()
```

## Time table filtering

Date Pickers can be used to filter tables with time columns.

```python
from deephaven.time import dh_now
from deephaven import time_table, ui


@ui.component
def date_table_filter(table, start_date, end_date, time_col="Timestamp"):
    after_date, set_after_date = ui.use_state(start_date)
    before_date, set_before_date = ui.use_state(end_date)
    return [
        ui.date_picker(label="Start Date", value=after_date, on_change=set_after_date),
        ui.date_picker(label="End Date", value=before_date, on_change=set_before_date),
        table.where(f"{time_col} >= after_date  && {time_col} < before_date"),
    ]


SECONDS_IN_DAY = 86400
today = dh_now()
_table = time_table("PT1s").update_view(
    ["Timestamp=today.plusSeconds(SECONDS_IN_DAY*i)", "Row=i"]
)
date_filter = date_table_filter(_table, today, today.plusSeconds(SECONDS_IN_DAY * 10))
```

## API Reference

A date picker allows the user to select a date.

**Returns:** `Element` The date picker element.

<ParamTable param={{"module_name": "deephaven.ui.", "name": "date_picker", "parameters": [{"name": "placeholder_value", "type": "DType | None | str | date | datetime | datetime64 | Timestamp | int", "description": "A placeholder date that influences the format of the placeholder shown when no value is selected. Defaults to today at midnight in the user's timezone."}, {"name": "value", "type": "DType | None | str | date | datetime | datetime64 | Timestamp | int", "description": "The current value (controlled).", "default": "None"}, {"name": "default_value", "type": "DType | None | str | date | datetime | datetime64 | Timestamp | int", "description": "The default value (uncontrolled).", "default": "None"}, {"name": "min_value", "type": "DType | None | str | date | datetime | datetime64 | Timestamp | int", "description": "The minimum allowed date that a user may select.", "default": "None"}, {"name": "max_value", "type": "DType | None | str | date | datetime | datetime64 | Timestamp | int", "description": "The maximum allowed date that a user may select.", "default": "None"}, {"name": "granularity", "type": "Literal['DAY', 'HOUR', 'MINUTE', 'SECOND'] | None", "description": "Determines the smallest unit that is displayed in the date picker. By default, this is \"DAY\" for LocalDate, and \"SECOND\" otherwise.", "default": "None"}, {"name": "page_behavior", "type": "Literal['single', 'visible'] | None", "description": "Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration.", "default": "None"}, {"name": "hour_cycle", "type": "Literal[12, 24] | None", "description": "Whether to display the time in 12 or 24 hour format. By default, this is determined by the user's locale.", "default": "None"}, {"name": "hide_time_zone", "type": "bool", "description": "Whether to hide the time zone abbreviation.", "default": "False"}, {"name": "should_force_leading_zeros", "type": "bool | None", "description": "Whether to always show leading zeros in the month, day, and hour fields. By default, this is determined by the user's locale.", "default": "None"}, {"name": "is_disabled", "type": "bool | None", "description": "Whether the input is disabled.", "default": "None"}, {"name": "is_read_only", "type": "bool | None", "description": "Whether the input can be selected but not changed by the user.", "default": "None"}, {"name": "is_required", "type": "bool | None", "description": "Whether user input is required on the input before form submission.", "default": "None"}, {"name": "validation_behavior", "type": "Literal['aria', 'native'] | None", "description": "Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA.", "default": "None"}, {"name": "auto_focus", "type": "bool | None", "description": "Whether the element should receive focus on render.", "default": "None"}, {"name": "label", "type": "Element | None", "description": "The content to display as the label.", "default": "None"}, {"name": "description", "type": "Element | None", "description": "A description for the field. Provides a hint such as specific requirements for what to choose.", "default": "None"}, {"name": "error_message", "type": "Element | None", "description": "An error message for the field.", "default": "None"}, {"name": "is_open", "type": "bool | None", "description": "Whether the overlay is open by default (controlled).", "default": "None"}, {"name": "default_open", "type": "bool | None", "description": "Whether the overlay is open by default (uncontrolled).", "default": "None"}, {"name": "name", "type": "str | None", "description": "The name of the input element, used when submitting an HTML form.", "default": "None"}, {"name": "max_visible_months", "type": "int | None", "description": "The maximum number of months to display at once in the calendar popover, if screen space permits.", "default": "None"}, {"name": "should_flip", "type": "bool | None", "description": "Whether the calendar popover should automatically flip direction when space is limited.", "default": "None"}, {"name": "is_quiet", "type": "bool | None", "description": "Whether the date picker should be displayed with a quiet style.", "default": "None"}, {"name": "show_format_help_text", "type": "bool | None", "description": "Whether to show the localized date format as help text below the field.", "default": "None"}, {"name": "label_position", "type": "Literal['top', 'side'] | None", "description": "The label's overall position relative to the element it is labeling.", "default": "None"}, {"name": "label_align", "type": "Literal['start', 'end'] | None", "description": "The label's horizontal alignment relative to the element it is labeling.", "default": "None"}, {"name": "necessity_indicator", "type": "Literal['icon', 'label'] | None", "description": "Whether the required state should be shown as an icon or text.", "default": "None"}, {"name": "contextual_help", "type": "Element | None", "description": "A ContextualHelp element to place next to the label.", "default": "None"}, {"name": "validation_state", "type": "Literal['valid', 'invalid'] | None", "description": "Whether the input should display its \"valid\" or \"invalid\" visual styling.", "default": "None"}, {"name": "on_focus", "type": "Callable[[FocusEvent], None] | None", "description": "Function called when the button receives focus.", "default": "None"}, {"name": "on_blur", "type": "Callable[[FocusEvent], None] | None", "description": "Function called when the button loses focus.", "default": "None"}, {"name": "on_focus_change", "type": "Callable[[bool], None] | None", "description": "Function called when the focus state changes.", "default": "None"}, {"name": "on_key_down", "type": "Callable[[KeyboardEvent], None] | None", "description": "Function called when a key is pressed.", "default": "None"}, {"name": "on_key_up", "type": "Callable[[KeyboardEvent], None] | None", "description": "Function called when a key is released.", "default": "None"}, {"name": "on_open_change", "type": "Callable[[bool], None] | None", "description": "Handler that is called when the overlay's open state changes.", "default": "None"}, {"name": "on_change", "type": "Callable[[DType | None | str | date | datetime | datetime64 | Timestamp | int], None] | None", "description": "Handler that is called when the value changes. The exact Date type will be the same as the type passed to value, default_value or placeholder_value, in that order of precedence.", "default": "None"}, {"name": "flex", "type": "str | float | bool | None", "description": "When used in a flex layout, specifies how the element will grow or shrink to fit the space available.", "default": "None"}, {"name": "flex_grow", "type": "float | None", "description": "When used in a flex layout, specifies how much the element will grow to fit the space available.", "default": "None"}, {"name": "flex_shrink", "type": "float | None", "description": "When used in a flex layout, specifies how much the element will shrink to fit the space available.", "default": "None"}, {"name": "flex_basis", "type": "str | float | None", "description": "When used in a flex layout, specifies the initial size of the element.", "default": "None"}, {"name": "align_self", "type": "Literal['auto', 'normal', 'start', 'end', 'center', 'flex-start', 'flex-end', 'self-start', 'self-end', 'stretch'] | None", "description": "Overrides the align_items property of a flex or grid container.", "default": "None"}, {"name": "justify_self", "type": "Literal['auto', 'normal', 'start', 'end', 'flex-start', 'flex-end', 'self-start', 'self-end', 'center', 'left', 'right', 'stretch'] | None", "description": "Specifies how the element is justified inside a flex or grid container.", "default": "None"}, {"name": "order", "type": "int | None", "description": "The layout order for the element within a flex or grid container.", "default": "None"}, {"name": "grid_area", "type": "str | None", "description": "The name of the grid area to place the element in.", "default": "None"}, {"name": "grid_row", "type": "str | None", "description": "The name of the grid row to place the element in.", "default": "None"}, {"name": "grid_row_start", "type": "str | None", "description": "The name of the grid row to start the element in.", "default": "None"}, {"name": "grid_row_end", "type": "str | None", "description": "The name of the grid row to end the element in.", "default": "None"}, {"name": "grid_column", "type": "str | None", "description": "The name of the grid column to place the element in.", "default": "None"}, {"name": "grid_column_start", "type": "str | None", "description": "The name of the grid column to start the element in.", "default": "None"}, {"name": "grid_column_end", "type": "str | None", "description": "The name of the grid column to end the element in.", "default": "None"}, {"name": "margin", "type": "str | float | None", "description": "The margin to apply around the element.", "default": "None"}, {"name": "margin_top", "type": "str | float | None", "description": "The margin to apply above the element.", "default": "None"}, {"name": "margin_bottom", "type": "str | float | None", "description": "The margin to apply below the element.", "default": "None"}, {"name": "margin_start", "type": "str | float | None", "description": "The margin to apply before the element.", "default": "None"}, {"name": "margin_end", "type": "str | float | None", "description": "The margin to apply after the element.", "default": "None"}, {"name": "margin_x", "type": "str | float | None", "description": "The margin to apply to the left and right of the element.", "default": "None"}, {"name": "margin_y", "type": "str | float | None", "description": "The margin to apply to the top and bottom of the element.", "default": "None"}, {"name": "width", "type": "str | float | None", "description": "The width of the element.", "default": "None"}, {"name": "height", "type": "str | float | None", "description": "The height of the element.", "default": "None"}, {"name": "min_width", "type": "str | float | None", "description": "The minimum width of the element.", "default": "None"}, {"name": "min_height", "type": "str | float | None", "description": "The minimum height of the element.", "default": "None"}, {"name": "max_width", "type": "str | float | None", "description": "The maximum width of the element.", "default": "None"}, {"name": "max_height", "type": "str | float | None", "description": "The maximum height of the element.", "default": "None"}, {"name": "position", "type": "Literal['static', 'relative', 'absolute', 'fixed', 'sticky'] | None", "description": "Specifies how the element is positioned.", "default": "None"}, {"name": "top", "type": "str | float | None", "description": "The distance from the top of the containing element.", "default": "None"}, {"name": "bottom", "type": "str | float | None", "description": "The distance from the bottom of the containing element.", "default": "None"}, {"name": "start", "type": "str | float | None", "description": "The distance from the start of the containing element.", "default": "None"}, {"name": "end", "type": "str | float | None", "description": "The distance from the end of the containing element.", "default": "None"}, {"name": "left", "type": "str | float | None", "description": "The distance from the left of the containing element.", "default": "None"}, {"name": "right", "type": "str | float | None", "description": "The distance from the right of the containing element.", "default": "None"}, {"name": "z_index", "type": "int | None", "description": "The stack order of the element.", "default": "None"}, {"name": "is_hidden", "type": "bool | None", "description": "Whether the element is hidden.", "default": "None"}, {"name": "id", "type": "str | None", "description": "A unique identifier for the element.", "default": "None"}, {"name": "aria_label", "type": "str | None", "description": "The label for the element.", "default": "None"}, {"name": "aria_labelledby", "type": "str | None", "description": "The id of the element that labels the element.", "default": "None"}, {"name": "aria_describedby", "type": "str | None", "description": "The id of the element that describes the element.", "default": "None"}, {"name": "aria_pressed", "type": "Literal['true', 'false'] | bool | Literal['mixed'] | None", "description": "Whether the element is pressed.", "default": "None"}, {"name": "aria_details", "type": "str | None", "description": "The details for the element.", "default": "None"}, {"name": "UNSAFE_class_name", "type": "str | None", "description": "A CSS class to apply to the element.", "default": "None"}, {"name": "UNSAFE_style", "type": "Dict[str, Any] | None", "description": "A CSS style to apply to the element.", "default": "None"}, {"name": "key", "type": "str | None", "description": "A unique identifier used by React to render elements in a list.", "default": "None"}]}} />
