我目前正在使用此方法(C#)以毫秒为单位获取Unix时间:
long UnixTime()
{
return (long) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds;
}
问题 - 有没有办法在纳秒中获取unix时间?
提前致谢。
答案 0 :(得分:4)
计算本身并不难:
long UnixTime()
{
DateTime epochStart=new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (DateTime.UtcNow - epochStart).Ticks*100;
}
DateTime
和TimeSpan
在内部存储一定数量的刻度,其中一个刻度为100ns。我还将时期开始指定为UTC时间,因为我认为用DateTime
来减去Kind
是很难的,即使它有效。
但DateTime.UtcNow
的准确率非常低。它仅每隔几毫秒更新一次(典型值在1ms到16ms之间变化)。
要获得恒定的帧速率,您可以使用StopWatch
,因为您不需要绝对时间。但如果你这样走,你必须忙着等待。由于Thread.Sleep
,定时器......受到同样的限制。
或者,您可以使用timeBeginPeriod(1)
API,强制Windows更新时钟并每隔1ms运行一次计时器。但这是全球性的设置,会增加功耗。仍然比忙碌等待更好。
要测量时间差,您可以使用基于StopWatch
的{{1}},但这会带来一系列问题,例如不同内核之间的desyncs。我已经看到当你的线程被安排在另一个核心上时,机器被QueryPerformanceCounter
跳了几百毫秒。
答案 1 :(得分:2)
TotalMilliseconds属性返回包含整个和小数毫秒的double
。
因此,您只需将其值乘以1000000
即可获得纳秒:
return (long) ((DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds * 1000000.0);
答案 2 :(得分:1)
我认为这不是那么容易(在琐碎的桌面x86计算机上)精确度问题。 所以首先,DateTime类在这种情况下是无用的。 您可以使用StopWatch
以下是关于此问题的非常好的文章:http://www.codeproject.com/KB/testing/stopwatch-measure-precise.aspx
+1:https://stackoverflow.com/q/1416188/241506 enter link description here
答案 3 :(得分:0)
这门课会有所帮助。它允许您从Unix转换到Windows时间。评论可能不需要更新,但一切都运作良好。
public sealed class LinuxToWindowsFileTimeConverter : IValueConverter
{
static long ticksFrom1601To1970 = (long)(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) - DateTime.FromFileTimeUtc(0)).Ticks;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new DateTime();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return new DateTime();
}
public static DateTime Convert(Int64 nanoSecsSince1970)
{
return Convert(nanoSecsSince1970, ScaleFactor.Billion);
}
/// <summary>
/// Converts from Linux seconds to Windows DateTime
/// </summary>
/// <param name="secs"></param><remarks> secs</remarks>
/// <param name="sf"></param><remarks>specifies scale factor.
/// Specify ScaleFactor.One for secs since 1970.
/// ScaleFactor.Thousand for milli (10^3) seconds since 1970.
/// ScaleFactor.Million for micro (10^6)seconds since 1970.
/// ScaleFactor.Billion for nano (10^9)seconds since 1970.
/// etc.</remarks>
/// <returns></returns>
public static DateTime Convert(Int64 secs, ScaleFactor sf)
{
long hndrdnsfrom1601 = 0;
switch(sf)
{
case ScaleFactor.Billion:
hndrdnsfrom1601 = ticksFrom1601To1970 + secs / 100;
break;
default:
// TODO: Correct for other cases.
hndrdnsfrom1601 = (long)ticksFrom1601To1970 + (secs * (long)ScaleFactor.TenMillion / (long)sf);
break;
}
return DateTime.FromFileTimeUtc(hndrdnsfrom1601);
}
public static long ConvertBack(DateTime dateTimeInUTC)
{
if (dateTimeInUTC == new DateTime())
dateTimeInUTC = new DateTime(1980, 1,1).ToUniversalTime();
long secsSince1970 = (dateTimeInUTC.ToFileTimeUtc() - ticksFrom1601To1970) * ((long)ScaleFactor.Billion / (long)ScaleFactor.TenMillion);
return secsSince1970;
}
public Int64 ConvertBack(DateTime dateTimeInUTC, CultureInfo culture)
{
return ConvertBack(dateTimeInUTC, culture, ScaleFactor.Billion);
}
/// <summary>
/// Converts from Windows file time to Linux seconds.
/// </summary>
/// <param name="dateTimeInUTC"></param>
/// <param name="culture"></param>
/// <param name="sf"></param><remarks>
/// Specify ScaleFactor.One for secs since 1970.
/// ScaleFactor.Thousand for milli (10^3) seconds since 1970.
/// ScaleFactor.Million for micro (10^6)seconds since 1970.
/// ScaleFactor.Billion for nano (10^9)seconds since 1970.
/// </remarks>
/// <returns></returns>
public Int64 ConvertBack(DateTime dateTimeInUTC, CultureInfo culture, ScaleFactor sf)
{
long secsSince1970 = (dateTimeInUTC.ToFileTimeUtc() - ticksFrom1601To1970) * ((long)sf / (long)ScaleFactor.TenMillion);
return secsSince1970;
}
}
public enum ScaleFactor : long
{
One = 1,
Ten = 10,
Hundred = 100,
Thousand = 1000,
TenThou = 10000,
HundredThou = 100000,
Million = 1000000,
TenMillion = 10000000,
HundredMillion = 100000000,
Billion = 1000000000,
TenBillion = 10000000000,
HundredBillion = 100000000000
}