时间

末鹿安然 提交于 2020-02-07 01:24:33
  • 日历时间 Calendar Time

UTC,格林威治标准时间,GMT这三个名词基本可以认为是等同的

Epoch是指UTC的1970年1月1日零点,这个时间是UNIX系统问世的大致日期

UNIX系统内部对时间的表示方式均是自Epoch以来的秒数来度量的

日历时间存储在类型为time_t的变量中

 

获取日历时间:

#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

timeval定义如下:

struct timeval
{
    time_t  tv_sec;       /* seconds */
    suseconds_t tv_usec;  /* microseconds */
};

其中,tz是一个历史产物,目前已遭废弃,应始终将其置为NULL

 

time函数返回自Epoch以来的秒数:

#include <time.h>

time_t time(time_t *tloc);

这个函数,除了返回值是秒数,其参数也是秒数、指示指向一个指针缓存区,常设置参数为空、按照以下方式使用:

t = time(NULL)

 

  • 时间转换函数

 

 

 

time_t转换为可打印格式

#include <time.h>

char *ctime(const time_t *timep);

把一个指向time_t的指针作为参数,返回一个26字节的字符串,内涵标准格式的日期和时间,包含换行符和终止字节(\0)各一,此函数会结合本地时区和DST输出结果,返回的字符串静态分配、被下次ctime会覆盖

ctime  gmtime  localtime  asctime这几个函数的返回结果会互相覆盖

 

time_t和分解时间之间的转换

#include <time.h>

struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);

gmtime将日历时间转化为对应的UTC的分解时间,localtime则会综合考虑当地时间和DST的影响,返回系统本地时间的一个分解时间。tm结构体定义:

 struct tm {
    int tm_sec;    /* Seconds (0-60) */
    int tm_min;    /* Minutes (0-59) */
    int tm_hour;   /* Hours (0-23) */
    int tm_mday;   /* Day of the month (1-31) */
    int tm_mon;    /* Month (0-11) */
    int tm_year;   /* Year - 1900 */
    int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    int tm_isdst;  /* Daylight saving time */
};

mktime()将一个本地区的分解时间翻译为time_t值,并将其作为函数结果返回

#include <time.h>

time_t mktime(struct tm *tm);

asctime()提供分解时间到打印格式的转换:

#include <time.h>

char *asctime(const struct tm *tm);

本地时区对asctime没有影响,因为其参数分解时间里已经包含了本地时间的处理了

 

另一个分解时间到打印格式的转换函数:

#include <time.h>

size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

其中,tm只想分解时间,则一个以null结尾的打印格式时间放在 s中(没有换行符),max指定s的最大长度,不包括终止空字节,若结果字符串的总长度(包含终止空字节)超过了maxsize参数指定大小,则strftime()会返回0表示出错。成功时会返回 s所指缓冲区的字节长度。而format是一个字符串,这个参数有许多选项,可用于规定 s中一些时间表示的格式。

 

打印格式时间转换为分解时间

#define _XOPEN_SOURCE       /* See feature_test_macros(7) */
#include <time.h>

char *strptime(const char *s, const char *format, struct tm *tm);

这个相当于strftime()的逆向函数,按照 format参数的格式要求,去解析由日期和时间组成的字符串 s,最后放在 tm指向的结构体中

若成功,strptime()返回一指针,指向 str中下一个未经处理的字符(这是当字符串里有一些额外信息时派上用场的),若整个 s字符串都无法正常识别,strptime()返回NULL

 

  • 时区

系统的本地时间由失去文件 /etc/localtime定义,通常链接到 /usr/share/zoneinfo 下的一个文件

设定时区是通过给TZ环境变量设置为由一冒号(:)和时区名称组成的字符串,其中时区名称定义域 /usr/share/zoneinfo中,可以用tzselect指令来逐级查询时间路径

 

  • 地区

每个地区使用的数字、货币、日期和时间之类的信息时,相关的表达书写格式有差异 —— locale的定义为:用户环境中依赖于语言和文化习俗的一个子集

地区信息维护在 /usr/share/local 路径,每个地区目录下的子目录又包括几个文件,其中描述不同类别的一些信息设置,如下表:

 

 

为程序设置地区:

