Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"at-rule-no-unknown": null,
"at-rule-disallowed-list": ["import"],
"scss/at-rule-no-unknown": true,
"scss/dollar-variable-colon-space-after": null,
"scss/dollar-variable-pattern": null,
"scss/at-import-partial-extension": null,
"scss/no-global-function-names": null,
Expand Down
7 changes: 7 additions & 0 deletions docs-site/src/components/Examples/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import YearItemNumber from "../../examples/ts/yearItemNumber?raw";
import WeekPicker from "../../examples/ts/weekPicker?raw";
import ExcludeWeeks from "../../examples/ts/excludeWeeks?raw";
import ExternalForm from "../../examples/ts/externalForm?raw";
import Timezone from "../../examples/ts/timezone?raw";

export const EXAMPLE_CONFIG: IExampleConfig[] = [
{
Expand Down Expand Up @@ -581,4 +582,10 @@ export const EXAMPLE_CONFIG: IExampleConfig[] = [
title: "External Form",
component: ExternalForm,
},
{
title: "Timezone",
description:
"Display and handle dates in a specific timezone using the timeZone prop. Requires date-fns-tz as a peer dependency.",
component: Timezone,
},
];
17 changes: 17 additions & 0 deletions docs-site/src/examples/ts/timezone.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Timezone = () => {
const [selectedDate, setSelectedDate] = useState<Date | null>(new Date());

return (
<DatePicker
selected={selectedDate}
onChange={setSelectedDate}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
dateFormat="MMMM d, yyyy h:mm aa (zzz)"
timeZone="America/New_York"
/>
);
};

render(Timezone);
4 changes: 4 additions & 0 deletions docs-site/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4694,8 +4694,12 @@ __metadata:
clsx: "npm:^2.1.1"
date-fns: "npm:^4.1.0"
peerDependencies:
date-fns-tz: ^3.0.0
react: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc
peerDependenciesMeta:
date-fns-tz:
optional: true
languageName: node
linkType: soft

Expand Down
107 changes: 106 additions & 1 deletion docs/timezone.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,112 @@

This guide explains how react-datepicker handles timezones and provides solutions for common timezone-related scenarios.

## The "Date is One Day Off" Problem (Issue #1018)
## Using the `timeZone` Prop

React-datepicker now supports a `timeZone` prop that allows you to display and handle dates in a specific timezone, regardless of the user's local timezone. This feature requires the optional `date-fns-tz` peer dependency.

### Installation

To use the `timeZone` prop, you need to install `date-fns-tz`:

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

### Basic Usage

```jsx
import DatePicker from "react-datepicker";

function MyComponent() {
const [startDate, setStartDate] = useState(new Date());

return <DatePicker selected={startDate} onChange={(date) => setStartDate(date)} timeZone="America/New_York" />;
}
```

### How It Works

When you provide a `timeZone` prop:

1. **Display**: Dates are displayed in the specified timezone. For example, if you select January 15th at noon UTC and the timezone is "America/New_York", the datepicker will display the date as it appears in New York time.

2. **Selection**: When a user selects a date, the `onChange` callback receives a Date object that represents the selected moment in UTC. The internal conversion ensures that the date selected visually in the specified timezone is correctly converted.

3. **Current Time**: The "today" indicator and default selections use the current time in the specified timezone.

### Supported Timezone Formats

The `timeZone` prop accepts IANA timezone identifiers:

- `"UTC"` - Coordinated Universal Time
- `"America/New_York"` - Eastern Time (US)
- `"America/Los_Angeles"` - Pacific Time (US)
- `"Europe/London"` - British Time
- `"Europe/Paris"` - Central European Time
- `"Asia/Tokyo"` - Japan Standard Time
- `"Australia/Sydney"` - Australian Eastern Time

For a complete list, see the [IANA Time Zone Database](https://www.iana.org/time-zones).

### Examples

#### Date and Time Picker in a Specific Timezone

```jsx
import DatePicker from "react-datepicker";

function TimezoneDateTimePicker() {
const [date, setDate] = useState(new Date());

return <DatePicker selected={date} onChange={setDate} showTimeSelect timeZone="Europe/London" dateFormat="MMMM d, yyyy h:mm aa" />;
}
```

#### Date Range in UTC

```jsx
import DatePicker from "react-datepicker";

function UTCDateRange() {
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);

const onChange = (dates) => {
const [start, end] = dates;
setStartDate(start);
setEndDate(end);
};

return <DatePicker selected={startDate} onChange={onChange} startDate={startDate} endDate={endDate} selectsRange timeZone="UTC" />;
}
```

#### Inline Calendar with Timezone

```jsx
import DatePicker from "react-datepicker";

function TokyoCalendar() {
const [date, setDate] = useState(new Date());

return <DatePicker selected={date} onChange={setDate} inline timeZone="Asia/Tokyo" />;
}
```

### Important Notes

- **Optional Dependency**: The `timeZone` prop requires `date-fns-tz` to be installed. If it's not installed and you use the `timeZone` prop, a warning will be logged in development mode and the datepicker will fall back to local timezone behavior.

- **UTC Storage**: Even when using a timezone, the Date objects passed to `onChange` represent moments in time (internally stored as UTC). The timezone only affects how dates are displayed and interpreted during selection.

- **Consistency**: When using the `timeZone` prop, ensure all date-related props (like `minDate`, `maxDate`, `excludeDates`, etc.) are provided in a consistent manner.

---

## The "Date is One Day Off" Problem

One of the most commonly reported issues is that the selected date appears to be "one day off" when converted to a string or sent to a server. This is **not a bug** in react-datepicker—it's the expected behavior of JavaScript Date objects.

Expand Down
32 changes: 28 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,23 @@
"./dist/": "./dist/",
"./src/stylesheets/": "./src/stylesheets/"
},
"files": ["*.md", "dist", "lib", "es", "src"],
"sideEffects": ["**/*.css"],
"keywords": ["react", "datepicker", "calendar", "date", "react-component"],
"files": [
"*.md",
"dist",
"lib",
"es",
"src"
],
"sideEffects": [
"**/*.css"
],
"keywords": [
"react",
"datepicker",
"calendar",
"date",
"react-component"
],
"repository": {
"type": "git",
"url": "git://github.com/Hacker0x01/react-datepicker.git"
Expand Down Expand Up @@ -65,6 +79,7 @@
"babel-jest": "^30.0.2",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"core-js": "^3.46.0",
"date-fns-tz": "^3.2.0",
"eslint": "^9.19.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-import": "^2.31.0",
Expand Down Expand Up @@ -96,9 +111,15 @@
"typescript-eslint": "^8.22.0"
},
"peerDependencies": {
"date-fns-tz": "^3.0.0",
"react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"date-fns-tz": {
"optional": true
}
},
"dependencies": {
"@floating-ui/react": "^0.27.15",
"clsx": "^2.1.1",
Expand Down Expand Up @@ -128,7 +149,10 @@
"prepare": "husky"
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css,scss,md}": ["prettier --write", "git add"]
"*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write",
"git add"
]
},
"packageManager": "[email protected]"
}
Loading
Loading