Как конвертировать время эпохи Unix в C # в реальном времени? (Начало эпохи 01.01.1970)
Как конвертировать время эпохи Unix в C # в реальном времени? (Начало эпохи 01.01.1970)
Ответы:
Я предполагаю, что вы имеете в виду время Unix , которое определяется как количество секунд с полуночи (UTC) 1 января 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);
AddXYZ
метод.
В последней версии .Net (v4.6) добавлена встроенная поддержка преобразования времени в Unix. Это включает в себя время от и до Unix, представленное в секундах или миллисекундах.
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
Unix время в секундах:long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
Unix время в миллисекундах:long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
Примечание. Эти методы конвертируются в и из DateTimeOffset
. Чтобы получить DateTime
представление просто используйте DateTimeOffset.DateTime
свойство:
DateTime dateTime = dateTimeOffset.UtcDateTime;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
Как бы я решить эту проблему?
С благодарностью LukeH я собрал несколько методов расширения для легкого использования:
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);
}
Обратите внимание на комментарий ниже от CodesInChaos , что выше FromUnixTime
возвращает DateTime
с Kind
из Utc
, что это хорошо, но выше ToUnixTime
гораздо больше подозрений в том , что не учитывает , какого рода DateTime
данного date
есть. Для того, чтобы обеспечить date
«S Kind
бытия либо Utc
или Local
, используйте 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
преобразует Local
(или Unspecified
) DateTime
в Utc
.
если вы не хотите создавать экземпляр DateTime эпохи при переходе от DateTime к эпохе, вы также можете сделать следующее:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
работает правильно только если дата в Utc. Либо добавьте чек, либо конвертируйте его. (Лично я предпочитаю чек)
milliseconds
не секунды !!!
AddMilliseconds
и вы должны использовать Double NOT Float. В противном случае у вас будет неправильное время.
Вы действительно хотите добавить миллисекунды (миллисекунды), а не секунды. Добавление секунд даст вам исключение вне диапазона.
AddMillis
и если вы начинаете с секунд, вы, очевидно, хотите AddSeconds
.
Если вы хотите лучшую производительность, вы можете использовать эту версию.
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);
}
Из быстрого теста (BenchmarkDotNet) под net471 я получаю этот номер:
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 |
В 2 раза быстрее по сравнению с версией LukeH (если производительность зависит)
Это похоже на внутреннюю работу DateTime.
Используйте метод DateTimeOffset.ToUnixTimeMilliseconds (). Возвращает количество миллисекунд, прошедших с 1970-01-01T00: 00: 00.000Z.
Это поддерживается только в Framework 4.6 или выше
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
Это хорошо задокументировано здесь DateTimeOffset.ToUnixTimeMilliseconds
Другим выходом является использование следующего
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
Чтобы получить EPOCH только за секунды, вы можете использовать
var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
и преобразовать Epoch
в DateTime
следующий метод
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
.Ticks
, можно получить хороший экземпляр TimeSpan из вычитания DateTime.
// 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);
}
Следует использовать ToUniversalTime () для объекта DateTime.
Я использую следующие методы расширения для преобразования эпох
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);
}
Чтобы не беспокоиться об использовании миллисекунд или секунд, просто сделайте:
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);
}
Если время эпохи указано в секундах, вы не сможете пройти 1972 год, прибавив миллисекунды.
Если вы не используете 4.6, это может помочь 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);
Если вам нужно преобразовать временную структуру (секунды, микросекунды), содержащую UNIX time
в DateTime
без потери точности, вот как:
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);
}
Начиная с версии .Net 4.6 и выше, используйте DateTimeOffset.Now.ToUnixTimeSeconds ()
Вот мое решение:
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);
}