Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/fix-message-parser-timestamp-overflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/message-parser': patch
---

Fixes `<t:...>` timestamps with dates on or after 2038-01-19 rendering as a wrong (1903) date. The parser truncated the epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the exact overflow boundary.

The signed 32-bit maximum remains valid at 2038-01-19T03:14:07Z. Overflow starts after that instant. Line 5 currently implies that all of January 19 is affected.

The PR objective identifies the boundary as 2038-01-19 03:14:07 UTC.

Proposed wording
-Fixes `<t:...>` timestamps with dates on or after 2038-01-19 rendering as a wrong (1903) date. The parser truncated the epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
+Fixes `<t:...>` timestamps after 2038-01-19 03:14:07 UTC rendering as incorrect pre-epoch dates. The parser truncated epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Fixes `<t:...>` timestamps with dates on or after 2038-01-19 rendering as a wrong (1903) date. The parser truncated the epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
Fixes `<t:...>` timestamps after 2038-01-19 03:14:07 UTC rendering as incorrect pre-epoch dates. The parser truncated epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/fix-message-parser-timestamp-overflow.md at line 5, Update the
changeset wording to state that signed 32-bit overflow begins after 2038-01-19
03:14:07 UTC, rather than implying the entire date is affected; retain that
Math.floor fixes future timestamp parsing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The changeset wording says dates "on or after 2038-01-19" are affected, but the 32-bit signed epoch overflow actually starts after 2038-01-19T03:14:07Z (values before that time are still valid). Consider tightening the wording to reference the exact boundary instant, e.g. "after 2038-01-19T03:14:07Z", to avoid implying all of Jan 19 is affected.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .changeset/fix-message-parser-timestamp-overflow.md, line 5:

<comment>The changeset wording says dates "on or after 2038-01-19" are affected, but the 32-bit signed epoch overflow actually starts after 2038-01-19T03:14:07Z (values before that time are still valid). Consider tightening the wording to reference the exact boundary instant, e.g. "after 2038-01-19T03:14:07Z", to avoid implying all of Jan 19 is affected.</comment>

<file context>
@@ -0,0 +1,5 @@
+'@rocket.chat/message-parser': patch
+---
+
+Fixes `<t:...>` timestamps with dates on or after 2038-01-19 rendering as a wrong (1903) date. The parser truncated the epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
</file context>
Suggested change
Fixes `<t:...>` timestamps with dates on or after 2038-01-19 rendering as a wrong (1903) date. The parser truncated the epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.
Fixes `<t:...>` timestamps after 2038-01-19 03:14:07 UTC rendering as incorrect pre-epoch dates. The parser truncated epoch seconds with `| 0`, which overflows the 32-bit signed range; it now uses `Math.floor`, so future dates parse correctly.

10 changes: 5 additions & 5 deletions packages/message-parser/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ export const timestampFromHours = (hours: string, minutes = '00', seconds = '00'

const yearMonthDay = date.toISOString().split('T')[0];

const timestamp = (new Date(`${yearMonthDay}T${hours}:${minutes}:${seconds}${timezone}`).getTime() / 1000) | 0;
const timestamp = Math.floor(new Date(`${yearMonthDay}T${hours}:${minutes}:${seconds}${timezone}`).getTime() / 1000);

return timestamp.toString();
};
Expand All @@ -387,9 +387,9 @@ export const timestampFromIsoTime = ({
milliseconds?: string;
timezone?: string;
}) => {
const date =
(new Date(`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds || '000'}${timezone ? `${timezone}` : ''}`).getTime() /
1000) |
0;
const date = Math.floor(
new Date(`${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds || '000'}${timezone ? `${timezone}` : ''}`).getTime() /
1000,
);
return date.toString();
};
3 changes: 3 additions & 0 deletions packages/message-parser/tests/timestamp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ test.each([
['<t:2025-07-22T10:00:00.000+00:00:R>', '1753178400', 'R' as const],
['<t:2025-07-22T10:00:00+00:00:R>', '1753178400', 'R' as const],
['<t:2025-07-24T20:19:58.154+00:00:R>', '1753388398', 'R' as const],
// Beyond the 2038-01-19 32-bit boundary: must not overflow to a negative
// (previously `| 0` turned this into -2085978496 -> a 1903 date).
['<t:2040-01-01T00:00:00.000+00:00:R>', '2208988800', 'R' as const],
])('parses %p', (input, value, format) => {
const node = timestampNode(value, format, [0, input.length]);
expect(parse(input)).toEqual([paragraph([node])]);
Expand Down