Jak konwertować czas epoki uniksowej na czas rzeczywisty w języku C #? (Początek epoki 1/1/1970)
Jak konwertować czas epoki uniksowej na czas rzeczywisty w języku C #? (Początek epoki 1/1/1970)
Odpowiedzi:
Zakładam, że masz na myśli czas uniksowy , który jest zdefiniowany jako liczba sekund od północy (UTC) 1 stycznia 1970 r.
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);
AddXYZ
metody.
Najnowszą wersję .NET (v4.6) po prostu dodał wbudowane wsparcie dla systemu UNIX konwersji czasowych. Obejmuje to zarówno do, jak i od czasu uniksowego reprezentowanego przez sekundy lub milisekundy.
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
do czasu uniksowego w sekundach:long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
do czasu uniksowego w milisekundach:long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
Uwaga: Te metody są konwertowane na i z DateTimeOffset
. Aby uzyskać DateTime
reprezentację, wystarczy użyć DateTimeOffset.DateTime
właściwości:
DateTime dateTime = dateTimeOffset.UtcDateTime;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
Jak mógłbym rozwiązać ten problem?
Z całym podziękowaniem dla LukeH, opracowałem kilka metod rozszerzenia dla łatwego użycia:
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);
}
Należy zwrócić uwagę na komentarz poniżej z CodesInChaos że powyższe FromUnixTime
Zwraca DateTime
z Kind
od Utc
, co jest w porządku, ale wyżej ToUnixTime
jest o wiele bardziej podejrzany, który nie bierze pod uwagę, jakie DateTime
dana date
jest. Aby umożliwić date
„s Kind
jest albo Utc
albo Local
, użyj 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
przekonwertuje Local
(lub Unspecified
) DateTime
na Utc
.
jeśli nie chcesz tworzyć instancji DateTime epoki podczas przenoszenia z DateTime do epoki, możesz również:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
działa poprawnie tylko wtedy, gdy data jest w Utc. Dodaj czek lub przekonwertuj go. (Osobiście wolę czek)
milliseconds
nie sekund !!!
AddMilliseconds
i powinieneś użyć Double NOT Float. W przeciwnym razie skończy się zły czas.
Naprawdę chcesz dodać milisekundy (milisekundy), a nie sekundy. Dodanie sekund da wyjątek poza zakresem.
AddMillis
a jeśli zaczynasz od sekund, to oczywiście chcesz AddSeconds
.
Jeśli chcesz uzyskać lepszą wydajność, możesz użyć tej wersji.
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);
}
Z szybkiego testu porównawczego (BenchmarkDotNet) pod net471 otrzymuję ten numer:
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 szybciej w porównaniu z wersją LukeH (jeśli wydajność ma znaczenie)
Jest to podobne do wewnętrznego działania DateTime.
Użyj metody DateTimeOffset.ToUnixTimeMilliseconds () Zwraca liczbę milisekund, które upłynęły od 1970-01-01T00: 00: 00.000Z.
Jest to obsługiwane tylko w Framework 4.6 lub nowszym
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
Jest tu dobrze udokumentowane DateTimeOffset.ToUnixTimeMilliseconds
Innym wyjściem jest skorzystanie z poniższych
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
Aby uzyskać EPOCH w kilka sekund, możesz użyć tylko tego
var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
i przekonwertować Epoch
do DateTime
z następującym sposobem
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
.Ticks
, odzyskasz ładną instancję TimeSpan z odejmowania DateTime.
Używam następujących metod rozszerzenia do konwersji epoki
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);
}
Aby nie martwić się o użycie milisekund lub sekund, po prostu:
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);
}
Jeśli czas epoki jest w sekundach, nie można w żaden sposób przekroczyć roku 1972, dodając milisekundy.
Jeśli nie korzystasz z wersji 4.6, może to pomóc 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;
}
using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
Jeśli chcesz przekonwertować strukturę czasową (sekundy, mikrosekundy) zawierającą UNIX time
na DateTime
bez utraty precyzji, oto jak to zrobić :
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);
}
Od wersji .Net 4.6 i nowszych należy używać funkcji DateTimeOffset.Now.ToUnixTimeSeconds ()
Oto moje rozwiązanie:
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);
}