Skip to content

Commit

Permalink
feat(Duration): Stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
richardschneider committed May 12, 2018
1 parent 5328af0 commit 02ad8f0
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 2 deletions.
51 changes: 49 additions & 2 deletions src/Duration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ namespace Ipfs
/// </remarks>
public static class Duration
{
const double TicksPerNanosecond = (double)TimeSpan.TicksPerMillisecond * 0.000001;
const double TicksPerMicrosecond = (double)TimeSpan.TicksPerMillisecond * 0.001;

/// <summary>
/// Converts the string representation of an IPFS duration
/// into its <see cref="TimeSpan"/> equivalent.
Expand Down Expand Up @@ -83,9 +86,9 @@ static TimeSpan ParseComponent(StringReader reader)
return TimeSpan.FromMilliseconds(value);
case "us":
case "µs":
return TimeSpan.FromTicks((long)(value * (double)TimeSpan.TicksPerMillisecond * 0.001));
return TimeSpan.FromTicks((long)(value * TicksPerMicrosecond));
case "ns":
return TimeSpan.FromTicks((long)(value * (double)TimeSpan.TicksPerMillisecond * 0.000001));
return TimeSpan.FromTicks((long)(value * TicksPerNanosecond));
case "":
throw new FormatException("Missing IPFS duration unit.");
default:
Expand Down Expand Up @@ -123,5 +126,49 @@ static string ParseUnit(StringReader reader)

return s.ToString();
}

/// <summary>
/// Converts the <see cref="TimeSpan"/> to the equivalent string representation of an
/// IPFS duration.
/// </summary>
/// <param name="duration">
/// The <see cref="TimeSpan"/> to convert.
/// </param>
/// <param name="zeroValue">
/// The string representation, when the <paramref name="duration"/>
/// is equal to <see cref="TimeSpan.Zero"/>/
/// </param>
/// <returns>
/// The IPFS duration string representation.
/// </returns>
public static string Stringify(TimeSpan duration, string zeroValue = "0s")
{
if (duration.Ticks == 0)
return zeroValue;

var s = new StringBuilder();
if (duration.Ticks < 0)
{
s.Append('-');
duration = TimeSpan.FromTicks(-duration.Ticks);
}

Stringify(Math.Floor(duration.TotalHours), "h", s);
Stringify(duration.Minutes, "m", s);
Stringify(duration.Seconds, "s", s);
Stringify(duration.Milliseconds, "ms", s);
Stringify((long)((double)duration.Ticks / TicksPerMicrosecond) % 1000, "us", s);
Stringify((long)((double)duration.Ticks / TicksPerNanosecond) % 1000, "ns", s);

return s.ToString();
}

static void Stringify(double value, string unit, StringBuilder sb)
{
if (value == 0)
return;
sb.Append(value.ToString(CultureInfo.InvariantCulture));
sb.Append(unit);
}
}
}
22 changes: 22 additions & 0 deletions test/DurationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,28 @@ public void Parsing_InvalidUnit()
var _ = Duration.Parse("1jiffy");
}, "Unknown IPFS duration unit 'jiffy'.");
}

[TestMethod]
public void Stringify()
{
Assert.AreEqual("0s", Duration.Stringify(TimeSpan.Zero));
Assert.AreEqual("n/a", Duration.Stringify(TimeSpan.Zero, "n/a"));

Assert.AreEqual("2h", Duration.Stringify(new TimeSpan(2, 0, 0)));
Assert.AreEqual("3m", Duration.Stringify(new TimeSpan(0, 3, 0)));
Assert.AreEqual("4s", Duration.Stringify(new TimeSpan(0, 0, 4)));
Assert.AreEqual("5ms", Duration.Stringify(new TimeSpan(0, 0, 0, 0, 5)));
Assert.AreEqual("2h4s", Duration.Stringify(new TimeSpan(2, 0, 4)));
Assert.AreEqual("26h3m4s5ms", Duration.Stringify(new TimeSpan(1, 2, 3, 4, 5)));

Assert.AreEqual("-48h", Duration.Stringify(TimeSpan.FromDays(-2)));
Assert.AreEqual("-2h", Duration.Stringify(TimeSpan.FromHours(-2)));
Assert.AreEqual("-1h30m", Duration.Stringify(TimeSpan.FromHours(-1.5)));

Assert.AreEqual("200ns", Duration.Stringify(TimeSpan.FromTicks(2)));
Assert.AreEqual("200us", Duration.Stringify(TimeSpan.FromTicks(2000)));
Assert.AreEqual("200us300ns", Duration.Stringify(TimeSpan.FromTicks(2003)));
}
}
}

0 comments on commit 02ad8f0

Please sign in to comment.