8000 chore: replace date-fns by dayjs by BrunoQuaresma · Pull Request #18022 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

chore: replace date-fns by dayjs #18022

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

Merged
merged 8 commits into from
May 25, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
15 changes: 7 additions & 8 deletions site/e2e/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import type { Page } from "@playwright/test";
import { expect } from "@playwright/test";
import { API, type DeploymentConfig } from "api/api";
import type { SerpentOption } from "api/typesGenerated";
import { formatDuration, intervalToDuration } from "date-fns";
import dayjs from "dayjs";
import duration from "dayjs/plugin/duration";
import relativeTime from "dayjs/plugin/relativeTime";

dayjs.extend(duration);
dayjs.extend(relativeTime);
import { coderPort, defaultPassword } from "./constants";
import { type LoginOptions, findSessionToken, randomName } from "./helpers";

Expand Down Expand Up @@ -295,13 +300,7 @@ export async function verifyConfigFlagDuration(
);
//
await expect(configOption).toHaveText(
formatDuration(
// intervalToDuration takes ms, so convert nanoseconds to ms
intervalToDuration({
start: 0,
end: (opt.value as number) / 1e6,
}),
),
dayjs.duration((opt.value as number) / 1e6).humanize(),
);
}

Expand Down
1 change: 0 additions & 1 deletion site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
"color-convert": "2.0.1",
"cron-parser": "4.9.0",
"cronstrue": "2.50.0",
"date-fns": "2.30.0",
"dayjs": "1.11.13",
"emoji-mart": "5.6.0",
"file-saver": "2.0.5",
Expand Down
3 changes: 0 additions & 3 deletions site/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 11 additions & 9 deletions site/src/components/LastSeen/LastSeen.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { useTheme } from "@emotion/react";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import type { FC, HTMLAttributes } from "react";
import { cn } from "utils/cn";

dayjs.extend(relativeTime);
import { isAfter, relativeTime, subtractTime } from "utils/time";

