Chinaunix首页 | 论坛 | 博客
  • 博客访问: 204827
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 11
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-02 01:08
文章分类
文章存档

2020年(1)

2018年(2)

2017年(1)

2016年(7)

2015年(31)

2014年(16)

我的朋友

分类: C/C++

2014-12-18 00:00:52

一、time函数   

#include
time_t time(time_t *calptr);


返回距计算机元年的秒数
一旦取得这种以秒计的很大的时间值后,通常要调用另一个时间函数将其变换为人们可读的时间和日期

#include    
//calendar time into a broken-down time expressed as UTC
struct tm *gmtime(const time_t *calptr);

//converts the calendar time to the local time, taking into account the local time zone and
//daylight saving time flag
struct tm *localtime(const time_t *calptr);

//converts it into a time_t value
time_t mktime(struct tm *tmptr);

  struct tm {        /* a broken-down time */
     int  tm_sec;     /* seconds after the minute: [0 - 60] */
     int  tm_min;     /* minutes after the hour: [0 - 59] */
     int  tm_hour;    /* hours after midnight: [0 - 23] */
     int  tm_mday;    /* day of the month: [1 - 31] */
     int  tm_mon;     /* months since January: [0 - 11] */
     int  tm_year;    /* years since 1900 */
     int  tm_wday;    /* days since Sunday: [0 - 6] */
     int  tm_yday;    /* days since January 1: [0 - 365] */
     int  tm_isdst;   /* daylight saving time flag: <0, 0, >0 */
   }; 
char *asctime(const struct tm *tmptr);
char *ctime(const time_t *calptr);


asctime()和ctime()函数产生形式的26字节字符串,这与date命令的系统默认输出形式类似:
        Tue Feb 10 18:27:38 2004\n\0


二、gettimeofday函数得到更精确的时间

#include
int gettimeofday(struct timeval *restrict tp, void *restrict tzp);

第二个形参是基于平台实现的,使用的时候最好用NULL

struct timeval{
    time_t tv_sec;        /*** second ***/
    susecond_t tv_usec;    /*** microsecond 微妙***/
}

1秒=1000毫秒,
1毫秒=1000微秒,
1微妙=1000纳秒,
1纳秒=1000皮秒。
秒用s表现,毫秒用ms,微秒用μs表示,纳秒用ns表示,皮秒用ps表示。

下面是从tcpdump源代码中的一个函数,用来将timeval转化成字符串。
void ts_print(register const struct timeval *tvp) 

    register int s; 
    struct tm *tm; 
    time_t Time; 
    static unsigned b_sec; 
    static unsigned b_usec; 
 
    switch(tflag) { 
    case 1: /* Default */ 
        s = (tvp->tv_sec + thiszone) % 86400; 
        (void)printf("%02d:%02d:%02d.%06u ", 
                 s / 3600, (s % 3600) / 60, s % 60, 
                 (unsigned)tvp->tv_usec); 
        break; 
    case -1: /* Unix timeval style */ 
        (void)printf("%u.%06u ", 
                 (unsigned)tvp->tv_sec, 
                 (unsigned)tvp->tv_usec); 
        break; 
    case -2: 
        if (b_sec == 0) { 
            printf("000000 "); 
        } else { 
            int d_usec = tvp->tv_usec - b_usec; 
            int d_sec = tvp->tv_sec - b_sec; 
 
            while (d_usec < 0) { 
                d_usec += 1000000; 
                d_sec--; 
            } 
            if (d_sec) 
                printf("%d. ", d_sec); 
            printf("%06d ", d_usec); 
        } 
        b_sec = tvp->tv_sec; 
        b_usec = tvp->tv_usec; 
        break; 
    case -3: /* Default + Date*/ 
        s = (tvp->tv_sec + thiszone) % 86400; 
        Time = (tvp->tv_sec + thiszone) - s; 
        tm = gmtime (&Time); 
        if (!tm) 
            printf("Date fail  "); 
        else 
            printf("%04d-%02d-%02d ", 
                   tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); 
        printf("%02d:%02d:%02d.%06u ", 
               s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec); 
        break; 
    } 



三、内核时间

内核有两个重要的全局变量:
unsigned long jiffies;
timeval xtime ;


jiffies 是记录着从电脑开机到现在总共的"时钟中断"的次数。
文件linux-2.6.24/kernel/timer.c  
void do_timer(unsigned long ticks)
{
    jiffies_64 += ticks;
    update_times(ticks);
}


