Ответы:
Вы получаете метку времени Unix в C #, используя DateTime.UtcNow
и вычитая время эпохи 1970-01-01.
например
Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
DateTime.UtcNow
может быть заменен любым DateTime
объектом, для которого вы хотите получить метку времени Unix.
Существует также поле, DateTime.UnixEpoch
которое очень плохо документировано MSFT, но может заменитьnew DateTime(1970, 1, 1)
DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Начиная с .NET 4.6, есть DateTimeOffset.ToUnixTimeSeconds()
.
Это метод экземпляра, поэтому вы должны вызывать его для экземпляра DateTimeOffset
. Вы также можете разыграть любой экземпляр DateTime
, хотя остерегайтесь часового пояса .
Чтобы получить текущую метку времени:
DateTimeOffset.UtcNow.ToUnixTimeSeconds()
Чтобы получить метку времени из DateTime
:
DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
Int64
- к тому времени, когда перевернется, мы больше не будем использовать земные годы из-за отсутствия Земли.
DateTimeOffset.Now.ToUnixTimeSeconds()
Вы также можете использовать тики. Я пишу для Windows Mobile, поэтому не имею полного набора методов. TotalSeconds не доступен для меня.
long epochTicks = new DateTime(1970, 1, 1).Ticks;
long unixTime = ((DateTime.UtcNow.Ticks - epochTicks) / TimeSpan.TicksPerSecond);
или
TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;
new DateTime(1970, 1, 1)
создает время с неопределенным Kind
свойством. То, что вы действительно хотите, чтобы new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
быть по-настоящему правильным
Это то, что я использую:
public long UnixTimeNow()
{
var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
return (long)timeSpan.TotalSeconds;
}
Имейте в виду, что этот метод будет возвращать время в формате UTC.
double
тип, литье это долго может привести к потере точности.)
Усечение .TotalSeconds
важно, так как оно определяется какthe value of the current System.TimeSpan structure expressed in whole fractional seconds.
А как насчет расширения для DateTime
? Второе, вероятно, более запутанно, чем стоит расширение свойств.
/// <summary>
/// Converts a given DateTime into a Unix timestamp
/// </summary>
/// <param name="value">Any DateTime</param>
/// <returns>The given DateTime in Unix timestamp format</returns>
public static int ToUnixTimestamp(this DateTime value)
{
return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
/// <summary>
/// Gets a Unix timestamp representing the current moment
/// </summary>
/// <param name="ignored">Parameter ignored</param>
/// <returns>Now expressed as a Unix timestamp</returns>
public static int UnixTimestamp(this DateTime ignored)
{
return (int)Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
Когда вы вычитаете 1970 из текущего времени, имейте в виду, что временной интервал чаще всего будет иметь поле, отличное от нуля миллисекунд. Если по какой-то причине вас интересуют миллисекунды, имейте это в виду.
Вот что я сделал, чтобы обойти эту проблему.
DateTime now = UtcNow();
// milliseconds Not included.
DateTime nowToTheSecond = new DateTime(now.Year,now.Month,now.Day,now.Hour,now.Minute,now.Second);
TimeSpan span = (date - new DateTime(1970, 1, 1, 0, 0, 0, 0));
Assert.That(span.Milliseconds, Is.EqualTo(0)); // passes.
Это то, что я использую.
public class TimeStamp
{
public Int32 UnixTimeStampUTC()
{
Int32 unixTimeStamp;
DateTime currentTime = DateTime.Now;
DateTime zuluTime = currentTime.ToUniversalTime();
DateTime unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (Int32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
return unixTimeStamp;
}
}
Я собрал воедино самые элегантные подходы к этому служебному методу:
public static class Ux {
public static decimal ToUnixTimestampSecs(this DateTime date) => ToUnixTimestampTicks(date) / (decimal) TimeSpan.TicksPerSecond;
public static long ToUnixTimestampTicks(this DateTime date) => date.ToUniversalTime().Ticks - UnixEpochTicks;
private static readonly long UnixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
}
Это решение помогло в моей ситуации:
public class DateHelper {
public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
return (TimeZoneInfo.ConvertTimeToUtc(dateTime) -
new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}
}
используя помощник в коде:
double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)
Для SystemTimeOffset в системе существует значение ToUnixTimeMilliseconds
Вы можете написать аналогичный метод для DateTime:
public static long ToUnixTimeSeconds(this DateTime value)
{
return value.Ticks / 10000000L - 62135596800L;
}
10000000L - преобразование тиков в секунды
62135596800L - преобразование с 01.01.01 по 01.01.1978
Нет проблем с Utc и утечками
Ниже приведен двухсторонний класс расширения, который поддерживает:
В случае OP, использование:
DateTime.Now.ToUnixtime();
или
DateTime.UtcNow.ToUnixtime();
Хотя прямой ответ существует, я считаю, что лучше использовать общий подход. Тем более, что это, скорее всего, проект, который нуждается в таком преобразовании, в любом случае также потребует этих расширений, поэтому лучше использовать один и тот же инструмент для всех.
public static class UnixtimeExtensions
{
public static readonly DateTime UNIXTIME_ZERO_POINT = new DateTime(1970, 1, 1, 0, 0,0, DateTimeKind.Utc);
/// <summary>
/// Converts a Unix timestamp (UTC timezone by definition) into a DateTime object
/// </summary>
/// <param name="value">An input of Unix timestamp in seconds or milliseconds format</param>
/// <param name="localize">should output be localized or remain in UTC timezone?</param>
/// <param name="isInMilliseconds">Is input in milliseconds or seconds?</param>
/// <returns></returns>
public static DateTime FromUnixtime(this long value, bool localize = false, bool isInMilliseconds = true)
{
DateTime result;
if (isInMilliseconds)
{
result = UNIXTIME_ZERO_POINT.AddMilliseconds(value);
}
else
{
result = UNIXTIME_ZERO_POINT.AddSeconds(value);
}
if (localize)
return result.ToLocalTime();
else
return result;
}
/// <summary>
/// Converts a DateTime object into a Unix time stamp
/// </summary>
/// <param name="value">any DateTime object as input</param>
/// <param name="isInMilliseconds">Should output be in milliseconds or seconds?</param>
/// <returns></returns>
public static long ToUnixtime(this DateTime value, bool isInMilliseconds = true)
{
if (isInMilliseconds)
{
return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalMilliseconds;
}
else
{
return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalSeconds;
}
}
}
Я использовал это после некоторой борьбы, это также учитывает смещение часового пояса:
public double Convert_DatTime_To_UNIXDATETIME(DateTime dt)
{
System.DateTime from_date = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
double unix_time_since = dt.Subtract(from_date).TotalMilliseconds;
TimeSpan ts_offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);
double offset = ts_offset.TotalMilliseconds;
return unix_time_since - offset;
}
Простой код, который я использую:
public static long CurrentTimestamp()
{
return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000);
}
Этот код дает метку времени Unix, общее количество миллисекунд с 1970-01-01 по настоящее время.