diff --git a/src/OpenClaw.Shared/Models.cs b/src/OpenClaw.Shared/Models.cs index 15b1afb..44de5db 100644 --- a/src/OpenClaw.Shared/Models.cs +++ b/src/OpenClaw.Shared/Models.cs @@ -441,9 +441,9 @@ internal static class ModelFormatting { var delta = DateTime.UtcNow - timestampUtc; if (delta.TotalSeconds < 60) return "just now"; - if (delta.TotalMinutes < 60) return $"{(int)Math.Round(delta.TotalMinutes)}m ago"; - if (delta.TotalHours < 48) return $"{(int)Math.Round(delta.TotalHours)}h ago"; - return $"{(int)Math.Round(delta.TotalDays)}d ago"; + if (delta.TotalMinutes < 60) return $"{(int)delta.TotalMinutes}m ago"; + if (delta.TotalHours < 48) return $"{(int)delta.TotalHours}h ago"; + return $"{(int)delta.TotalDays}d ago"; } /// diff --git a/tests/OpenClaw.Shared.Tests/ModelsTests.cs b/tests/OpenClaw.Shared.Tests/ModelsTests.cs index 3b5c68b..03b300f 100644 --- a/tests/OpenClaw.Shared.Tests/ModelsTests.cs +++ b/tests/OpenClaw.Shared.Tests/ModelsTests.cs @@ -762,6 +762,31 @@ public class SessionInfoAgeTextTests }; Assert.Equal("10m ago", session.AgeText); } + + [Fact] + public void AgeText_NearMinuteBoundary_DoesNotRoundUpTo60m() + { + // 59.5 minutes: Math.Round would produce 60 with banker's rounding; + // truncation correctly yields 59m ago. + var session = new SessionInfo { UpdatedAt = DateTime.UtcNow.AddSeconds(-3570) }; // 59.5 min + Assert.Equal("59m ago", session.AgeText); + } + + [Fact] + public void AgeText_NearHourBoundary_DoesNotRoundUpTo48h() + { + // 47.5 hours: Math.Round would produce 48 with banker's rounding; + // truncation correctly yields 47h ago. + var session = new SessionInfo { UpdatedAt = DateTime.UtcNow.AddSeconds(-(int)(47.5 * 3600)) }; + Assert.Equal("47h ago", session.AgeText); + } + + [Fact] + public void AgeText_ExactlyOneMinute_ShowsMinutesAgo() + { + var session = new SessionInfo { UpdatedAt = DateTime.UtcNow.AddSeconds(-60) }; + Assert.Equal("1m ago", session.AgeText); + } } public class SessionInfoRichDisplayTextTests