Tuesday, July 30, 2019

C# Human Readable Ticks with microsecond and nanosecond units



Here's a great modern way to format C# ticks to be human readable number including micro and nanoseconds places. It uses StringBuilder (for speed) and Action delegate for string format variability. 




This implementation will leave out zero units parts.  Say that microseconds is 0, it will not print 0µs place to save space of output string.

  

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System; using System.Text; 
using System.Diagnostics; 
     
public static class Program
{
 /// <summary>
 ///  Human readable elapsed time Ticks using modern Action delegate, leaving out zero parts and variable length formating
 /// </summary>
 /// <param name="ticks">a long type</param>
 /// <returns>Human readable units place for microseconds & nanoseconds</returns>
 public static string HumanReadableTicks(this long ticks)
 {
  if (ticks == 0) return "0 ns"; 

  StringBuilder sb = new StringBuilder(); 
  
  Action<long, StringBuilder, int> addActionToSB = 
  (val, displayunit, zeroplaces) => 
  {if (val > 0) 
   sb.AppendFormat(
     " {0:DZ}X".Replace("X", displayunit.ToString())
     .Replace("Z",zeroplaces.ToString())        
     ,val
    ); 
  };

  var t = TimeSpan.FromTicks(ticks); 
  
  //addActionToSringBuilderList(timespan property, readable display displayunit, number of 0 placeholders) //Tue 30-Jul-19 11:13am metadataconsulting.ca
  addActionToSB((long)t.Days, new StringBuilder("d"),  1);
  addActionToSB((long)t.Hours, new StringBuilder("h"), 1);
  addActionToSB((long)t.Minutes, new StringBuilder("m"), 1);
  addActionToSB((long)t.Seconds, new StringBuilder("s"), 1);
  addActionToSB((long)t.Milliseconds, new StringBuilder("ms"), 3); //set milliseconds to 3 numbers 
  addActionToSB((long)Convert.ToUInt64((int)((t.TotalMilliseconds - (int)t.TotalMilliseconds) * 1000)), new StringBuilder("µs"), 3); //TotalMilliseconds is a double and has enough decimal places for accuracy here
  addActionToSB((long)Convert.ToUInt64((((decimal)(t.Ticks * 100) % 1000) )), new StringBuilder("ns"), 3); //1 tick is one hundred nanoseconds. get thousands place

  return sb.ToString().TrimStart();
 }
 
 public static void Main()
 {
   Stopwatch sw = new Stopwatch();
   Console.WriteLine("HumanReadableTimeSpan ran for"); 
   sw.Start();
   System.Threading.Thread.Sleep(1345);
   sw.Stop();
   Console.WriteLine(sw.ElapsedTicks*100 + " nanoseconds (ns)."); 
   Console.WriteLine(sw.ElapsedTicks.HumanReadableTicks()); 
 }
}

No comments:

Post a Comment