-
Notifications
You must be signed in to change notification settings - Fork 8
fix(blog-list): avoid timezone shift when rendering string dates #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -71,16 +71,59 @@ const getClassName = (...classNames: Array<string | false | undefined>) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return classNames.filter(Boolean).join(' '); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 2025-6-26 16:00:00 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ISO_DATE_PREFIX_RE = /^(\d{4})-(\d{2})-(\d{2})(?:$|[T\s])/; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const getDatePartsFromString = (value: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const match = ISO_DATE_PREFIX_RE.exec(value.trim()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!match) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return undefined; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [, year, month, day] = match; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| year: Number(year), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| month: Number(month), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| day: Number(day), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+84
to
+89
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [, year, month, day] = match; | |
| return { | |
| year: Number(year), | |
| month: Number(month), | |
| day: Number(day), | |
| const [, yearString, monthString, dayString] = match; | |
| const year = Number(yearString); | |
| const month = Number(monthString); | |
| const day = Number(dayString); | |
| if ( | |
| !Number.isInteger(year) || | |
| !Number.isInteger(month) || | |
| !Number.isInteger(day) || | |
| month < 1 || | |
| month > 12 || | |
| day < 1 || | |
| day > 31 | |
| ) { | |
| return undefined; | |
| } | |
| const normalizedDate = new Date(year, month - 1, day); | |
| if ( | |
| Number.isNaN(normalizedDate.getTime()) || | |
| normalizedDate.getFullYear() !== year || | |
| normalizedDate.getMonth() !== month - 1 || | |
| normalizedDate.getDate() !== day | |
| ) { | |
| return undefined; | |
| } | |
| return { | |
| year, | |
| month, | |
| day, |
Copilot
AI
Apr 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
normalizeDate now contains a nested ternary where both non-Date branches are identical (new Date(value)), which adds complexity without changing behavior. Consider reverting to value instanceof Date ? value : new Date(value) to keep the helper straightforward.
| const date = | |
| value instanceof Date | |
| ? value | |
| : typeof value === 'string' | |
| ? new Date(value) | |
| : new Date(value); | |
| const date = value instanceof Date ? value : new Date(value); |
Copilot
AI
Apr 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When dateFormatOptions includes an explicit timeZone, formatting a string date via new Date(year, month - 1, day) (local-midnight) can still shift the rendered day when the formatter time zone differs from the client’s local zone. Consider either (a) documenting that the string-date fast path ignores timeZone semantics and is intended to be a locale-only display, or (b) adjusting the construction strategy based on the requested timeZone (e.g., use a UTC-based Date when dateFormatOptions.timeZone is set).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example comment shows
2025-6-26 16:00:00, butISO_DATE_PREFIX_RErequires zero-padded month/day (\d{2}), so that example would not match and the string would fall back tonew Date(value)(reintroducing the timezone-shift behavior). Either update the example toYYYY-MM-DD ...or relax the regex to accept 1–2 digit month/day (and normalize accordingly).