Skip to content

Commit 7293a85

Browse files
match review feedback
1 parent 500e3aa commit 7293a85

File tree

3 files changed

+83
-67
lines changed

3 files changed

+83
-67
lines changed

src/components/DateDetails/DateDetails.stories.tsx

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1+
import { Args } from "@storybook/react";
12
import { DateDetails } from "./DateDetails";
23

34
export default {
45
argTypes: {
5-
locale: {
6-
options: ["en-US", "en-GB", "fr-FR", "de-DE", "ru-RU"],
7-
control: {
8-
type: "select",
9-
},
10-
},
116
side: {
127
control: {
138
type: "select",
149
},
1510
options: ["top", "right", "left", "bottom"],
1611
},
12+
date: {
13+
control: "date",
14+
},
1715
systemTimeZone: {
1816
options: [
1917
"America/Denver",
@@ -39,9 +37,18 @@ export default {
3937
export const Playground = {
4038
args: {
4139
date: new Date(),
42-
locale: "en-US",
4340
side: "top",
4441
systemTimeZone: "America/Los_Angeles",
4542
title: "DateDetails",
4643
},
44+
render: (args: Args) => {
45+
const date = args.date ? new Date(args.date) : new Date();
46+
return (
47+
<DateDetails
48+
date={date}
49+
side={args.side}
50+
systemTimeZone={args.systemTimeZone}
51+
/>
52+
);
53+
},
4754
};

src/components/DateDetails/DateDetails.test.tsx

+30-10
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ describe("DateDetails", () => {
2424
it("renders the DateDetails component with relevant timezone information", () => {
2525
const baseDate = new Date("2024-12-24 11:45:00 AM");
2626
const systemTimeZone = "America/Los_Angeles";
27-
const locale = new Intl.Locale("en", { region: "US" });
2827
vi.setSystemTime(baseDate);
2928

3029
const fiveMinutesAgo = new Date("2024-12-24 11:40:00 AM");
3130

3231
const { getByText } = renderCUI(
3332
<DateDetails
3433
date={fiveMinutesAgo}
35-
locale={locale}
3634
systemTimeZone={systemTimeZone}
3735
/>
3836
);
@@ -51,24 +49,46 @@ describe("DateDetails", () => {
5149
return content.includes("PST");
5250
})
5351
).toBeInTheDocument();
54-
expect(getByText("Dec 24, 2024, 4:40:00 PM")).toBeInTheDocument();
55-
expect(getByText("Dec 24, 2024, 11:40:00 AM (EST)")).toBeInTheDocument();
56-
expect(getByText("Dec 24, 2024, 8:40:00 AM (PST)")).toBeInTheDocument();
52+
expect(getByText("Dec 24, 4:40 p.m.")).toBeInTheDocument();
53+
expect(getByText("Dec 24, 11:40 a.m. (EST)")).toBeInTheDocument();
54+
expect(getByText("Dec 24, 8:40 a.m. (PST)")).toBeInTheDocument();
5755
expect(getByText(fiveMinutesAgo.getTime() / 1000)).toBeInTheDocument();
5856
});
5957

58+
it("only shows the date if the previous date isn't in this year", () => {
59+
const baseDate = new Date("2025-02-07 11:45:00 AM");
60+
const systemTimeZone = "America/Los_Angeles";
61+
vi.setSystemTime(baseDate);
62+
63+
const oneYearAgo = new Date("2024-02-07 11:45:00 AM");
64+
65+
const { getByText } = renderCUI(
66+
<DateDetails
67+
date={oneYearAgo}
68+
systemTimeZone={systemTimeZone}
69+
/>
70+
);
71+
72+
const trigger = getByText("1 year ago");
73+
expect(trigger).toBeInTheDocument();
74+
75+
fireEvent.click(trigger);
76+
expect(getByText("Feb 7, 2024, 4:45 p.m.")).toBeInTheDocument();
77+
expect(getByText("Feb 7, 2024, 11:45 a.m. (EST)")).toBeInTheDocument();
78+
expect(getByText("Feb 7, 2024, 8:45 a.m. (PST)")).toBeInTheDocument();
79+
expect(getByText(oneYearAgo.getTime() / 1000)).toBeInTheDocument();
80+
});
81+
6082
it("handles Daylight Savings Time", () => {
6183
const baseDate = new Date("2024-07-04 11:45:00 AM");
6284
const systemTimeZone = "America/Los_Angeles";
63-
const locale = new Intl.Locale("en", { region: "US" });
6485
vi.setSystemTime(baseDate);
6586

6687
const fiveMinutesAgo = new Date("2024-07-04 11:40:00 AM");
6788

6889
const { getByText } = renderCUI(
6990
<DateDetails
7091
date={fiveMinutesAgo}
71-
locale={locale}
7292
systemTimeZone={systemTimeZone}
7393
/>
7494
);
@@ -87,9 +107,9 @@ describe("DateDetails", () => {
87107
return content.includes("PDT");
88108
})
89109
).toBeInTheDocument();
90-
expect(getByText("Jul 4, 2024, 3:40:00 PM")).toBeInTheDocument();
91-
expect(getByText("Jul 4, 2024, 11:40:00 AM (EDT)")).toBeInTheDocument();
92-
expect(getByText("Jul 4, 2024, 8:40:00 AM (PDT)")).toBeInTheDocument();
110+
expect(getByText("Jul 4, 3:40 p.m.")).toBeInTheDocument();
111+
expect(getByText("Jul 4, 11:40 a.m. (EDT)")).toBeInTheDocument();
112+
expect(getByText("Jul 4, 8:40 a.m. (PDT)")).toBeInTheDocument();
93113
expect(getByText(fiveMinutesAgo.getTime() / 1000)).toBeInTheDocument();
94114
});
95115
});

src/components/DateDetails/DateDetails.tsx

+39-50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import dayjs from "dayjs";
1+
import dayjs, { Dayjs } from "dayjs";
22
import advancedFormat from "dayjs/plugin/advancedFormat";
33
import duration from "dayjs/plugin/duration";
44
import localizedFormat from "dayjs/plugin/localizedFormat";
@@ -62,66 +62,56 @@ const UnderlinedTrigger = styled(Popover.Trigger)<StyledLinkProps>`
6262
${linkStyles}
6363
`;
6464

65-
const dateStyle = "medium";
66-
const timeStyle = "medium";
65+
const formatDateDetails = (date: Dayjs, timezone?: string): string => {
66+
const isCurrentYear = dayjs().year() === date.year();
67+
const formatForCurrentYear = "MMM D, h:mm a";
68+
const formatForPastYear = "MMM D, YYYY, h:mm a";
69+
70+
if (isCurrentYear) {
71+
if (timezone) {
72+
const dateWithTimezone = date.tz(timezone);
73+
return dateWithTimezone
74+
.format(formatForCurrentYear)
75+
.replace("am", "a.m.")
76+
.replace("pm", "p.m.");
77+
}
6778

68-
const createBasicDateDetailsFormatter = () => {
69-
return new Intl.DateTimeFormat(undefined, {
70-
dateStyle,
71-
timeStyle,
72-
});
73-
};
79+
return date.format(formatForCurrentYear).replace("am", "a.m.").replace("pm", "p.m.");
80+
}
7481

75-
const formatDateDetails = (date: Date, locale?: Intl.Locale, timeZone?: string) => {
76-
let dateDetailsFormatter;
77-
try {
78-
dateDetailsFormatter = new Intl.DateTimeFormat(locale, {
79-
dateStyle,
80-
timeStyle,
81-
timeZone,
82-
});
83-
} catch (error) {
84-
if ((error as Error).message.includes("invalid time zone")) {
85-
try {
86-
dateDetailsFormatter = new Intl.DateTimeFormat(locale, {
87-
dateStyle,
88-
timeStyle,
89-
});
90-
} catch {
91-
dateDetailsFormatter = createBasicDateDetailsFormatter();
92-
}
93-
} else if ((error as Error).message.includes("invalid language tag")) {
94-
try {
95-
dateDetailsFormatter = new Intl.DateTimeFormat(undefined, {
96-
dateStyle,
97-
timeStyle,
98-
timeZone,
99-
});
100-
} catch {
101-
dateDetailsFormatter = createBasicDateDetailsFormatter();
102-
}
103-
} else {
104-
dateDetailsFormatter = createBasicDateDetailsFormatter();
105-
}
82+
if (timezone) {
83+
const dateWithTimezone = date.tz(timezone);
84+
return dateWithTimezone
85+
.format(formatForPastYear)
86+
.replace("am", "a.m.")
87+
.replace("pm", "p.m.");
10688
}
89+
return date.format(formatForPastYear).replace("am", "a.m.").replace("pm", "p.m.");
90+
};
10791

108-
return dateDetailsFormatter.format(date);
92+
const formatTimezone = (date: Dayjs, timezone: string): string => {
93+
return (
94+
new Intl.DateTimeFormat("en-US", {
95+
timeZone: timezone,
96+
timeZoneName: "short",
97+
})
98+
.formatToParts(date.toDate())
99+
.find(part => part.type === "timeZoneName")?.value ?? date.format("z")
100+
);
109101
};
110102

111103
export type ArrowPosition = "top" | "right" | "left" | "bottom";
112104

113105
export interface DateDetailsProps {
114106
date: Date;
115-
locale?: Intl.Locale;
116107
side?: ArrowPosition;
117108
systemTimeZone?: string;
118109
}
119110

120111
export const DateDetails = ({
121112
date,
122-
locale,
123113
side = "top",
124-
systemTimeZone,
114+
systemTimeZone = "America/New_York",
125115
}: DateDetailsProps) => {
126116
const dayjsDate = dayjs(date);
127117

@@ -155,7 +145,8 @@ export const DateDetails = ({
155145
<Text size="md">Local</Text>
156146
<Container justifyContent="end">
157147
<Text size="md">
158-
{formatDateDetails(dayjsDate.toDate(), locale)} ({dayjsDate.format("z")})
148+
{formatDateDetails(dayjsDate)} (
149+
{formatTimezone(dayjsDate, dayjs.tz.guess())})
159150
</Text>
160151
</Container>
161152

@@ -165,18 +156,16 @@ export const DateDetails = ({
165156

166157
<Container justifyContent="end">
167158
<Text size="md">
168-
{formatDateDetails(systemTime.toDate(), locale, systemTimeZone)} (
169-
{systemTime.format("z")})
159+
{formatDateDetails(systemTime, systemTimeZone)} (
160+
{formatTimezone(systemTime, systemTimeZone)})
170161
</Text>
171162
</Container>
172163
</>
173164
)}
174165

175166
<Text size="md">UTC</Text>
176167
<Container justifyContent="end">
177-
<Text size="md">
178-
{formatDateDetails(dayjsDate.utc().toDate(), locale, "UTC")}
179-
</Text>
168+
<Text size="md">{formatDateDetails(dayjsDate.utc(), "UTC")}</Text>
180169
</Container>
181170

182171
<Text size="md">Unix</Text>

0 commit comments

Comments
 (0)