开发者

How do you convert epoch time in C#?

How do you convert Unix epoch time into real time开发者_如何学Go in C#? (Epoch beginning 1/1/1970)


UPDATE 2020

You can do this with DateTimeOffset

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(epochSeconds);
DateTimeOffset dateTimeOffset2 = DateTimeOffset.FromUnixTimeMilliseconds(epochMilliseconds);

And if you need the DateTime object instead of DateTimeOffset, then you can call the DateTime property

DateTime dateTime = dateTimeOffset.DateTime;

Original answer

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

private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}


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.


The Unix epoch is the number of seconds that have elapsed since January 1, 1970 at midnight UTC time minus the leap seconds. This means that at midnight of January 1, 1970, Unix time was 0. The Unix epoch is also called Unix time, POSIX time, or Unix timestamp.

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

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

It's well documented here DateTimeOffset.ToUnixTimeMilliseconds

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); 
}

But Since

On systems where the representation of Unix time is as a signed 32-bit number, the representation will end after 231 - 1 seconds which will happen at 3:14:08 on 19 January 2038 UTC. This is called the Year 2038 problem where the 32-bit signed Unix time will overflow.

I suggest to save it as long not int as EPOCH_2038_SAFE

long EPOCH_2038_SAFE = 
(long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

If you are looking for more, use the following with more ticks precision

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


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.


currently you can simply use

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

it will be returned as a 64-bits long


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);

    }


Since .Net 4.6 and above please use

DateTimeOffset.Now.ToUnixTimeSeconds()


To not worry about using milliseconds or seconds just do:

    public static DateTime _ToDateTime(this long unixEpochTime)
    {
        DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var date = epoch.AddMilliseconds(unixEpochTime);

        if (date.Year > 1972)
            return date;

        return epoch.AddSeconds(unixEpochTime);
    }

If epoch time is in seconds then there is no way you can pass year 1972 adding milliseconds.


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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