精华内容
下载资源
问答
  • AndroidStudio logcat显示时间与当前系统时间不一致今天在用模拟器调试程序的时候,突然发现AndroidStudio的logcat显示的调试信息时间跟当前系统的时间不一致,这对于我们查看调试信息无疑带来了很大的不便,所以就...

    AndroidStudio logcat显示时间与当前系统时间不一致


    今天在用模拟器调试程序的时候,突然发现AndroidStudio的logcat显示的调试信息时间跟当前系统的时间不一致,这对于我们查看调试信息无疑带来了很大的不便,所以就在此将解决方法稍微记录下。


    出现这个问题的原因是模拟器所默认的时区是美国太平洋时区,导致模拟器的时间与我们系统的时间不一致,而logcat显示的是模拟器的当前时间。解决方法很简单,只要将模拟器的时区改变下就OK了。步骤如下:


    1.打开模拟器,打开Settings,打开Date&time

    这里写图片描述


    2.选择Select time zone

    这里写图片描述


    3.选择Shanghai

    这里写图片描述


    4.完工,logcat打印出来的时间与系统时间一致了,可以愉快地调试了

    这里写图片描述

    展开全文
  • ios 获取当前准确时间

    千次阅读 2018-10-10 11:12:38
    获取当前时间:(之前做倒计时时发现一些bug,这里对获取当前时间进行总结) 启动app时发送服务器时间请求获取当前最新时间,存储到内存; 退到后台或锁屏手机后再进入前台情况下最新时间: 这里处理的方案是将...

    获取当前时间:(之前做倒计时时发现一些bug,这里对获取当前时间进行总结)

    启动app时发送服务器时间请求获取当前最新时间,存储到内存;

    退到后台或锁屏手机后再进入前台情况下最新时间:

    这里处理的方案是将(启动app时获取到的服务器时间 - 当时获取服务器时间时处系统运行时长 + 现在的系统运行时长)

    这里只要能得到系统运行时长即可:

    了解下ios关于时间的处理:

    1.NSDate对象描述的是时间线上的一个绝对的值,和时区和文化无关,它参考的值是:以UTC为标准的,2001年一月一日00:00:00这一刻的时间绝对值。

    NSDate输出的是绝对的UTC时间(而北京时间的时区为UTC+8,输出+8个小时)和市区和文化无关,所以要展示具体格式的时间,我们需要NSDateFormatter和NSTimeZone的辅助。NSDate是受手机系统时间控制的。

    2.CFAbsoluteTimeGetCurrent()的概念和NSDate非常相似,只不过参考点是:以GMT为标准的,2001年一月一日00:00:00这一刻的时间绝对值。也会跟着当前设备的系统时间一起变化。

    3.gettimeofday获得的值是Unix time,Unix time是以UTC 1970年1月1号 00:00:00为基准时间,当前时间距离基准点偏移的秒数。NSDate也有一个API能返回Unix time:

    NSDate* date = [ NSDatedate];

    NSLog( @"timeIntervalSince1970: %f", [date timeIntervalSince1970]);

     

    gettimeofday和NSDate,CFAbsoluteTimeGetCurrent()一样,都是受当前设备的系统时间影响。只不过是参考的时间基准点不一样而已。我们和服务器通讯的时候一般使用Unix time。

     

    4.mach_absolute_time()返回的就是CPU已经运行的CPU的时钟周期数(ticks)。tick的数量可以用来描述时间,将这个tick数经过一定的转换就可以变成秒数,或者纳秒数,这样就和时间直接关联了。不过这个tick数,在每次手机重启之后,会重新开始计数,而且iPhone锁屏进入休眠之后tick也会暂停计数。mach_absolute_time()不会受系统时间影响,只受设备重启和休眠行为影响。

    5.CACurrentMediaTime()就是将上面mach_absolute_time()的CPU tick数转化成秒数的结果。以下代码:

    doublemediaTime = CACurrentMediaTime();

    NSLog( @"CACurrentMediaTime: %f", mediaTime);

    返回的就是开机后设备一共运行了(设备休眠不统计在内)多少秒,另一个API也能返回相同的值:(原来做倒计时用的就是该API)

    NSTimeIntervalsystemUptime = [[NSProcessInfo processInfo] systemUptime];

    NSLog( @"systemUptime: %f", systemUptime);

    CACurrentMediaTime()也不会受系统时间影响,只受设备重启和休眠行为影响。

    6.sysctl记录了上次设备重启的时间。可以通过如下API调用获取:#include <sys/sysctl.h>

    - ( long)bootTime{

    #define MIB_SIZE 2intmib[MIB_SIZE]; size_t size;

    structtimeval boottime;

    mib[ 0] = CTL_KERN; mib[ 1] = KERN_BOOTTIME;

     size = sizeof(boottime);

    if(sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != - 1) {

    returnboottime .tv_sec; }

    return0;}

    返回的值是上次设备重启的Unix time。

    这个API返回的值也会受系统时间影响,用户如果修改时间,值也会随着变化。

     

    结合上面描述这里获取运行时长:

    - ( NSTimeInterval)uptime{

    structtimeval boottime;

    intmib[ 2] = {CTL_KERN, KERN_BOOTTIME};

     size_t size = sizeof(boottime);

    structtimeval now;

    structtimezone tz;

     gettimeofday(&now, &tz);

    doubleuptime = - 1;

    if(sysctl(mib, 2, &boottime, &size, NULL, 0) != - 1&& boottime .tv_sec!= 0) {

     uptime = now .tv_sec- boottime .tv_sec;

     uptime += ( double)(now .tv_usec- boottime .tv_usec) / 1000000.0; }

    returnuptime;}

    gettimeofday和sysctl都会受系统时间影响,但他们二者做一个减法所得的值,就和系统时间无关了。

    展开全文
  • C语言获取当前系统时间的几种方式

    万次阅读 2017-01-04 12:23:03
    C语言获取当前系统时间的几种方式 C语言获取系统时间的几种方式 C语言中如何获取时间?精度如何? 1 使用time_t time( time_t * timer ) 精确到秒 2 使用clock_t clock() 得到的是CPU时间精确到1/CLOCKS_PER_SEC...

    C语言获取当前系统时间的几种方式
    C语言获取系统时间的几种方式
    C语言中如何获取时间?精度如何?
    1 使用time_t time( time_t * timer ) 精确到秒
    2 使用clock_t clock() 得到的是CPU时间精确到1/CLOCKS_PER_SEC秒
    3 计算时间差使用double difftime( time_t timer1, time_t timer0 )
    4 使用DWORD GetTickCount() 精确到毫秒
    5 如果使用MFC的CTime类,可以用CTime::GetCurrentTime() 精确到秒
    6 要获取高精度时间,可以使用
    BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
    获取系统的计数器的频率
    BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
    获取计数器的值
    然后用两次计数器的差除以Frequency就得到时间。
    7 Multimedia Timer Functions
    The following functions are used with multimedia timers.
    timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime
    //*********************************************************************
    //用标准C实现获取当前系统时间的函数
     
    一.time()函数
     
         time(&rawtime)函数获取当前时间距1970年1月1日的秒数,以秒计数单位,存于rawtime 中。
    #include "time.h"
    void main ()
    {
    time_t rawtime;
    struct tm * timeinfo;
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    printf ( "\007The current date/time is: %s", asctime (timeinfo) );
    exit(0);
    }
    =================
    #include -- 必须的时间函数头文件
    time_t -- 时间类型(time.h 定义是typedef long time_t; 追根溯源,time_t是long)
    struct tm -- 时间结构,time.h 定义如下:
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
    time ( &rawtime ); -- 获取时间,以秒计,从1970年1月一日起算,存于rawtime
    localtime ( &rawtime ); -- 转为当地时间,tm 时间结构
    asctime ()-- 转为标准ASCII时间格式:
    星期 月 日 时:分:秒 年
     
    -----------------------------------------------------------------------------
    二.clock()函数,用clock()函数,得到系统启动以后的毫秒级时间,然后除以CLOCKS_PER_SEC,就可以换成“秒”,标准c函数。
    clock_t clock ( void );
    #include
    clock_t t = clock();
    long sec = t / CLOCKS_PER_SEC;
    他是记录时钟周期的,实现看来不会很精确,需要试验验证;
    ---------------------------------------------------------------------------
    三.gettime(&t); 据说tc2.0的time结构含有毫秒信息
    #include
    #include
    int main(void)
    {
    struct time t;
    gettime(&t);
    printf("The current time is: -:d:d.d\n",
    t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
    return 0;
    }
    time 是一个结构体,, 其中成员函数 ti_hund 是毫秒。。。
     
    --------------------------------------------------------------------------------
    四.GetTickCount(),这个是windows里面常用来计算程序运行时间的函数;
    DWORD dwStart = GetTickCount();
    //这里运行你的程序代码
    DWORD dwEnd = GetTickCount();
    则(dwEnd-dwStart)就是你的程序运行时间, 以毫秒为单位
    这个函数只精确到55ms,1个tick就是55ms。
    --------------------------------------------------------------------------------
    五.timeGetTime()t,imeGetTime()基本等于GetTickCount(),但是精度更高
    DWORD dwStart = timeGetTime();
    //这里运行你的程序代码
    DWORD dwEnd = timeGetTime();
    则(dwEnd-dwStart)就是你的程序运行时间, 以毫秒为单位
    虽然返回的值单位应该是ms,但传说精度只有10ms。
    =========================================
    //*****************************************************************Unix
    ##unix时间相关,也是标准库的
    //*********************************************************************
    1.timegm函数只是将struct tm结构转成time_t结构,不使用时区信息;
    time_t timegm(struct tm *tm);
    2.mktime使用时区信息
    time_t mktime(struct tm *tm);
    timelocal 函数是GNU扩展的与posix函数mktime相当
    time_t timelocal (struct tm *tm);
    3.gmtime函数只是将time_t结构转成struct tm结构,不使用时区信息;
    struct tm * gmtime(const time_t *clock);
    4.localtime使用时区信息
    struct tm * localtime(const time_t *clock);
    1.time获取时间,stime设置时间
    time_t t;
    t = time(&t);
    2.stime其参数应该是GMT时间,根据本地时区设置为本地时间;
    int stime(time_t *tp)
    3.UTC=true 表示采用夏时制;
    4.文件的修改时间等信息全部采用GMT时间存放,不同的系统在得到修改时间后通过localtime转换成本地时间;
    5.设置时区推荐使用setup来设置;
    6.设置时区也可以先更变/etc/sysconfig/clock中的设置再将ln -fs /usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效
    time_t只能表示68年的范围,即mktime只能返回1970-2038这一段范围的time_t
    看看你的系统是否有time_t64,它能表示更大的时间范围
    //***************************************************************windows
    ##Window里面的一些不一样的
    //*********************************************************************
     
    一.CTime () 类
    VC编程一般使用CTime类 获得当前日期和时间
     
    CTime t = GetCurrentTime();
    SYSTEMTIME 结构包含毫秒信息
    typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
    } SYSTEMTIME, *PSYSTEMTIME;
    SYSTEMTIME t1;
    GetSystemTime(&t1)
    CTime curTime(t1);
    WORD ms = t1.wMilliseconds;
    SYSTEMTIME sysTm;
    ::GetLocalTime(&sysTm);
    在time.h中的_strtime() //只能在windows中用
    char t[11];
    _strtime(t);
    puts(t);
     
    //*****************************
    获得当前日期和时间
    CTime tm=CTime::GetCurrentTime();
    CString str=tm.Format("%Y-%m-%d");
    在VC中,我们可以借助CTime时间类,获取系统当前日期,具体使用方法如下:
    CTime t = CTime::GetCurrentTime(); //获取系统日期,存储在t里面
    int d=t.GetDay(); //获得当前日期
    int y=t.GetYear(); //获取当前年份
    int m=t.GetMonth(); //获取当前月份
    int h=t.GetHour(); //获取当前为几时
    int mm=t.GetMinute(); //获取当前分钟
    int s=t.GetSecond(); //获取当前秒
    int w=t.GetDayOfWeek(); //获取星期几,注意1为星期天,7为星期六
     
    二.CTimeSpan类
    如果想计算两段时间的差值,可以使用CTimeSpan类,具体使用方法如下:
    CTime t1( 1999, 3, 19, 22, 15, 0 );
    CTime t = CTime::GetCurrentTime();
    CTimeSpan span=t-t1; //计算当前系统时间与时间t1的间隔
    int iDay=span.GetDays(); //获取这段时间间隔共有多少天
    int iHour=span.GetTotalHours(); //获取总共有多少小时
    int iMin=span.GetTotalMinutes();//获取总共有多少分钟
    int iSec=span.GetTotalSeconds();//获取总共有多少秒
     
     
    ------------------------------------------------------------------------------
     
    三._timeb()函数
    _timeb定义在SYS\TIMEB.H,有四个fields
    dstflag
    millitm
    time
    timezone
    void _ftime( struct _timeb *timeptr );
    struct _timeb timebuffer;
    _ftime( &timebuffer );
    取当前时间:文档讲可以到ms,有人测试,好象只能到16ms!
     
     
    四.设置计时器
    定义TIMER ID
    #define TIMERID_JISUANFANGSHI 2
    在适当的地方设置时钟,需要开始其作用的地方;
    SetTimer(TIMERID_JISUANFANGSHI,200,NULL);
    在不需要定时器的时候的时候销毁掉时钟
    KillTimer(TIMERID_JISUANFANGSHI);
    对应VC程序的消息映射
    void CJisuan::OnTimer(UINT nIDEvent)
    {switch(nIDEvent)}
    ---------------------------------------------------------------------------------------
    ##如何设定当前系统时间---------------------------------------windows
    SYSTEMTIME m_myLocalTime,*lpSystemTime;
    m_myLocalTime.wYear=2003;
    m_myLocalTime.wM;
    m_myLocalTime.wDay=1;
    m_myLocalTime.wHour=0;
    m_myLocalTime.wMinute=0;
    m_myLocalTime.wSec;
    m_myLocalTime.wMillisec;
    lpSystemTime=&m_myLocalTime;
    if( SetLocalTime(lpSystemTime) ) //此处换成 SetSystemTime( )也不行
    MessageBox("OK !");
    else
    MessageBox("Error !");
    SYSTEMTIME m_myLocalTime,*lpSystemTime;
    m_myLocalTime.wYear=2003;
    m_myLocalTime.wM;
    m_myLocalTime.wDay=1;
    lpSystemTime=&m_myLocalTime;
    if( SetDate(lpSystemTime) ) //此处换成 SetSystemTime( )也不行
    MessageBox("OK !");
    else
    MessageBox("Error !");
     
     
     
    一种制作微秒级精度定时器的方法
    当使用定时器时,在很多情况下只用到毫秒级的时间间隔,所以只需用到下面的两种常用方式就满足要求了。一是用SetTimer函数建立一个定时器后,在程序中通过处理由定时器发送到线程消息队列中的WM_TIMER消息,而得到定时的效果(退出程序时别忘了调用和SetTimer配对使用的KillTimer函数)。二是利用GetTickCount函数可以返回自计算机启动后的时间,通过两次调用GetTickCount函数,然后控制它们的差值来取得定时效果,此方式跟第一种方式一样,精度也是毫秒级的。
    用这两种方式取得的定时效果虽然在许多场合已经满足实际的要求,但由于它们的精度只有毫秒级的,而且在要求定时时间间隔小时,实际定时误差大。下面介绍一种能取得高精度定时的方法。
    在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution   performance   counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。采用这种方法的步骤如下:
    1、首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数一般很大。
    2、在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f。
    下面举一个例子来演示这种方法的使用及它的精确度。
    在VC   6.0   下用MFC建立一个对话框工程,取名为HightTimer.在对话框面板中控件的布局如下图:
    其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACTUAL,通过MFC   ClassWizard添加的成员变量也分别对应为DWORD   m_dwTest和DWORD   m_dwAct.   “退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC   ClassWizard添加此按纽的单击消息处理函数如下:
    void   CHightTimerDlg::OnBTest()
    {
    //   TODO:   Add   your   control   notification   handler   code   here
    UpdateData(TRUE);   //取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中
     
    LARGE_INTEGER   frequence;
    if(!QueryPerformanceFrequency(   &frequence))   //取高精度运行计数器的频率,若硬件不支持则返回FALSE
    MessageBox("Your   computer   hardware   doesn't   support   the   high-resolution   performance   counter",
    "Not   Support",   MB_ICONEXCLAMATION   |   MB_OK);
     
    LARGE_INTEGER   test,   ret;
    test.QuadPart   =   frequence.QuadPart   *   m_dwTest   /   1000000;   //通过频率换算微秒数到对应的数量(与CPU时钟有关),1秒=1000000微秒
    ret   =   MySleep(   test   );   //调用此函数开始延时,返回实际花销的数量
     
    m_dwAct   =   (DWORD)(1000000   *   ret.QuadPart   /   frequence.QuadPart   );   //换算到微秒数
     
    UpdateData(FALSE);   //显示到对话框面板
    }
       其中上面调用的MySleep函数如下:
     
    LARGE_INTEGER   CHightTimerDlg::MySleep(LARGE_INTEGER   Interval)
    /
    //   功能:执行实际的延时功能    
    //   参数:Interval   参数为需要执行的延时与时间有关的数量    
    //   返回值:返回此函数执行后实际所用的时间有关的数量    
    ///
    {  
    LARGE_INTEGER   privious,   current,   Elapse;
     
    QueryPerformanceCounter(   &privious   );
    current   =   privious;
     
    while(   current.QuadPart   -   privious.QuadPart   <   Interval.QuadPart   )
    QueryPerformanceCounter(   ¤t   );
     
    Elapse.QuadPart   =   current.QuadPart   -   privious.QuadPart;
     
    return   Elapse;
    }
    注:别忘了在头文件中为此函数添加函数声明。
     
    至此,可以编译和执行此工程了,结果如上图所示。在本人所用的机上(奔腾366,   64M内存)测试,当测试时间超过3微秒时,准确度已经非常高了,此时机器执行本身延时函数代码的时间对需要延时的时间影响很小了。
     
    上面的函数由于演示测试的需要,没有在函数级封装,下面给出的函数基本上可以以全局函数的形式照搬到别的程序中。
     
    BOOL   MySleep(DWORD   dwInterval)
    /
    //   功能:执行微秒级的延时功能    
    //   参数:Interval   参数为需要的延时数(单位:微秒)    
    //   返回值:若计算机硬件不支持此功能,返回FALSE,若函数执行成功,返回TRUE    
    /// 
    {
    BOOL   bNormal   =   TRUE;
    LARGE_INTEGER   frequence,   privious,   current,   interval;
     
    if(!QueryPerformanceFrequency(   &frequence))
    {
    ::MessageBox(NULL,   "Your   computer   hardware   doesn't   support   the   high-resolution   performance   counter",
    "Not   Support",   MB_ICONEXCLAMATION   |   MB_OK);   //或其它的提示信息
    return   FALSE;
    }
     
    interval.QuadPart   =   frequence.QuadPart   *   dwInterval   /   1000000;
     
    bNormal   =   bNormal   &&   QueryPerformanceCounter(   &privious   );
    current   =   privious;
     
    while(   current.QuadPart   -   privious.QuadPart   <   interval.QuadPart   )
    bNormal   =   bNormal   &&   QueryPerformanceCounter(   ¤t   );
     
    return   bNormal;
    }
     
    需要指出的是,由于在此函数中的代码很多,机器在执行这些代码所花费的时间也很长,所以在需要几个微秒的延时时,会影响精度。实际上,读者在熟悉这种方法后,只要使用QueryPerformanceFrequency和QueryPerformanceCounter这两个函数就能按实际需要写出自己的延时代码了。
     
    使用CPU时间戳进行高精度计时
    对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里可以尽快的确定程序的性能瓶颈,或者对不同的算法作出有说服力的性能比较。
     
    在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。
     
    本文要介绍的,是另一种直接利用Pentium   CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第15页-17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。
     
    在Intel   Pentium以上级别的CPU中,有一个称为“时间戳(Time   Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。
     
    在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read   Time   Stamp   Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:
     
    inline   unsigned   __int64   GetCycleCount()

    __asm   RDTSC 

     
    但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
     
    inline   unsigned   __int64   GetCycleCount()  
    {  
        __asm   _emit   0x0F  
        __asm   _emit   0x31  
    }  
       
    以后在需要计数器的场合,可以像使用普通的Win32   API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:  
       
    unsigned   long   t;  
    t   =   (unsigned   long)GetCycleCount();  
    //Do   Something   time-intensive   ...  
    t   -=   (unsigned   long)GetCycleCount();  
       
      《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在Celeron   800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿也过于粗糙了。  
       
    这个方法的优点是:  
       
    1.高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。  
       
    2.成本低。timeGetTime   函数需要链接多媒体库winmm.lib,QueryPerformance*   函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。  
       
    3.具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。  
       
    这个方法的缺点是:  
       
    1.现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。  
       
    2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。  
       
    关于这个方法计时的最大长度,我们可以简单的用下列公式计算:  
       
    自CPU上电以来的秒数   =   RDTSC读出的周期数   /   CPU主频速率(Hz)  
       
    64位无符号整数所能表达的最大数字是1.8×10^19,在我的Celeron   800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。  
       
    下面是几个小例子,简要比较了三种计时方法的用法与精度  
       
    //Timer1.cpp   使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15  
    //编译行:CL   Timer1.cpp   /link   USER32.lib  
    #include     
    #include   "KTimer.h"  
    main()  
    {  
        unsigned   t;  
        KTimer   timer;  
        timer.Start();  
        Sleep(1000);  
        t   =   timer.Stop();  
        printf("Lasting   Time:   %d\n",t);  
    }  
       
    //Timer2.cpp   使用了timeGetTime函数  
    //需包含,但由于Windows头文件错综复杂的关系  
    //简单包含比较偷懒:)  
    //编译行:CL   timer2.cpp   /link   winmm.lib    
    #include     
    #include     
       
    main()  
    {  
        DWORD   t1,   t2;  
        t1   =   timeGetTime();  
        Sleep(1000);  
        t2   =   timeGetTime();  
        printf("Begin   Time:   %u\n",   t1);  
        printf("End   Time:   %u\n",   t2);  
        printf("Lasting   Time:   %u\n",(t2-t1));  
    }  
       
    //Timer3.cpp   使用了QueryPerformanceCounter函数  
    //编译行:CL   timer3.cpp   /link   KERNEl32.lib  
    #include     
    #include     
       
    main()  
    {  
        LARGE_INTEGER   t1,   t2,   tc;  
        QueryPerformanceFrequency(&tc);  
        printf("Frequency:   %u\n",   tc.QuadPart);  
        QueryPerformanceCounter(&t1);  
        Sleep(1000);  
        QueryPerformanceCounter(&t2);  
        printf("Begin   Time:   %u\n",   t1.QuadPart);  
        printf("End   Time:   %u\n",   t2.QuadPart);  
        printf("Lasting   Time:   %u\n",(   t2.QuadPart-   t1.QuadPart));  
    }  
       
     
    //以上三个示例程序都是测试1秒钟休眠所耗费的时间  
    file://测/试环境:Celeron   800MHz   /   256M   SDRAM      
    //                     Windows   2000   Professional   SP2  
    //                     Microsoft   Visual   C++   6.0   SP5  
     
       
    以下是Timer1的运行结果,使用的是高精度的RDTSC指令  
    Lasting   Time:   804586872  
       
    以下是Timer2的运行结果,使用的是最粗糙的timeGetTime   API  
    Begin   Time:   20254254  
    End   Time:   20255255  
    Lasting   Time:   1001  
       
    以下是Timer3的运行结果,使用的是QueryPerformanceCount   API  
    Frequency:   3579545  
    Begin   Time:   3804729124  
    End   Time:   3808298836  
    Lasting   Time:   3569712 
    展开全文
  • 两种时间更新机制NITZNITZ(Network...NITZ是自从PHASE 2+ RELEASE 96 的GSM中的可选功能,经常被用来自动更新移动电话的系统时钟。NITZ需要运营商网络支持(通过CS网络),目前国内电信、移动都支持NITZ方式更新时间...

    两种时间更新机制

    NITZ

    NITZ(Network Identity and Time Zone,网络标识和时区),是一种用于自动配置本地的时间和日期的机制,同时也通过无线网向移动设备提供运营商信息。NITZ是自从PHASE 2+ RELEASE 96 的GSM中的可选功能,经常被用来自动更新移动电话的系统时钟。NITZ需要运营商网络支持(通过CS网络),目前国内电信、移动都支持NITZ方式更新时间日期,而联通目前不支持。

    参考: https://en.wikipedia.org/wiki/NITZ

    NTP

    NTP:NTP(Network Time Protocol)提供准确时间,首先要有准确的时间来源,这一时间应该是国际标准时间UTC。 NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。这样就有了准确而可靠的时间源。时间按NTP服务器的等级传播。与NITZ不同的是,NTP需要从专门的NTP服务器来获取时间,只要手机连接上网络,都可以实现时间的更新。

    参考: https://en.wikipedia.org/wiki/Network_Time_Protocol

    Android如何更新系统时间

    Android有一个专门的系统服务 NetworkTimeUpdateServcie来负责更新系统时间,该服务在系统启动时在SystemServer.java中被创建:

        if (!disableNetwork && !disableNetworkTime) {
            try {
                Slog.i(TAG, "NetworkTimeUpdateService");
                networkTimeUpdater = new NetworkTimeUpdateService(context);
           } catch (Throwable e) {
                reportWtf("starting NetworkTimeUpdate service", e);
            }
        }
        ...
        ...
        try {
            if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
        } catch (Throwable e) {
            reportWtf("Notifying NetworkTimeService running", e);
        }

    源码: /frameworks/base/services/core/java/com/android/server/NetworkTimeUpdateService.java

    服务初始化

    NetworkTimeUpdateService初始时会:

    • 注册RIL的ACTION_NETWORK_SET_TIME以及ACTION_NETWORK_SET_TIMEZONE事件,以接受来自Telephony FW的NITZ时间更新;
    • 监听 ACTION_POLL事件(定时更新时间)以及手机网络连接状态;
    • 发送消息同步NTP时间
    • 监听 Settings中“自动更新时间”选项的变化
        /** Initialize the receivers and initiate the first NTP request */
        public void systemRunning() {
            registerForTelephonyIntents();
            registerForAlarms();
            registerForConnectivityIntents();
    
            HandlerThread thread = new HandlerThread(TAG);
            thread.start();
            mHandler = new MyHandler(thread.getLooper());
            // Check the network time on the new thread
            mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
    
            mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
            mSettingsObserver.observe(mContext);
        }

    同步NTP时间

    如果没有收到NITZ时间的更新并且NTP超过一定间隔没有更新时间,服务会主动去同步NTP时间:

        // force refresh NTP cache when outdated
        if (mTime.getCacheAge() >= mPollingIntervalMs) {
            mTime.forceRefresh();
        }

    这里可能会出现问题,时区选对了,但是时间日期都不准确,这里原因NTPServer服务器配置不对

    修改配置位置:frameworks\base\core\res\res\values\config.xml

    关键参数config_ntpServer

    可以参考一下

     <!-- Remote server that can provide NTP responses. -->
        <string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
        <!-- Normal polling frequency in milliseconds -->
        <integer name="config_ntpPollingInterval">864000000</integer>
        <!-- Try-again polling interval in milliseconds, in case the network request failed -->
        <integer name="config_ntpPollingIntervalShorter">60000</integer>
        <!-- Number of times to try again with the shorter interval, before backing
             off until the normal polling interval. A value < 0 indicates infinite. -->
        <integer name="config_ntpRetry">3</integer>
        <!-- If the time difference is greater than this threshold in milliseconds,
             then update the time. -->
        <integer name="config_ntpThreshold">5000</integer>
        <!-- Timeout to wait for NTP server response. -->
        <integer name="config_ntpTimeout">20000</integer>

    NTP从服务器获取时间:

        @Override
        public boolean forceRefresh() {
        ...
            // We can't do this at initialization time: ConnectivityService might not be running yet.
            synchronized (this) {
                if (mCM == null) {
                    mCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
                }
            }
        ...
            if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
            final SntpClient client = new SntpClient();
            if (client.requestTime(mServer, (int) mTimeout)) {
                mHasCache = true;
                mCachedNtpTime = client.getNtpTime();
                mCachedNtpElapsedRealtime = client.getNtpTimeReference();
                mCachedNtpCertainty = client.getRoundTripTime() / 2;
               return true;
            } else {
               return false;
            }
        }

    源码: /frameworks/base/core/java/android/util/NtpTrustedTime.java

    接收NITZ时间

    Telephony Framework层在接收到最新的NITZ时间后,会主动发送广播请求更新系统时间,NetworkTimeUpateService接收到广播后,保存相应的NITZ时间,下一次poll请求时,就会将该事件更新为系统时间。

        private BroadcastReceiver mNitzReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
                    mNitzTimeSetTime = SystemClock.elapsedRealtime();
                } else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) {
                    mNitzZoneSetTime = SystemClock.elapsedRealtime();
                }
            }
        };

    监听Settings中 “自动确定时间和日期”的变化

    在setting中勾选“自动确定时间和日期”、“自动确定时区”后对key值为AUTO_TIME和AUTO_TIME_ZONE的Preference进行了赋值.

    源码路径:packages/apps/Settings/src/com/android/settings/DateTimeSettings.java

        void observe(Context context) {
                ContentResolver resolver = context.getContentResolver();
                resolver.registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUTO_TIME),
                        false, this);
            }
    
            @Override
            public void onChange(boolean selfChange) {
                mHandler.obtainMessage(mMsg).sendToTarget();
            }

    NetworkTimeUpdateService在检测到key值改变的时,就会发送一个消息EVENT_AUTO_TIME_CHANGED;handler接到消息后进行消息处理调用onPollNetworkTime(msg.what):

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_AUTO_TIME_CHANGED:
                case EVENT_POLL_NETWORK_TIME:
                case EVENT_NETWORK_CONNECTED:
                    onPollNetworkTime(msg.what);
                    break;
            }
        }

    在onPollNetworkTime方法中先判断是否勾选“自动更新时间”,如果没勾选直接退出,如果勾选了再看。如果NITZ已经更新了(不为NOT_SET(-1)),且更新间隔小于mPollingIntervalMs(mPollingIntervalMs=24*60*60*1000),则直接用NITZ更新系统时间,否则用NTP同步时间。

        // If NITZ time was received less than mPollingIntervalMs time ago,
        // no need to sync to NTP.
        if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
            resetAlarm(mPollingIntervalMs);
            return;
        }
    
         final long ntp = mTime.currentTimeMillis();
         mTryAgainCounter = 0;
         // If the clock is more than N seconds off or this is the first time it's been
         // fetched since boot, set the current time.
         if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
                    || mLastNtpFetchTime == NOT_SET) {
            // Set the system time
            ......
            if (ntp / 1000 < Integer.MAX_VALUE) {
                               SystemClock.setCurrentTimeMillis(ntp);
         }

    当从NTP服务器上获取的时间和当前时间之差的绝对值大于一个阀值,则认为当前时间错误,需要更新时间。

    总结:

    • 时间自动同步选项未勾选,不主动更新时间,直接返回;
    • NITZ已同步且上次NITZ同步未超过24小时,则设置定时器24小时后再触发同步,即广播NetworkTimeUpdateService.ACTION_POLL;
    • NTP上次成功同步超过24小时或用户勾选自动同步选项,则进行下面的NTP同步,否则同上设置定时器24小时后再触发同步

    参考文献

    展开全文
  • Android 倒计时功能,完美解决系统时间更改后,倒计时不准问题。 1、Android倒计时大家一下子就会想到使用:timer.schedule(); 我们查看schedule实现的源码:sched(task, System.currentTimeMillis()+delay, 0); ...
  • 这两天做迭代任务遇到了一个难题,现在找到了解决方法,为了...问题描述:使用home键把页面切到后台运行,倒计时就暂停了,再切回到前台运行回去看倒计时,时间不准确(具体表现为:切出之前是20:20:20,切出等...
  • 2.当前时间要用服务器时间 3.如何考虑手机锁屏线程休眠 4.如何做到tableViewCell里面放倒计时 5.到期时间不变,当前时间在变,主要操作的是这个差值 Demo分析 1.创建GCD定时器 Demo用NSDate来模拟服务器...
  • 前段时间测试提了一个bug,是这样的,设置一个闹铃,等待闹铃时间到,闹铃响应,然后插拔电池,让手机系统时间恢复到出厂默认时间,让手机联网,等待手机时间更新后,已经过期的闹钟突然响了,这让人百思不得其解,...
  • Android 系统时间

    千次阅读 2018-03-16 17:35:27
    Android系统更新时间两类方式: 1.网络提供时间(运营商SIM和WIFI) 2.GPS提供时间(GPS模块接收GPS卫星信号获得,定位成功即生效) 1.时间相关概念 1.1 GMT格林威治标准时间(Greenwich Mean Time) ...
  • 优化Android手机的GPS定位系统,加速搜星,定位准确

    万次阅读 热门讨论 2012-10-20 15:52:54
    呵呵,同时,我还把自己的笔记本电脑的时间同步也进行了更改。大家可以试试。我将手机的google服务器改成了nokia的,大家有兴趣的话,可以试试不同的服务情况,适合大家的话,请顶我。。。觉得好的
  • Android系统时间更新机制

    千次阅读 2016-12-01 09:19:54
    系统设置–日期和时间–自动确定日期和时间:  智能机 提供2类日期和时间同步方式:  使用网络提供时间  使用GPS提供时间  以及”自动确定时区“的选项。  Android 之时间和日期的自动同步  那就是说,...
  • Android 系统时间更新机制

    千次阅读 2015-09-21 11:17:51
    系统设置–日期和时间–自动确定日期和时间: 智能机 提供2类日期和时间同步方式: 使用网络提供时间 使用GPS提供时间 以及”自动确定时区“的选项。 Android 之时间和日期的自动同步 那就是说,我们可以通过...
  • Linux--Date命令查看及修改系统时间

    千次阅读 2020-06-06 18:15:21
    在我们使用linux服务器时,肯定会遇到Linux服务器时间不准确的情况,如何查看Linux系统的时间,如何修改Linux系统上的当前时间呢。 查看Linux系统当前时间。 命令: date +回车 修改Linux系统当前时间。 1.不修改年...
  • android 手机系统的性能测试

    千次阅读 2018-03-20 16:20:35
    2.1 性能指标 a,响应时间/加载速度 b,动画帧率 图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染。高的帧率可以得到更流畅,更逼真的动画,不过帧率达到60... 在android系统中,每个APP进程除了...
  • Android 系统时间自动更新机制

    千次阅读 2016-10-22 16:53:34
    Android中两种时间更新机制NITZNITZ(Network Identity and Time Zone,网络标识和时区),是一种用于自动配置本地的时间和日期的机制,同时也通过无线网向移动设备提供运营商信息。NITZ是自从PHASE 2+ RELEASE 96 的...
  • 自助式手机地图服务系统   1、什么是自助式手机地图 自助式手机地图就是自己动手制作地图文件,然后放到手机上,使用手机地图程序打开手机上的地图文件来实现地图的操作,获得地图服务,如查看道路,查找地名...
  • 【7】 MTK手机软件系统 MTK feature phone的基本功能是通话和短信,要了解MTK手机软件系统,首先需要简要回顾几个移动网络通讯的基本概念。 Figure 38. GSM-GPRS Architecture Courtesy ...
  • “自主”手机操作系统:如何判定及怎么做 http://www.sina.com.cn 2012年09月21日 23:18 新浪科技微博 作者:魏永明  编者注:这是一篇难得的科普及技术分析,从五方面详细地阐述了近日甚嚣尘上的“自主...
  • 有两种方案解决定时器前后台切换,倒计时停止显示不准确的问题。 1.准确及时方案:创建NSTimer定时器,监控前后台通知和全局变量记录时间。 2.切换到后台存在延迟刷新的问题解决方案:起线程记录时间
  • 微信小程序 获取当前日期时间

    千次阅读 2020-02-02 19:44:12
    获取当前系统日期和时间,但是搜索到的博客都写的什么import utils.js,麻烦的很,我来写个简单易懂的,一看就会。 解: // 当前日期 YYYY-MM-DD console.log(new Date().toISOString().substring(0, 10)); ...
  • 当代GSM手机的硬件系统分析

    千次阅读 2012-07-02 18:14:23
    当代GSM手机的硬件系统分析 Harald Welte 2010年4月14日 Translated by 黑白兔(lennyhhf@gmail.com) 摘要 每天有数以十亿计的手机被几乎相同数量的用户使用。这些手机中的绝大多数是基于GSM...
  • 1.手机系统时间存在的问题 Android系统或者Java程序在打时间戳时,经常使用System.currentTimeMillis(),如果直接用这个函数来打时间戳,会存在潜在的问题,即无法保证单调性和顺序性,对于这个函数,Java官方解释是...
  • iOS获取当前时间当前时区)

    千次阅读 2016-05-11 14:54:00
    为什么80%的码农都做了架构师?>>> ...
  • 来自52RD , ... ...原文标题为《"自主"操作系统——为什么及如何》,刊载于Fmsoft.cn。...在笔者看来,也是一篇对操作系统的技术甄别稿,非常值得一读,以窥清闹的沸沸扬扬的阿里云OS事件的真伪:所谓"自
  • 关于android手机充电时间的计算公式

    万次阅读 2013-01-14 14:33:41
    最近在做android手机电池管理相关的项目,其中有一个需求是计算手机充电时间的。翻阅了一些资料和一些相关的竞品,发现每个产品的在手机充电时长的计算上多不是很统一,后来翻阅了物理学的一些知识和文章,总算给出...
  • 这两天做迭代任务遇到了一个难题,现在找到了解决方法,为了避免忘记,在...问题描述:使用home键把页面切到后台运行,倒计时就暂停了,再切回到前台运行回去看倒计时,时间不准确(具体表现为:切出之前是20:20:20...
  • kotlin获取当前时间This tutorial helps you learn How to get current latitude and longitude in the Android application and then saving them in Firebase Firestore. As a developer if you know how to get ...
  • 那些抱怨手机电池越用越经用的机油们一定要试试这个方法,此方法通过清除记录在手机内的包括电压在内的各种电池信息,并重新记录,保证系统日志里电量信息的准确性,对于电池可拆卸的手机效果最好。 1...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,590
精华内容 13,836
关键字:

当前手机系统时间不准确