Skip to content

Commit 3d38acd

Browse files
Frontend/i18n: Use Temporal in localizeDateTime (#9247)
1 parent 1435b33 commit 3d38acd

20 files changed

Lines changed: 216 additions & 222 deletions

app/web/features/auth/InviteCodesPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { ListInviteCodesRes } from "proto/account_pb";
1919
import React from "react";
2020
import { inviteRoute } from "routes";
2121
import { service } from "service";
22-
import { localizeDateTime } from "utils/date";
22+
import { localizeDateTime, timestampToPlainDateTime } from "utils/date";
2323

2424
import { inviteCodesKey } from "../queryKeys";
2525

@@ -164,7 +164,7 @@ export default function InviteCodesPage() {
164164
<>
165165
{t("global:invites.created_datetime", {
166166
datetime: localizeDateTime(
167-
new Date(c.created.seconds * 1000),
167+
timestampToPlainDateTime(c.created),
168168
{
169169
locale: locale,
170170
abbreviate: true,
@@ -178,7 +178,7 @@ export default function InviteCodesPage() {
178178
{" • "}
179179
{t("global:invites.disabled_datetime", {
180180
datetime: localizeDateTime(
181-
new Date(c.disabled.seconds * 1000),
181+
timestampToPlainDateTime(c.disabled),
182182
{
183183
locale,
184184
abbreviate: true,

app/web/features/auth/jail/ModNoteCard.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ModNote } from "proto/account_pb";
77
import { useState } from "react";
88
import { service } from "service";
99
import { theme } from "theme";
10-
import { localizeDateTime, timestamp2Date } from "utils/date";
10+
import { localizeDateTime, timestampToPlainDateTime } from "utils/date";
1111

1212
const StyledNoteContainer = styled("div")(() => ({
1313
marginBottom: theme.spacing(4),
@@ -33,10 +33,13 @@ export default function ModNoteCard({ note, updateJailed }: ModNoteCardProps) {
3333
const [acknowledged, setAcknowledged] = useState(false);
3434
const [loading, setLoading] = useState(false);
3535

36-
const formattedTime = localizeDateTime(timestamp2Date(note.created!), {
37-
locale,
38-
abbreviate: true,
39-
});
36+
const formattedTime = localizeDateTime(
37+
timestampToPlainDateTime(note.created!),
38+
{
39+
locale,
40+
abbreviate: true,
41+
},
42+
);
4043

4144
const acknowledge = async () => {
4245
setLoading(true);

app/web/features/auth/logins/LoginCard.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import { AUTH, GLOBAL } from "i18n/namespaces";
2121
import { useTranslation } from "next-i18next";
2222
import { ActiveSession } from "proto/account_pb";
2323
import { service } from "service";
24-
import { localizeDateTime, timestamp2Date } from "utils/date";
24+
import {
25+
localizeDateTime,
26+
timestamp2Date,
27+
timestampToPlainDateTime,
28+
} from "utils/date";
2529
import { timeAgo } from "utils/timeAgo";
2630

2731
const StyledCard = styled(Card)(({ theme }) => ({
@@ -44,16 +48,22 @@ export default function LoginsPage({
4448
t,
4549
locale,
4650
});
47-
const createdDisplay = localizeDateTime(timestamp2Date(session.created!), {
48-
locale,
49-
includeSeconds: true,
50-
abbreviate: true,
51-
});
52-
const expiryDisplay = localizeDateTime(timestamp2Date(session.expiry!), {
53-
locale,
54-
includeTime: false,
55-
abbreviate: true,
56-
});
51+
const createdDisplay = localizeDateTime(
52+
timestampToPlainDateTime(session.created!),
53+
{
54+
locale,
55+
includeSeconds: true,
56+
abbreviate: true,
57+
},
58+
);
59+
const expiryDisplay = localizeDateTime(
60+
timestampToPlainDateTime(session.expiry!),
61+
{
62+
locale,
63+
includeTime: false,
64+
abbreviate: true,
65+
},
66+
);
5767
const queryClient = useQueryClient();
5868

5969
const {

app/web/features/auth/timezone/Timezone.tsx

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Typography } from "@mui/material";
22
import { Trans, useTranslation } from "i18n";
33
import { AUTH } from "i18n/namespaces";
4+
import { Temporal } from "temporal-polyfill";
45
import { localizeDateTime } from "utils/date";
5-
import dayjs from "utils/dayjs";
66

77
interface TimezoneProps {
88
className?: string;
@@ -24,27 +24,18 @@ export default function Timezone({ className, timezone }: TimezoneProps) {
2424
<Trans
2525
t={t}
2626
i18nKey="account_settings_page.timezone_section.description"
27+
components={{
28+
1: <strong />,
29+
4: <strong />,
30+
}}
2731
values={{
2832
timezone: timezone,
29-
time: localizeDateTime(dayjs(), {
30-
timezone,
33+
time: localizeDateTime(Temporal.Now.plainDateTimeISO(timezone), {
3134
locale,
3235
includeDate: false,
3336
}),
3437
}}
35-
>
36-
{`Your timezone is `}
37-
<strong>{timezone}</strong>. Based on this, your local time is
38-
approximately{` `}
39-
<strong>
40-
{localizeDateTime(dayjs(), {
41-
timezone,
42-
locale,
43-
includeDate: false,
44-
})}
45-
</strong>
46-
{`.`}
47-
</Trans>
38+
/>
4839
</Typography>
4940
<Typography variant="body1">
5041
{t("account_settings_page.timezone_section.explanation")}

app/web/features/communities/discussions/DiscussionPage.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import { useState } from "react";
2424
import { useForm } from "react-hook-form";
2525
import { service } from "service";
2626
import { theme } from "theme";
27-
import { localizeDateTime, timestamp2Date } from "utils/date";
27+
import {
28+
localizeDateTime,
29+
timestamp2Date,
30+
timestampToPlainDateTime,
31+
} from "utils/date";
2832
import { timeAgo } from "utils/timeAgo";
2933

3034
import { sendNativeBack, useIsNativeEmbed } from "../../../utils/nativeLink";
@@ -287,7 +291,9 @@ export default function DiscussionPage({
287291
<Typography variant="body2">
288292
{t("communities:discussion_creation_date", {
289293
dateOnly: localizeDateTime(
290-
timestamp2Date(discussion.created!),
294+
timestampToPlainDateTime(
295+
discussion.created!,
296+
),
291297
{
292298
locale,
293299
includeTime: false,

app/web/features/communities/events/EventCard.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,7 @@ import Link from "next/link";
1616
import { Event } from "proto/events_pb";
1717
import { useMemo } from "react";
1818
import { routeToEvent } from "routes";
19-
import {
20-
BROWSER_TIMEZONE,
21-
localizeDateTimeRange,
22-
timestamp2Date,
23-
} from "utils/date";
24-
import dayjs from "utils/dayjs";
19+
import { localizeDateTimeRange, timestampToPlainDateTime } from "utils/date";
2520
import stripMarkdown from "utils/stripMarkdown";
2621

2722
const StyledCard = styled(Card, {
@@ -133,11 +128,10 @@ export default function EventCard({ event, className }: EventCardProps) {
133128
} = useTranslation([COMMUNITIES]);
134129

135130
const dateTimeRangeText = localizeDateTimeRange(
136-
dayjs(timestamp2Date(event.startTime!)),
137-
dayjs(timestamp2Date(event.endTime!)),
131+
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
132+
timestampToPlainDateTime(event.startTime!),
133+
timestampToPlainDateTime(event.endTime!),
138134
{
139-
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
140-
timezone: BROWSER_TIMEZONE,
141135
locale,
142136
includeDayOfWeek: true,
143137
abbreviate: true,

app/web/features/communities/events/EventPage.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ import {
3434
import { service } from "service";
3535
import { theme } from "theme";
3636
import {
37-
BROWSER_TIMEZONE,
3837
localizeDateTimeRange,
3938
timestamp2Date,
39+
timestampToPlainDateTime,
4040
} from "utils/date";
4141
import dayjs from "utils/dayjs";
4242
import { sendNativeBack, useIsNativeEmbed } from "utils/nativeLink";
@@ -411,11 +411,10 @@ export default function EventPage({
411411
<StyledCalendarIcon />
412412
<Typography variant="body1">
413413
{localizeDateTimeRange(
414-
dayjs(timestamp2Date(event.startTime!)),
415-
dayjs(timestamp2Date(event.endTime!)),
414+
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
415+
timestampToPlainDateTime(event.startTime!),
416+
timestampToPlainDateTime(event.endTime!),
416417
{
417-
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
418-
timezone: BROWSER_TIMEZONE,
419418
locale,
420419
includeDayOfWeek: true,
421420
capitalize: true,

app/web/features/communities/events/EventTimeChanger.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { styled } from "@mui/material";
22
import Datepicker from "components/Datepicker";
33
import Timepicker from "components/Timepicker";
4-
import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb";
54
import { useTranslation } from "i18n";
65
import { COMMUNITIES } from "i18n/namespaces";
76
import { Event } from "proto/events_pb";
87
import { UseFormReturn } from "react-hook-form";
98
import { Temporal } from "temporal-polyfill";
109
import { theme } from "theme";
11-
import { timestamp2Date } from "utils/date";
10+
import { timestampToPlainDateTime } from "utils/date";
1211
import { timePattern } from "utils/validation";
1312

1413
import { CreateEventData } from "./EventForm";
@@ -32,16 +31,6 @@ interface EventTimeChangerProps
3231
errors: UseFormReturn<CreateEventData>["formState"]["errors"];
3332
}
3433

35-
function toPlainDateTime(
36-
timestamp: Timestamp.AsObject,
37-
): Temporal.PlainDateTime {
38-
const legacyDate = timestamp2Date(timestamp);
39-
const instant = Temporal.Instant.fromEpochMilliseconds(legacyDate.getTime());
40-
// FIXME(#8064): Event times should be interpreted in their timezones.
41-
const zoned = instant.toZonedDateTimeISO(Temporal.Now.timeZoneId());
42-
return zoned.toPlainDateTime();
43-
}
44-
4534
export default function EventTimeChanger({
4635
control,
4736
dirtyFields,
@@ -52,11 +41,12 @@ export default function EventTimeChanger({
5241
}: EventTimeChangerProps) {
5342
const { t } = useTranslation([COMMUNITIES]);
5443

44+
// FIXME(#8064): Event times should be interpreted in their timezones.
5545
const defaultStartDateTime = event?.startTime
56-
? toPlainDateTime(event.startTime)
46+
? timestampToPlainDateTime(event.startTime)
5747
: undefined;
5848
const defaultEndDateTime = event?.endTime
59-
? toPlainDateTime(event.endTime)
49+
? timestampToPlainDateTime(event.endTime)
6050
: undefined;
6151

6252
const handleStartDateChange = (value: Temporal.PlainDate) => {

app/web/features/communities/events/LongEventCard.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@ import { COMMUNITIES } from "i18n/namespaces";
1515
import Link from "next/link";
1616
import { Event } from "proto/events_pb";
1717
import { routeToEvent } from "routes";
18-
import {
19-
BROWSER_TIMEZONE,
20-
localizeDateTimeRange,
21-
timestamp2Date,
22-
} from "utils/date";
23-
import dayjs from "utils/dayjs";
18+
import { localizeDateTimeRange, timestampToPlainDateTime } from "utils/date";
2419

2520
const StyledCard = styled(Card)(({ theme }) => ({
2621
margin: 0,
@@ -137,11 +132,10 @@ const LongEventCard = ({
137132
} = useTranslation([COMMUNITIES]);
138133

139134
const dateTimeRangeText = localizeDateTimeRange(
140-
dayjs(timestamp2Date(event.startTime!)),
141-
dayjs(timestamp2Date(event.endTime!)),
135+
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
136+
timestampToPlainDateTime(event.startTime!),
137+
timestampToPlainDateTime(event.endTime!),
142138
{
143-
// TODO(#8064): Should use the event.timezone, but it's currently incorrect.
144-
timezone: BROWSER_TIMEZONE,
145139
locale,
146140
includeDayOfWeek: true,
147141
includeTime: true,

app/web/features/dashboard/DashboardPublicTripCard.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { useTranslation } from "i18n";
1313
import { DASHBOARD, PUBLIC_TRIPS } from "i18n/namespaces";
1414
import Link from "next/link";
1515
import { myPublicTripsRoute, routeToCommunity } from "routes";
16+
import { Temporal } from "temporal-polyfill";
1617
import { localizeDateTimeRange, localizeRelativeDays } from "utils/date";
1718
import dayjs from "utils/dayjs";
1819

@@ -202,8 +203,8 @@ export function DashboardPublicTripCard({
202203
);
203204

204205
const dateRange = localizeDateTimeRange(
205-
new Date(trip.fromDate + "T00:00:00"),
206-
new Date(trip.toDate + "T00:00:00"),
206+
Temporal.PlainDateTime.from(trip.fromDate),
207+
Temporal.PlainDateTime.from(trip.toDate),
207208
{ locale, includeTime: false, abbreviate: true },
208209
);
209210

0 commit comments

Comments
 (0)