| File: Commands\Test\MTP\Terminal\HumanReadableDurationFormatter.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; namespace Microsoft.DotNet.Cli.Commands.Test.Terminal; internal static class HumanReadableDurationFormatter { public static void Append(ITerminal terminal, TimeSpan duration, bool wrapInParentheses = true) { bool hasParentValue = false; if (wrapInParentheses) { terminal.Append('('); } // Duration abbreviations (d/h/m/s/ms) are intentionally NOT localized: // they use common time unit abbreviations and are kept identical across // cultures to match MSBuild Terminal Logger's behavior and the typical // convention for CLI tools (kubectl, cargo, etc.). This keeps timing // output easy to parse and consistent regardless of the active culture. if (duration.Days > 0) { terminal.Append($"{duration.Days}d"); hasParentValue = true; } if (duration.Hours > 0 || hasParentValue) { terminal.Append(GetFormattedPart(duration.Hours, hasParentValue, "h")); hasParentValue = true; } if (duration.Minutes > 0 || hasParentValue) { terminal.Append(GetFormattedPart(duration.Minutes, hasParentValue, "m")); hasParentValue = true; } if (duration.Seconds > 0 || hasParentValue) { terminal.Append(GetFormattedPart(duration.Seconds, hasParentValue, "s")); hasParentValue = true; } if (duration.Milliseconds >= 0 || hasParentValue) { terminal.Append(GetFormattedPart(duration.Milliseconds, hasParentValue, "ms", paddingWitdh: 3)); } if (wrapInParentheses) { terminal.Append(')'); } } private static string GetFormattedPart(int value, bool hasParentValue, string suffix, int paddingWitdh = 2) => $"{(hasParentValue ? " " : string.Empty)}{(hasParentValue ? value.ToString(CultureInfo.InvariantCulture).PadLeft(paddingWitdh, '0') : value.ToString(CultureInfo.InvariantCulture))}{suffix}"; public static string Render(TimeSpan? duration, bool wrapInParentheses = true, bool showMilliseconds = false) { if (duration is null) { return string.Empty; } bool hasParentValue = false; var stringBuilder = new StringBuilder(); if (wrapInParentheses) { stringBuilder.Append('('); } if (duration.Value.Days > 0) { stringBuilder.Append(CultureInfo.CurrentCulture, $"{duration.Value.Days}d"); hasParentValue = true; } if (duration.Value.Hours > 0 || hasParentValue) { stringBuilder.Append(GetFormattedPart(duration.Value.Hours, hasParentValue, "h")); hasParentValue = true; } if (duration.Value.Minutes > 0 || hasParentValue) { stringBuilder.Append(GetFormattedPart(duration.Value.Minutes, hasParentValue, "m")); hasParentValue = true; } if (duration.Value.Seconds > 0 || hasParentValue || !showMilliseconds) { stringBuilder.Append(GetFormattedPart(duration.Value.Seconds, hasParentValue, "s")); hasParentValue = true; } if (showMilliseconds) { if (duration.Value.Milliseconds >= 0 || hasParentValue) { stringBuilder.Append(GetFormattedPart(duration.Value.Milliseconds, hasParentValue, "ms", paddingWitdh: 3)); } } if (wrapInParentheses) { stringBuilder.Append(')'); } return stringBuilder.ToString(); } }