Skip to content

Commit 43acb66

Browse files
Merge pull request #6055 from Hacker0x01/docs/timezone-handling-guide
Add timezone handling documentation
2 parents c150b04 + c60ac8a commit 43acb66

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ Locales can be changed in the following way:
121121

122122
- **Globally** - `setDefaultLocale('es');`
123123

124+
### Timezone handling
125+
126+
React-datepicker uses native JavaScript Date objects which are timezone-aware. By default, dates are displayed in the user's local timezone. The library does not include built-in timezone conversion utilities.
127+
128+
For detailed information about working with timezones, UTC dates, and common timezone-related scenarios, see the [Timezone Handling Guide](https://github.com/Hacker0x01/react-datepicker/blob/main/docs/timezone.md).
129+
130+
For applications requiring timezone conversion, we recommend using [date-fns-tz](https://github.com/marnusw/date-fns-tz) alongside react-datepicker.
131+
124132
## Compatibility
125133

126134
### React

docs/timezone.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Timezone Handling Guide
2+
3+
This guide explains how react-datepicker handles timezones and provides solutions for common timezone-related scenarios.
4+
5+
## How react-datepicker Handles Dates
6+
7+
React-datepicker uses native JavaScript `Date` objects and the [date-fns](https://date-fns.org/) library for date manipulation. This means:
8+
9+
1. **All dates are stored as JavaScript Date objects** - These represent a specific moment in time (internally stored as milliseconds since Unix epoch in UTC).
10+
11+
2. **Display is based on the user's local timezone** - When a Date object is displayed, JavaScript automatically converts it to the user's local timezone.
12+
13+
3. **No built-in timezone conversion** - The datepicker does not include built-in timezone conversion utilities. If you need timezone support, you'll need to handle conversions in your application code.
14+
15+
## Common Questions and Solutions
16+
17+
### 1. Why do dates appear differently across timezones?
18+
19+
JavaScript Date objects represent an absolute moment in time. When displayed, they're converted to the user's local timezone. For example, `2025-01-15T00:00:00Z` (midnight UTC) will display as:
20+
21+
- `Jan 14, 2025 7:00 PM` in New York (UTC-5)
22+
- `Jan 15, 2025 9:00 AM` in Tokyo (UTC+9)
23+
24+
**Solution**: If you want dates to display consistently regardless of timezone, consider:
25+
26+
- Storing and transmitting dates as date-only strings (e.g., `"2025-01-15"`) without time components
27+
- Creating dates at noon local time to avoid day boundary issues: `new Date(2025, 0, 15, 12, 0, 0)`
28+
29+
### 2. How do I work with UTC dates?
30+
31+
If your backend stores dates in UTC and you want to display them as UTC:
32+
33+
```jsx
34+
// Convert UTC string to local Date for display
35+
const utcDateString = "2025-01-15T10:30:00Z";
36+
const date = new Date(utcDateString);
37+
38+
// When sending back to server, convert to UTC ISO string
39+
const handleChange = (date) => {
40+
const utcString = date.toISOString(); // Always returns UTC
41+
sendToServer(utcString);
42+
};
43+
44+
<DatePicker selected={date} onChange={handleChange} />;
45+
```
46+
47+
### 3. How do I display dates in a specific timezone?
48+
49+
For displaying dates in a specific timezone (not the user's local timezone), you can use libraries like [date-fns-tz](https://github.com/marnusw/date-fns-tz):
50+
51+
```jsx
52+
import { formatInTimeZone, toZonedTime } from "date-fns-tz";
53+
54+
// Display a date in a specific timezone
55+
const timeZone = "America/New_York";
56+
const utcDate = new Date(); // Current time in UTC
57+
58+
// Convert to the target timezone for display
59+
const zonedDate = toZonedTime(utcDate, timeZone);
60+
61+
// Format with timezone
62+
const formatted = formatInTimeZone(utcDate, timeZone, "yyyy-MM-dd HH:mm:ss zzz");
63+
```
64+
65+
### 4. Why does the selected date change when I submit a form?
66+
67+
This typically happens because:
68+
69+
- The date is created in local time but sent to the server as UTC
70+
- The server interprets the UTC date differently
71+
72+
**Solution**: Be explicit about how you serialize dates:
73+
74+
```jsx
75+
const handleChange = (date) => {
76+
// Option 1: Send as ISO string (includes timezone info)
77+
const isoString = date.toISOString(); // "2025-01-15T05:00:00.000Z"
78+
79+
// Option 2: Send as date-only string (no timezone ambiguity)
80+
const dateOnly = date.toISOString().split("T")[0]; // "2025-01-15"
81+
82+
// Option 3: Send as Unix timestamp
83+
const timestamp = date.getTime(); // 1736920800000
84+
};
85+
```
86+
87+
### 5. How do I create a date without timezone issues?
88+
89+
For date-only scenarios (no time component), create dates at noon to avoid day boundary issues:
90+
91+
```jsx
92+
// Instead of this (can shift days at timezone boundaries):
93+
const date = new Date("2025-01-15"); // Parsed as UTC midnight
94+
95+
// Do this (noon local time is safe from day shifts):
96+
const createLocalDate = (year, month, day) => {
97+
return new Date(year, month - 1, day, 12, 0, 0);
98+
};
99+
100+
// Or parse a date string as local time:
101+
const parseLocalDate = (dateString) => {
102+
const [year, month, day] = dateString.split("-").map(Number);
103+
return new Date(year, month - 1, day, 12, 0, 0);
104+
};
105+
```
106+
107+
### 6. How do I handle date ranges across timezones?
108+
109+
When working with date ranges, ensure both start and end dates are handled consistently:
110+
111+
```jsx
112+
const [startDate, setStartDate] = useState(null);
113+
const [endDate, setEndDate] = useState(null);
114+
115+
// Normalize dates to start/end of day in local time
116+
const normalizeStartDate = (date) => {
117+
if (!date) return null;
118+
const d = new Date(date);
119+
d.setHours(0, 0, 0, 0);
120+
return d;
121+
};
122+
123+
const normalizeEndDate = (date) => {
124+
if (!date) return null;
125+
const d = new Date(date);
126+
d.setHours(23, 59, 59, 999);
127+
return d;
128+
};
129+
130+
<DatePicker
131+
selectsRange
132+
startDate={startDate}
133+
endDate={endDate}
134+
onChange={(dates) => {
135+
const [start, end] = dates;
136+
setStartDate(normalizeStartDate(start));
137+
setEndDate(normalizeEndDate(end));
138+
}}
139+
/>;
140+
```
141+
142+
## Best Practices
143+
144+
1. **Be consistent**: Choose one approach for handling timezones across your application and stick with it.
145+
146+
2. **Store dates in UTC**: When persisting dates, store them in UTC format (ISO 8601 strings or Unix timestamps).
147+
148+
3. **Convert on the boundaries**: Handle timezone conversion at the edges of your application (when receiving from or sending to APIs).
149+
150+
4. **Use date-fns-tz for complex timezone needs**: If you need to display dates in specific timezones, use a dedicated library like date-fns-tz.
151+
152+
5. **Test across timezones**: Test your application with different system timezones to catch timezone-related bugs.
153+
154+
6. **Document your date format**: Make sure your team knows what format dates are stored and transmitted in.
155+
156+
## Additional Resources
157+
158+
- [date-fns Documentation](https://date-fns.org/docs/Getting-Started)
159+
- [date-fns-tz for timezone support](https://github.com/marnusw/date-fns-tz)
160+
- [MDN Date Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
161+
- [Understanding JavaScript Date and Timezones](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format)

0 commit comments

Comments
 (0)