Unix时间 - 纳秒?

时间:2011-11-23 10:41:10

标签: c# visual-studio-2010

我目前正在使用此方法(C#)以毫秒为单位获取Unix时间:

long UnixTime()
{
    return (long) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds;
}   

问题 - 有没有办法在纳秒中获取unix时间?

提前致谢。

4 个答案:

答案 0 :(得分:4)

计算本身并不难:

long UnixTime()
{
    DateTime epochStart=new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return (DateTime.UtcNow - epochStart).Ticks*100;
}

DateTimeTimeSpan在内部存储一定数量的刻度,其中一个刻度为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
    }