Last Updated: February 25, 2016
·
3.905K
· teddy

C# UNIX Timestamp Creation

For years, I had been creating timestamps in C# using Ticks, which is uses such large numbers that it is absolutely impossible to remember. A tick is 100 nanoseconds and the large number is used to convert the minimum DateTime value to the start of the Unix Timestamp.

(EV_Epoch.Ticks - 621355968000000000) / 10000000

Then I discovered a wonderful thing, DateTime.Subtract, which made creating timestamps a lot easier. It's simple to remember that the beginning of the Unix timestamp was 1/1/1970 and retrieve the TotalSeconds offset between the DateTimes.

EV_Epoch.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds

I wanted to make sure I wasn't adding superfluous strain on the system by instantiating an extra DateTime struct because I was too lazy to dig up the ticks values I couldn't remember.
It turns out the impact is minimal. Yes, it takes over 2.5x as long to use the new DateTime method, but it's on the nanosecond level. For development, and even production where this is not continuously run, the switch to ticks is not entirely necessary.

Results:

Number of seconds since the start of the EV Epoch, Ticks method: 1308823200
Number of seconds since the start of the EV Epoch, new DateTime method: 1308823200


Results for 1000000000 trials

Method      Total Time [ms]     Avg Time [ms]
Ticks       16219           1.6219E-05
DateTime    42282           4.2282E-05

Test method:

public static void timestampSpeeds()
{
    //determine the best way to create a unix timestamp

    //set the number of trials to run
    int trials = 1000000000;
    DateTime EV_Epoch = new DateTime(2011, 6, 23, 10, 0, 0, DateTimeKind.Utc);

    //start the stopwatch and begin making timestamps
    double sec;
    Stopwatch sw_ticks = Stopwatch.StartNew();
    for (int i = 0; i < trials; i++)
        sec = (EV_Epoch.Ticks - 621355968000000000) / 10000000;
    sw_ticks.Stop();


    Stopwatch sw_datetime = Stopwatch.StartNew();
    for (int i = 0; i < trials; i++)
        sec = EV_Epoch.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
    sw_datetime.Stop();


    //do some diagnostics stuff
    using (StreamWriter writer = new StreamWriter(string.Format("Ticks_vs_New_DateTime_{0}.txt", trials)))
    {
        writer.WriteLine(string.Format("Number of seconds since the start of the EV Epoch, Ticks method: {0}", (EV_Epoch.Ticks - 621355968000000000) / 10000000));
        writer.WriteLine(string.Format("Number of seconds since the start of the EV Epoch, new DateTime method: {0}", (int)EV_Epoch.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds));
        writer.WriteLine(string.Format("\r\n\r\nResults for {0} trials", trials));
        writer.WriteLine("\r\nMethod\t\tTotal Time [ms]\t\tAvg Time [ms]");
        writer.WriteLine(string.Format("Ticks\t\t{0}\t\t\t{1}", sw_ticks.ElapsedMilliseconds, (sw_ticks.ElapsedMilliseconds / (double)trials)));
        writer.WriteLine(string.Format("DateTime\t{0}\t\t\t{1}", sw_datetime.ElapsedMilliseconds, (sw_datetime.ElapsedMilliseconds / (double)trials)));
    }
}