interface LastSeenProps
extends Omit<HTMLAttributes<HTMLSpanElement>, "children"> {
Expand All @@ -15,21 +13,25 @@ interface LastSeenProps
export const LastSeen: FC<LastSeenProps> = ({ at, className, ...attrs }) => {
const theme = useTheme();
const t = dayjs(at);
const now = dayjs();
const now = new Date();
E864 const oneHourAgo = subtractTime(now, 1, "hour");
const threeDaysAgo = subtractTime(now, 3, "day");
const oneMonthAgo = subtractTime(now, 1, "month");
const centuryAgo = subtractTime(now, 100, "year");

let message = t.fromNow();
let message = relativeTime(at);
let color = theme.palette.text.secondary;

if (t.isAfter(now.subtract(1, "hour"))) {
if (isAfter(at, oneHourAgo)) {
// Since the agent reports on a 10m interval,
// the last_used_at can be inaccurate when recent.
message = "Now";
color = theme.roles.success.fill.solid;
} else if (t.isAfter(now.subtract(3, "day"))) {
} else if (isAfter(at, threeDaysAgo)) {
color = theme.experimental.l2.text;
} else if (t.isAfter(now.subtract(1, "month"))) {
} else if (isAfter(at, oneMonthAgo)) {
color = theme.roles.warning.fill.solid;
} else if (t.isAfter(now.subtract(100, "year"))) {
} else if (isAfter(at, centuryAgo)) {
color = theme.roles.error.fill.solid;
} else {
message = "Never";
Expand Down
15 changes: 11 additions & 4 deletions site/src/components/Timeline/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import formatRelative from "date-fns/formatRelative";
import subDays from "date-fns/subDays";
import dayjs from "dayjs";
import calendar from "dayjs/plugin/calendar";

dayjs.extend(calendar);

export const createDisplayDate = (
date: Date,
base: Date = new Date(),
): string => {
const lastWeek = subDays(base, 7);
const lastWeek = dayjs(base).subtract(7, "day").toDate();
if (date >= lastWeek) {
return formatRelative(date, base).split(" at ")[0];
return dayjs(date).calendar(dayjs(base), {
sameDay: "[Today]",
lastDay: "[Yesterday]",
lastWeek: "[last] dddd",
sameElse: "MM/DD/YYYY",
});
}
return date.toLocaleDateString();
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import Tooltip from "@mui/material/Tooltip";
import type { Workspace } from "api/typesGenerated";
import { Badge } from "components/Badge/Badge";
import { formatDistanceToNow } from "date-fns";
import type { FC } from "react";
import {
DATE_FORMAT,
formatDateTime,
relativeTimeWithoutSuffix,
} from "utils/time";

export type WorkspaceDormantBadgeProps = {
workspace: Workspace;
Expand All @@ -11,25 +15,14 @@ export type WorkspaceDormantBadgeProps = {
export const Wor F438 kspaceDormantBadge: FC<WorkspaceDormantBadgeProps> = ({
workspace,
}) => {
const formatDate = (dateStr: string): string => {
const date = new Date(dateStr);
return date.toLocaleDateString(undefined, {
month: "long",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
});
};

return workspace.deleting_at ? (
<Tooltip
title={
<>
This workspace has not been used for{" "}
{formatDistanceToNow(Date.parse(workspace.last_used_at))} and has been
{relativeTimeWithoutSuffix(workspace.last_used_at)} and has been
marked dormant. It is scheduled to be deleted on{" "}
{formatDate(workspace.deleting_at)}.
{formatDateTime(workspace.deleting_at, DATE_FORMAT.FULL_DATETIME)}.
</>
}
>
Expand All @@ -42,7 +35,7 @@ export const WorkspaceDormantBadge: FC<WorkspaceDormantBadgeProps> = ({
title={
<>
This workspace has not been used for{" "}
{formatDistanceToNow(Date.parse(workspace.last_used_at))} and has been
{relativeTimeWithoutSuffix(workspace.last_used_at)} and has been
marked dormant. It is not scheduled for auto-deletion but will become
a candidate if auto-deletion is enabled on this template.
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { GetLicensesResponse } from "api/api";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Pill } from "components/Pill/Pill";
import { Stack } from "components/Stack/Stack";
import { compareAsc } from "date-fns";
import dayjs from "dayjs";
import { type FC, useState } from "react";

Expand Down Expand Up @@ -92,10 +91,7 @@ export const LicenseCard: FC<LicenseCardProps> = ({
alignItems="center"
width="134px" // standardize width of date column
>
{compareAsc(
new Date(license.claims.license_expires * 1000),
new Date(),
) < 1 ? (
{dayjs(license.claims.license_expires * 1000).isBefore(dayjs()) ? (
<Pill css={styles.expiredBadge} type="error">
Expired
</Pill>
Expand Down
10 changes: 2 additions & 8 deletions site/src/pages/DeploymentSettingsPage/optionValue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SerpentOption } from "api/typesGenerated";
import { formatDuration, intervalToDuration } from "date-fns";
import { humanDuration } from "utils/time";

// optionValue is a helper function to format the value of a specific deployment options
export function optionValue(
Expand All @@ -14,13 +14,7 @@ export function optionValue(
}
switch (k) {
case "format_duration":
return formatDuration(
// intervalToDuration takes ms, so convert nanoseconds to ms
intervalToDuration({
start: 0,
end: (option.value as number) / 1e6,
}),
);
return humanDuration((option.value as number) / 1e6);
// Add additional cases here as needed.
}
}
Expand Down
32 changes: 12 additions & 20 deletions site/src/pages/TemplatePage/TemplateInsightsPage/DateRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@ import {
PopoverContent,
PopoverTrigger,
} from "components/deprecated/Popover/Popover";
import {
addDays,
addHours,
format,
isToday,
startOfDay,
startOfHour,
subDays,
} from "date-fns";
import dayjs from "dayjs";
import { MoveRightIcon } from "lucide-react";
import { type ComponentProps, type FC, useRef, useState } from "react";
import { DateRangePicker, createStaticRanges } from "react-date-range";
Expand Down Expand Up @@ -55,9 +47,9 @@ export const DateRange: FC<DateRangeProps> = ({ value, onChange }) => {
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger>
<Button variant="outline">
<span>{format(value.startDate, "MMM d, Y")}</span>
<span>{dayjs(value.startDate).format("MMM D, YYYY")}</span>
<MoveRightIcon />
<span>{format(value.endDate, "MMM d, Y")}</span>
<span>{dayjs(value.endDate).format("MMM D, YYYY")}</span>
</Button>
</PopoverTrigger>
<PopoverContent>
Expand All @@ -79,10 +71,10 @@ export const DateRange: FC<DateRangeProps> = ({ value, onChange }) => {
const endDate = range.endDate as Date;
const now = new Date();
onChange({
startDate: startOfDay(startDate),
endDate: isToday(endDate)
? startOfHour(addHours(now, 1))
: startOfDay(addDays(endDate, 1)),
startDate: dayjs(startDate).startOf("day").toDate(),
endDate: dayjs(endDate).isSame(dayjs(), "day")
? dayjs(now).startOf("hour").add(1, "hour").toDate()
: dayjs(endDate).startOf("day").add(1, "day").toDate(),
});
setOpen(false);
}}
Expand All @@ -102,28 +94,28 @@ export const DateRange: FC<DateRangeProps> = ({ value, onChange }) => {
{
label: "Yesterday",
range: () => ({
startDate: subDays(new Date(), 1),
endDate: subDays(new Date(), 1),
startDate: dayjs().subtract(1, "day").toDate(),
endDate: dayjs().subtract(1, "day").toDate(),
}),
},
{
label: "Last 7 days",
range: () => ({
startDate: subDays(new Date(), 6),
startDate: dayjs().subtract(6, "day").toDate(),
endDate: new Date(),
}),
},
{
label: "Last 14 days",
range: () => ({
startDate: subDays(new Date(), 13),
startDate: dayjs().subtract(13, "day").toDate(),
endDate: new Date(),
}),
},
{
label: "Last 30 days",
range: () => ({
startDate: subDays(new Date(), 29),
startDate: dayjs().subtract(29, "day").toDate(),
endDate: new Date(),
}),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ import {
} from "components/HelpTooltip/HelpTooltip";
import { Loader } from "components/Loader/Loader";
import { Stack } from "components/Stack/Stack";
import {
addHours,
addWeeks,
format,
startOfDay,
startOfHour,
subDays,
} from "date-fns";
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
import { CircleCheck as CircleCheckIcon } from "lucide-react";
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
Expand All @@ -57,6 +49,13 @@ import { Helmet } from "react-helmet-async";
import { useQuery } from "react-query";
import { useSearchParams } from "react-router-dom";
import { getLatencyColor } from "utils/latency";
import {
addTime,
formatDateTime,
startOfDay,
startOfHour,
subtractTime,
} from "utils/time" 57AE ;;
import { getTemplatePageTitle } from "../utils";
import { DateRange as DailyPicker, type DateRangeValue } from "./DateRange";
import { type InsightsInterval, IntervalMenu } from "./IntervalMenu";
Expand Down Expand Up @@ -138,7 +137,7 @@ export default function TemplateInsightsPage() {
const getDefaultInterval = (template: Template) => {
const now = new Date();
const templateCreateDate = new Date(template.created_at);
const hasFiveWeeksOrMore = addWeeks(templateCreateDate, 5) < now;
const hasFiveWeeksOrMore = addTime(templateCreateDate, 5, "week") < now;
return hasFiveWeeksOrMore ? "week" : "day";
};

Expand All @@ -162,9 +161,9 @@ const getDateRange = (
// instantiation.
const today = new Date();
return {
startDate: startOfDay(subDays(today, 6)),
startDate: startOfDay(subtractTime(today, 6, "day")),
// Add one hour to endDate to include real-time data for today.
endDate: addHours(startOfHour(today), 1),
endDate: addTime(startOfHour(today), 1, "hour"),
};
}

Expand Down Expand Up @@ -910,7 +909,7 @@ function formatTime(seconds: number): string {
}

function toISOLocal(d: Date, offset: number) {
return format(d, `yyyy-MM-dd'T'HH:mm:ss${formatOffset(offset)}`);
return formatDateTime(d, `YYYY-MM-DD[T]HH:mm:ss${formatOffset(offset)}`);
}

function formatOffset(offset: number): string {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Button from "@mui/material/Button";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import { differenceInWeeks } from "date-fns";
import dayjs from "dayjs";
import { ChevronDownIcon } from "lucide-react";
import { CheckIcon } from "lucide-react";
import { type FC, useRef, useState } from "react";
Expand All @@ -20,7 +20,10 @@ interface WeekPickerProps {
export const WeekPicker: FC<WeekPickerProps> = ({ value, onChange }) => {
const anchorRef = useRef<HTMLButtonElement>(null);
const [open, setOpen] = useState(false);
const numberOfWeeks = differenceInWeeks(value.endDate, value.startDate);
const numberOfWeeks = dayjs(value.endDate).diff(
dayjs(value.startDate),
"week",
);

const handleClose = () => {
setOpen(false);
Expand Down
6 changes: 3 additions & 3 deletions site/src/pages/TemplatePage/TemplateInsightsPage/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { startOfDay, subDays } from "date-fns";
import { startOfDay, subtractTime } from "utils/time";

export const lastWeeks = (numberOfWeeks: number) => {
const now = new Date();
const endDate = startOfDay(subDays(now, 1));
const startDate = startOfDay(subDays(endDate, 7 * numberOfWeeks));
const endDate = subtractTime(startOfDay(now), 1, "day");
const startDate = subtractTime(endDate, 7 * numberOfWeeks, "day");
return { startDate, endDate };
};
Loading
Loading
0