mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 18:22:38 +00:00
Show the date for a message from today's weekday last week (#5341)
A reply sent last Friday at 12:02 PM, read on Friday at 11:47 AM, was labelled "Friday 12:02 PM" because the weekday window counted 24-hour periods, and that reply was just under seven of them old. Count calendar days instead, so the weekday form covers only the previous six days and today's weekday a week back shows its date. Closes #5225 Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -108,6 +108,17 @@ describe("formatMessageTimestamp", () => {
|
||||
expect(formatted).toMatch(/10:12 PM|22:12/);
|
||||
});
|
||||
|
||||
it("shows the full date for last week's same weekday, even under seven days ago", () => {
|
||||
// 2026-09-18 is a Friday. The reply is 6 days 23h45m old and lands on today's weekday,
|
||||
// so a weekday label would read as today.
|
||||
const now = new Date(2026, 8, 25, 11, 47);
|
||||
const date = new Date(2026, 8, 18, 12, 2);
|
||||
const formatted = formatMessageTimestamp(date, now);
|
||||
expect(formatted).toMatch(/Sep|September/);
|
||||
expect(formatted).toMatch(/18/);
|
||||
expect(formatted).not.toMatch(/Friday/);
|
||||
});
|
||||
|
||||
it("includes full date for older timestamps", () => {
|
||||
const now = new Date(2026, 4, 14, 17, 30);
|
||||
const date = new Date(2026, 3, 1, 9, 5);
|
||||
|
||||
@@ -91,12 +91,14 @@ export function formatCompactTimeAgo(date: Date, now: Date = new Date()): string
|
||||
return describeCompactTimeAgo(date, now).label;
|
||||
}
|
||||
|
||||
function isSameLocalDay(a: Date, b: Date): boolean {
|
||||
return (
|
||||
a.getFullYear() === b.getFullYear() &&
|
||||
a.getMonth() === b.getMonth() &&
|
||||
a.getDate() === b.getDate()
|
||||
);
|
||||
/**
|
||||
* How many local midnights lie between two instants: 0 for the same day, 1 for yesterday.
|
||||
* Counted on the calendar rather than in elapsed time, so six days and 23 hours ago on
|
||||
* today's weekday is 7, and rounded so a DST day of 23 or 25 hours still counts as one.
|
||||
*/
|
||||
function localCalendarDaysBetween(earlier: Date, later: Date): number {
|
||||
const startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||
return Math.round((startOfDay(later).getTime() - startOfDay(earlier).getTime()) / DAY_MS);
|
||||
}
|
||||
|
||||
// Cached Intl formatter. Explicitly carrying `hourCycle` from the resolved
|
||||
@@ -120,19 +122,18 @@ function getTimeFormatter(): Intl.DateTimeFormat {
|
||||
/**
|
||||
* Format a chat-message timestamp for hover-revealed UI.
|
||||
* - Same day: "10:11 PM" or "22:11" depending on user preference
|
||||
* - Within ~6 days: "Wednesday 10:11 PM"
|
||||
* - Older: "14 May 2026, 10:11 PM"
|
||||
* - The previous 6 calendar days: "Wednesday 10:11 PM"
|
||||
* - Older, including today's weekday last week: "14 May 2026, 10:11 PM"
|
||||
*/
|
||||
export function formatMessageTimestamp(date: Date, now: Date = new Date()): string {
|
||||
const time = getTimeFormatter().format(date);
|
||||
const daysAgo = localCalendarDaysBetween(date, now);
|
||||
|
||||
if (isSameLocalDay(date, now)) {
|
||||
if (daysAgo === 0) {
|
||||
return time;
|
||||
}
|
||||
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||
if (diffDays >= 0 && diffDays < 7) {
|
||||
if (daysAgo > 0 && daysAgo < 7) {
|
||||
const weekday = date.toLocaleDateString(undefined, { weekday: "long" });
|
||||
return `${weekday} ${time}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user