Pergunta

How do you convert Unix epoch time into real time in C#? (Epoch beginning 1/1/1970)

Foi útil?

Solução

I presume that you mean Unix time, which is defined as the number of seconds since midnight (UTC) on 1st January 1970.

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

Outras dicas

The latest version of .Net (v4.6) just added built-in support for Unix time conversions. That includes both to and from Unix time represented by either seconds or milliseconds.

  • Unix time in seconds to DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset to Unix time in seconds:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Unix time in milliseconds to DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset to Unix time in milliseconds:

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();

Note: These methods convert to and from DateTimeOffset. To get a DateTime representation simply use the DateTimeOffset.DateTime property:

DateTime dateTime = dateTimeOffset.UtcDateTime;

With all credit to LukeH, I've put together some extension methods for easy use:

public static DateTime FromUnixTime(this long unixTime)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return epoch.AddSeconds(unixTime);
}

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date - epoch).TotalSeconds);
}

Note the comment below from CodesInChaos that the above FromUnixTime returns a DateTime with a Kind of Utc, which is fine, but the above ToUnixTime is much more suspect in that doesn't account for what kind of DateTime the given date is. To allow for date's Kind being either Utc or Local, use ToUniversalTime:

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

ToUniversalTime will convert a Local (or Unspecified) DateTime to Utc.

if you dont want to create the epoch DateTime instance when moving from DateTime to epoch you can also do:

public static long ToUnixTime(this DateTime date)
{
    return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}

You actually want to AddMilliseconds(milliseconds), not seconds. Adding seconds will give you an out of range exception.

If you want better performance you can use this version.

public const long UnixEpochTicks = 621355968000000000;
public const long TicksPerMillisecond = 10000;
public const long TicksPerSecond = TicksPerMillisecond * 1000;

//[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DateTime FromUnixTimestamp(this long unixTime)
{
    return new DateTime(UnixEpochTicks + unixTime * TicksPerSecond);
}

From a quick benchmark (BenchmarkDotNet) under net471 I get this number:

        Method |     Mean |     Error |    StdDev | Scaled |
-------------- |---------:|----------:|----------:|-------:|
         LukeH | 5.897 ns | 0.0897 ns | 0.0795 ns |   1.00 |
      MyCustom | 3.176 ns | 0.0573 ns | 0.0536 ns |   0.54 |

2x faster against LukeH's version (if the performance mater)

This is similar to how DateTime internally work.

// convert datetime to unix epoch seconds
public static long ToUnixTime(DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

Should use ToUniversalTime() for the DateTime object.

I use following extension methods for epoch conversion

public static int GetEpochSeconds(this DateTime date)
    {
        TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
        return (int)t.TotalSeconds;
    }

public static DateTime FromEpochSeconds(this DateTime date, long EpochSeconds)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(EpochSeconds);

    }

Use the method DateTimeOffset.ToUnixTimeMilliseconds() It returns the number of milliseconds that have elapsed since 1970-01-01T00:00:00.000Z.

This is only supported with Framework 4.6 or higher

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

It's well documented here DateTimeOffset.ToUnixTimeMilliseconds

The other way out is to use the following

long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;

To get the EPOCH with seconds only you may use

 var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

and convert the Epoch to DateTime with the following method

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}

If you are not using 4.6, this may help Source: System.IdentityModel.Tokens

    /// <summary>
    /// DateTime as UTV for UnixEpoch
    /// </summary>
    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// Per JWT spec:
    /// Gets the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the desired date/time.
    /// </summary>
    /// <param name="datetime">The DateTime to convert to seconds.</param>
    /// <remarks>if dateTimeUtc less than UnixEpoch, return 0</remarks>
    /// <returns>the number of seconds since Unix Epoch.</returns>
    public static long GetIntDate(DateTime datetime)
    {
        DateTime dateTimeUtc = datetime;
        if (datetime.Kind != DateTimeKind.Utc)
        {
            dateTimeUtc = datetime.ToUniversalTime();
        }

        if (dateTimeUtc.ToUniversalTime() <= UnixEpoch)
        {
            return 0;
        }

        return (long)(dateTimeUtc - UnixEpoch).TotalSeconds;
    }    

In case you need to convert a timeval struct (seconds, microseconds) containing UNIX time to DateTime without losing precision, this is how:

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private DateTime UnixTimeToDateTime(Timeval unixTime)
{
    return _epochTime.AddTicks(
        unixTime.Seconds * TimeSpan.TicksPerSecond +
        unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000);
}

Here is my solution:

public long GetTime()
{
    DateTime dtCurTime = DateTime.Now.ToUniversalTime();

    DateTime dtEpochStartTime = Convert.ToDateTime("1/1/1970 0:00:00 AM");

    TimeSpan ts = dtCurTime.Subtract(dtEpochStartTime);

    double epochtime;

    epochtime = ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds);   

    return Convert.ToInt64(epochtime);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top