Skip to content

Commit 88e163c

Browse files
committed
Merge commit 'ddf906756a638175410aa06997f138a1acb75404' into pr-7679-xplat-ci
2 parents cc0185f + ddf9067 commit 88e163c

2 files changed

Lines changed: 44 additions & 12 deletions

File tree

studio/frontend/src/features/hub/lib/format.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
// SPDX-License-Identifier: AGPL-3.0-only
22
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
33

4+
const SECONDS_PER_MINUTE = 60;
5+
const MINUTES_PER_HOUR = 60;
6+
const HOURS_PER_DAY = 24;
7+
const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
8+
const MAX_DISPLAYABLE_ETA_SECONDS = HOURS_PER_DAY * SECONDS_PER_HOUR;
9+
410
export function formatBytes(bytes: number): string {
511
if (!Number.isFinite(bytes) || bytes < 0) return "N/A";
612
if (bytes === 0) return "0 B";
@@ -27,20 +33,16 @@ export function formatRate(bytesPerSec: number): string {
2733
export function formatEta(seconds: number): string {
2834
if (!Number.isFinite(seconds) || seconds <= 0) return "";
2935
const s = Math.round(seconds);
30-
if (s < 60) return `${s}s left`;
31-
if (s < 3600) {
32-
const m = Math.floor(s / 60);
33-
const rem = s % 60;
36+
if (s >= MAX_DISPLAYABLE_ETA_SECONDS) return "";
37+
if (s < SECONDS_PER_MINUTE) return `${s}s left`;
38+
if (s < SECONDS_PER_HOUR) {
39+
const m = Math.floor(s / SECONDS_PER_MINUTE);
40+
const rem = s % SECONDS_PER_MINUTE;
3441
return rem ? `${m}m ${rem}s left` : `${m}m left`;
3542
}
36-
if (s < 86400) {
37-
const h = Math.floor(s / 3600);
38-
const rem = Math.floor((s % 3600) / 60);
39-
return rem ? `${h}h ${rem}m left` : `${h}h left`;
40-
}
41-
const d = Math.floor(s / 86400);
42-
const rem = Math.floor((s % 86400) / 3600);
43-
return rem ? `${d}d ${rem}h left` : `${d}d left`;
43+
const h = Math.floor(s / SECONDS_PER_HOUR);
44+
const rem = Math.floor((s % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
45+
return rem ? `${h}h ${rem}m left` : `${h}h left`;
4446
}
4547

4648
export function ownerOf(id: string): string {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
3+
4+
import assert from "node:assert/strict";
5+
import test from "node:test";
6+
7+
import { formatEta } from "../src/features/hub/lib/format.ts";
8+
9+
const SECONDS_PER_MINUTE = 60;
10+
const MINUTES_PER_HOUR = 60;
11+
const HOURS_PER_DAY = 24;
12+
const REPRO_ETA_DAYS = 753;
13+
const REPRO_ETA_HOURS = 5;
14+
const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
15+
const MAX_DISPLAYABLE_ETA_SECONDS = HOURS_PER_DAY * SECONDS_PER_HOUR;
16+
const REPRO_ETA_SECONDS =
17+
(REPRO_ETA_DAYS * HOURS_PER_DAY + REPRO_ETA_HOURS) * SECONDS_PER_HOUR;
18+
19+
test("download ETA hides estimates that are too uncertain to be useful", () => {
20+
assert.equal(formatEta(Number.NaN), "");
21+
assert.equal(formatEta(0), "");
22+
assert.equal(formatEta(SECONDS_PER_MINUTE - 1), "59s left");
23+
assert.equal(formatEta(SECONDS_PER_MINUTE), "1m left");
24+
assert.equal(formatEta(SECONDS_PER_MINUTE + 1), "1m 1s left");
25+
assert.equal(formatEta(SECONDS_PER_HOUR), "1h left");
26+
assert.equal(formatEta(SECONDS_PER_HOUR + SECONDS_PER_MINUTE), "1h 1m left");
27+
assert.equal(formatEta(REPRO_ETA_SECONDS), "");
28+
assert.equal(formatEta(MAX_DISPLAYABLE_ETA_SECONDS - 1), "23h 59m left");
29+
assert.equal(formatEta(MAX_DISPLAYABLE_ETA_SECONDS), "");
30+
});

0 commit comments

Comments
 (0)