Skip to content
Browse files

Add TimeSpanUtility.

  • Loading branch information...
1 parent 8713aee commit 20eee061f38ecc6f76f0c79416cbb6375624d36f @bgrainger bgrainger committed Mar 19, 2013
View
1 src/Logos.Utility/Logos.Utility.csproj
@@ -96,6 +96,7 @@
<Compile Include="Threading\TaskCompletionSourceUtility.cs" />
<Compile Include="Threading\TaskUtility.cs" />
<Compile Include="Threading\ThreadUtility.cs" />
+ <Compile Include="TimeSpanUtility.cs" />
<Compile Include="Win32.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
View
35 src/Logos.Utility/TimeSpanUtility.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace Logos.Utility
+{
+ /// <summary>
+ /// Helper methods for working with <see cref="TimeSpan"/>.
+ /// </summary>
+ public static class TimeSpanUtility
+ {
+ /// <summary>
+ /// Formats <paramref name="ts"/> as a concise string suitable for logging; the precision of the returned
+ /// string (which is not culture-sensitive) depends on the duration of the <see cref="TimeSpan"/>.
+ /// </summary>
+ /// <param name="ts">The TimeSpan to render.</param>
+ /// <returns>A culture-invariant string with a concise rendering of the TimeSpan.</returns>
+ public static string FormatForLogging(TimeSpan ts)
+ {
+ if (ts.Ticks < 0)
+ throw new ArgumentOutOfRangeException("ts", "The TimeSpan must have a positive duration.");
+
+ // log the timespan in the most appropriate format for the actual duration
+ double seconds = ts.Seconds + ts.Milliseconds / 1000.0;
+ if (ts.TotalSeconds < 10)
+ return "{0}ms".FormatInvariant((int) (ts.TotalMilliseconds + 0.5));
+ else if (ts.TotalMinutes < 1)
+ return "{0:0.00}s".FormatInvariant(Math.Min(seconds, 59.99));
+ else if (ts.TotalHours < 1)
+ return "{0}m {1:0.0}s".FormatInvariant(ts.Minutes, Math.Min(seconds, 59.9));
+ else if (ts.TotalDays < 1)
+ return "{0}h {1}m {2:0}s".FormatInvariant((int) ts.TotalHours, ts.Minutes, Math.Min(seconds, 59));
+ else
+ return "{0}d {1}h {2}m {3:0}s".FormatInvariant((int) ts.TotalDays, ts.Hours, ts.Minutes, Math.Min(seconds, 59));
+ }
+ }
+}
View
1 tests/Logos.Utility.Tests/Logos.Utility.Tests.csproj
@@ -78,6 +78,7 @@
<Compile Include="Salsa20Tests.cs" />
<Compile Include="ScopeTests.cs" />
<Compile Include="StreamUtilityTests.cs" />
+ <Compile Include="TimeSpanUtilityTests.cs" />
<Compile Include="WrappingStreamTests.cs" />
</ItemGroup>
<ItemGroup>
View
48 tests/Logos.Utility.Tests/TimeSpanUtilityTests.cs
@@ -0,0 +1,48 @@
+using System;
+using NUnit.Framework;
+
+namespace Logos.Utility.Tests
+{
+ [TestFixture]
+ public class TimeSpanUtilityTests
+ {
+ [TestCase(0, "0ms")]
+ [TestCase(1, "1ms")]
+ [TestCase(1234, "1234ms")]
+ [TestCase(9999, "9999ms")]
+ [TestCase(10000, "10.00s")]
+ [TestCase(10004, "10.00s")]
+ [TestCase(10005, "10.01s")]
+ [TestCase(59990, "59.99s")]
+ [TestCase(59999, "59.99s")]
+ [TestCase(60000, "1m 0.0s")]
+ [TestCase(61000, "1m 1.0s")]
+ [TestCase(61049, "1m 1.0s")]
+ [TestCase(61050, "1m 1.1s")]
+ [TestCase(3599000, "59m 59.0s")]
+ [TestCase(3599850, "59m 59.9s")]
+ [TestCase(3599900, "59m 59.9s")]
+ [TestCase(3599950, "59m 59.9s")]
+ [TestCase(86398500, "23h 59m 59s")]
+ [TestCase(86399000, "23h 59m 59s")]
+ [TestCase(86399500, "23h 59m 59s")]
+ [TestCase(86400000, "1d 0h 0m 0s")]
+ [TestCase(1121685567, "12d 23h 34m 46s")]
+ public void FormatForLogging(int ms, string expected)
+ {
+ Assert.AreEqual(expected, TimeSpanUtility.FormatForLogging(TimeSpan.FromMilliseconds(ms)));
+ }
+
+ [Test]
+ public void RoundUp()
+ {
+ Assert.AreEqual("1ms", TimeSpanUtility.FormatForLogging(TimeSpan.FromMilliseconds(0.5)));
+ }
+
+ [Test]
+ public void NegativeTimeSpan()
+ {
+ Assert.Throws<ArgumentOutOfRangeException>(() => TimeSpanUtility.FormatForLogging(TimeSpan.FromMinutes(-1)));
+ }
+ }
+}

0 comments on commit 20eee06

Please sign in to comment.
Something went wrong with that request. Please try again.