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);
}
精彩评论