xtime 是从cmos电路或rtc芯片中取得的时间,一般是从某一历史时刻开始到现在的时间。
这个就是所谓的"墙上时钟walltimer",通过它可计算得出操作系统需要的日期时间,它的精确度是微秒。

xtime第一次赋值是在系统启动时调用timekeeping_init或time_init进行的
再调用read_persistent_clock进一步调用get_rtc_time得到的

PS:在/proc/uptime里面的两个数字分别表示:   
the uptime of the system(seconds),
and the amount of time spent in idle process(seconds).   

四、代码示例

“UTC时间字符串”与 “time函数返回值”互换

     int64_t TimeToUTC(char *time)
    {
        struct tm temp1;
        int rc;
        int year;
        int mon;
        int day;
        int hour;
        int min;
        int sec;
        rc = sscanf(time, "%4d-%2d-%2d %2d:%2d:%2d",
                        &(temp1.tm_year),
                        &(temp1.tm_mon),
                        &(temp1.tm_mday),
                        &(temp1.tm_hour),
                        &(temp1.tm_min),
                        &(temp1.tm_sec));
        sscanf(time, "%4d-%2d-%2d %2d:%2d:%2d",
                        &year,
                        &mon,
                        &day,
                        &hour,
                        &min,
                        &sec);
        if((rc<6)
            || (temp1.tm_year<1900) || (temp1.tm_year>2100)
            || (temp1.tm_mon<1) || (temp1.tm_mon>12)
            || (temp1.tm_mday<1) || (temp1.tm_mday>31)
            || (temp1.tm_hour<0) || (temp1.tm_hour>23)
            || (temp1.tm_min<0) || (temp1.tm_min>59)
            || (temp1.tm_sec<0) || (temp1.tm_sec>59))
        {
            return -1;
        }
        temp1.tm_mon -= 1;
        temp1.tm_year -= 1900;
        struct tm temp3;
        time_t temp2 = mktime(&temp1);
        if (temp2 == -1){
            return -1;
        }
        else{
            localtime_r(&temp2, &temp3);
            if (!((mon == (temp3.tm_mon+1))
                && (day == temp3.tm_mday)
                &&(year == (temp3.tm_year+1900)))){
                return -1;
            }
            else{
                    return temp2*1000000LL;
            }
        }
    }
    void UTCToTime(int64_t utc, char * clock)
    {
        struct tm temp1;
        time_t sec;
        float msec;
        int rc;
        sec = utc/1000000;
        msec = utc/1000000.0-sec;
        localtime_r(&sec, &temp1);
        temp1.tm_year += 1900;
        temp1.tm_mon += 1;
        rc = sprintf(clock, "%04d-%02d-%02d %02d:%02d:%02d",
                        temp1.tm_year,
                        temp1.tm_mon,
                        temp1.tm_mday,
                        temp1.tm_hour,
                        temp1.tm_min,
                        temp1.tm_sec);
        clock[rc] = '\0';
    }

生成Date

static char * g_weekstr[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    static char * g_monthstr[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    /*generate the current date string*/
    time_t now = time(NULL);
    struct tm tt;
    gmtime_r( &now, &tt );
    char timebuf[64];
    snprintf( timebuf, sizeof(timebuf),
            "%s, %02d %s %d %02d:%02d:%02d GMT",
            g_weekstr[tt.tm_wday], tt.tm_mday,
            g_monthstr[tt.tm_mon], tt.tm_year + 1900,
            tt.tm_hour, tt.tm_min, tt.tm_sec );


------------------------------ 华丽的分割线 ------------------------------------

关于scanf的返回值
Both scanf and wscanf return the number of fields successfully converted
and assigned; the return value does not include fields that were read but
not assigned. A return value of 0 indicates that no fields were assigned.
The return value is EOF for an error or if the end-of-file character or the
end-of-string character is nocountered in the first attempt to read a character.

如:scanf("%d%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。


void main()
{
    int a;
    int b;
    int c;
    int x;
    printf("请输入三个整数:");
    x=scanf("%d%d%d",&a,&b,&c);
    printf("%d\n%d\n",a,x);
}
输入三个整数:5 6 7则x的值为3;
输入5 6 d(即给c 赋值不正确)则x的值为2;
输入5 t d(即给b和c 赋值不正确)则x的值为1;

scanf()的返回值对我们来说也很有用的,例如可使用if(scanf("%d,%d",&a,&b)==2)这样语句来判断是否正确的给所有的变量赋值了,正确的话才能使用这个变量与运算,这样才能提高我们代码的安全性。
阅读(1790) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~