Як ви перетворюєте час епохи Unix в реальний час у C #? (Початок епохи 1.01.1970)
Як ви перетворюєте час епохи Unix в реальний час у C #? (Початок епохи 1.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. Інакше ви закінчитеся не в той час.
Ви насправді хочете Додати AddMilliseconds (мілісекунд), а не секунди. Додавання секунд призведе до виключення поза діапазоном.
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.
Це підтримується лише Рамкою 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, це може допомогти Джерело: 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);
}