#include <locale.h>

char *setlocale(int category, const char *locale);

setlocale()可设置也可查询程序的当前地区,category参数选择设置或查询地区的那一部分,使用上面表格列出的类别的常量名称,常用 LC_ALL 来指定我们要设置的地区的所有部分的值

locale参数可能是一个字符串,指定系统上已定义的一个地区(如 de_DE,en_US)

若 locale 为空字符串,则从环境变量取得地区的设置:

setLocale(LC_ALL, "")

除了LC_ALL,LANG也可以指定当前地区的所有部分的值,指示LANG优先级是最低的、LC_ALL优先级最高能够覆盖之前设置的所有内容设置的值,因此,若要指定某一地区某方面内容,可以先用LANG设置使用地区所有方面的内容默认值,然后再用具体的LC_*来定义具体需要使用的某地区的某内容定义

setLocale()返回一个指针指向表示这一类地区设置的字符串,如果我们是为了查看当前的地区设置,则可以指定locale参数为NULL

shell中可以使用 locale 指令查询当前shell内的地区环境相关信息, locale -a列出系统上定义的整套地区

 

  • 更新系统时钟

两个更新系统时钟的接口:settimeofday()和adjtime()。

这俩接口实际很少使用,因为更新系统时间通常是由工具软件维护的

#include <sys/time.h>
int settimeofday(const struct timeval *tv, const struct timezone *tz);

参数 tz已被废弃,这个函数会造成系统时间的突然变化,可能会造成有害影响

推荐使用adjtime(),它将系统时钟逐步调整到正确时间

#include <sys/time.h>

int adjtime(const struct timeval *delta, struct timeval *olddelta);

delta参数指向一个 结构体,指定需要改变的秒和微秒数,可以是整数或负数,系统时钟会根据此值快一点或慢一点逐渐调节。

adjtime执行的时间里可能无法完成所有的时间调节,所以将它剩余时间放在 olddelta里。

只将 delta设置为NULL则只关注当前未完成的时间校正信息,只将 olddelta设置为NULL则不关心剩余未完成时间校正信息。

 

  • 进程时间

进程时间是进程创建后使用的CPU时间数量,分为两部分:

用户CPU时间:用户模式下执行所花费的时间数量

系统CPU时间:在内核模式中执行所花费的时间数量

 

调用shell指令或shell中调用程序时,可以使用time 命令来获得相关进程时间:

 

 

 

系统调用 times() ,检索进程时间信息,结果返回到 buf指向的结构体里:

#include <sys/times.h>

clock_t times(struct tms *buf);
struct tms {
               clock_t tms_utime;  /* user time */
               clock_t tms_stime;  /* system time */
               clock_t tms_cutime; /* user time of children */
               clock_t tms_cstime; /* system time of children */
           };

返回值是“相对于某一点流逝的以时钟计时单元为单位的时间”,一般就是两个times结果做差用,不过有可能会有clock_t溢出的情况,所以做差也不一定准确,用gettimeofday()去计算更好些

函数 clock()提供了一个简单的接口用于取得进程时间,它返回一个值描述了调用进程使用的总的CPU时间(用户时间+系统时间):

#include <time.h>

clock_t clock(void);

注意这times()和clock()各有一个时间单位,看以下代码是如何将函数返回值换算成秒数的:

static void             /* Display 'msg' and process times */
displayProcessTimes(const char *msg)
{
    struct tms t;
    clock_t clockTime;
    static long clockTicks = 0;

    if (msg != NULL)
        printf("%s", msg);

    if (clockTicks == 0) {      /* Fetch clock ticks on first call */
        clockTicks = sysconf(_SC_CLK_TCK);
        if (clockTicks == -1)
            errExit("sysconf");
    }

    clockTime = clock();
    if (clockTime == -1)
        errExit("clock");

    printf("        clock() returns: %ld clocks-per-sec (%.2f secs)\n",
            (long) clockTime, (double) clockTime / CLOCKS_PER_SEC);

    if (times(&t) == -1)
        errExit("times");
    printf("        times() yields: user CPU=%.2f; system CPU: %.2f\n",
            (double) t.tms_utime / clockTicks,
            (double) t.tms_stime / clockTicks);
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!