Unix时间和日期例程

几个关于时间的概念
  • Coordinated Universal Tim(UTC)
    协调世界时,又称为世界标准时间,通常也指的是格林威治标准时间(Greenwich Mean Time,GMT)。地球被分为24个时区,相邻时区相差一个小时。比如中国上海是+8区,意思就是,假如格林威治现在是27日1点0分0秒,而中国上海就是27日早上9点0分0秒。中国内地的时间与UTC的时差为+8,也就是UTC+8,美国则是UTC-5。

  • Calendar Time
    日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。

Linux设置时间

Linux 系统时钟有2个,一个是硬件时钟即BIOS时间。另一个是Linux系统kernel时间,当Linux启动时,系统kernel会去读取硬件时钟的设置,然后系统时钟就会独立于硬件运作。

  • 设置硬件时间

    # hwclock  # 查看硬件时钟
    # hwclock --set --date="06/18/14 14:55:30" # 月/日/年 时:分:秒
    
  • 同步系统和硬件时钟

    # hwclock --hctosys  # hc代表硬件时间,sys代表系统时间,表示用硬件时钟同步系统时钟
    # hwclock --systohc # 表示用系统时钟同步硬件时钟
    
  • 设置时区

    # timedatectl list-timezones | grep Shanghai    # 查找中国时区的完整名称
      Asia/Shanghai
    # timedatectl set-timezone Asia/Shanghai    # 其他时区以此类推
    
time_t
#include 

typedef long  time_t;   // 一般用来记录从1970年1月1日0时0分0秒到现在时刻的秒数
timeval结构
#include 

struct timeval {
    time_t tv_sec;         // 秒
    suseconds_t tv_usec    // 微妙
}
timespec结构
#include 

struct timespec {
    time_t tv_sec;       // 秒
    long int tv_nsec     // 纳秒
}
time函数
#include 

time_t time(time_t *calptr)                 
    函数返回值:时间戳(秒数)
                                                   
如果calptr非空,那么时间值也会写入到calptr所指的内存中
gettimeofday函数
#include 

int gettimeofday(struct timeval *restrict tp,  void *restrict tzp);
    函数返回值:总是返回0

tzp唯一合法参数是NULL

gettimeofday返回距1970年1月1日0时0分0秒的时间,将其存放于timeval 结构中。

struct tm
#include 

struct tm {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;    // day of month  [1 -~ 31] 
    int tm_mon;     // month since January [0 ~ 11]
    int tm_year;    // years since 1900
    int tm_wday;    // days since Sunday  [0 ~ 6]
    int tm_yday;    // days since 1月1日 [0 ~ 265]
    int tm_isdst;
};
gmtime和localtime函数
#include 

struct tm* gmtime(const time_t *calptr);
    函数返回值:指向分解的tm结构的指针;若出错,返回 NULL
    gmtime 将时间戳转换协调统一时间的tm结构的指针

struct tm* localtime(const time_t *calptr);
    函数返回值:指向分解的tm结构的指针;若出错,返回 NULL
    localtime 将时间戳转换成本地时间的tm结构的指针
    
strftime和strftim_l函数
#include 

size_t strftime(char *restrict buf, size_t maxsize, 
    const char* restrict format,   const struct tm* restrict tmptr);

size_t strfime_l(char *restrict buf, size_t maxsize, 
    const char* restrict format,   const struct tm *restrict tmptr, 
    locale_t locale); 

    2个函数的返回值:若有空间,返回存入数组的字符数。否则,返回0
常用格式:
格式 说明 实例
%F YYYY-MM-DD 2017-08-29
%T %H:%M:%S 21:24:52
%Y 2018
%m 08
%b 缩写的月名 Jan
%d 月日 30
%a 缩写的周日名 Thu
代码示例:
#include 
#include 

int main()
{
    time_t t;
    struct tm *tmp,*tmp2;
    char buf[64], buf2[64];

    time(&t);
      
    tmp = localtime(&t);
    strftime(buf, 64, "time and date: %F %T", tmp);
    printf("%s\n", buf);

    tmp2 = gmtime(&t);
    strftime(buf2, 64, "time and date: %F %T", tmp2);
    printf("%s\n", buf2);
}
输出:
time and date: 2018-04-28 22:05:40
time and date: 2018-04-28 14:05:40
#include 
#include 
#include 

int main(int argc, char**argv)
{
    struct timeval ti;
    struct tm *tmp;
    char buf[64];

    gettimeofday(&ti, NULL);
    tmp = localtime(&(ti.tv_sec));

    printf("%ld, %ld\n", ti.tv_sec, ti.tv_usec);
    strftime(buf, 64, "time: %F %T", tmp);
    printf("time is now: %s.%ld\n", buf, ti.tv_usec);
}
转换关系
Unix时间和日期例程_第1张图片
转换关系.jpg
  • Timestamp 类
class Timestamp
{
  public:
    static const int microSecondsPerSecond = 1000 * 1000;

  public:
    Timestamp() : microSecondsSinceEpoch_(0)
    {
    }

    explicit Timestamp(int64_t microSecondsSinceEpochArg) : microSecondsSinceEpoch_(microSecondsSinceEpochArg)
    {
    }

    std::string toString() const;

    std::string toFormattedString(bool showMicroseconds = true) const;
    
    ......

  public:
    static Timestamp now();
    ......

  private:
    int64_t microSecondsSinceEpoch_; // 从1970年1月1日0时0分0秒到现在时刻的微妙数
};

Timestamp Timestamp::now()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);

    int64_t seconds = tv.tv_sec;
    return Timestamp(seconds * Timestamp::microSecondsPerSecond + tv.tv_usec);
}

std::string Timestamp::toString() const
{
    char buf[32] = {0};
    int64_t seconds = microSecondsSinceEpoch_ / microSecondsPerSecond;
    int64_t microseconds = microSecondsSinceEpoch_ % microSecondsPerSecond;
    snprintf(buf, sizeof(buf) - 1, "%" PRId64 ".%06" PRId64 "", seconds, microseconds);

    return std::string(buf);
}

std::string Timestamp::toFormattedString(bool showMicroseconds) const
{
    char buf[32] = {0};
    time_t seconds = static_cast(microSecondsSinceEpoch_ / microSecondsPerSecond);
    struct tm tm_time;
    gmtime_r(&seconds, &tm_time);

    if (showMicroseconds)
    {
        int microseconds = static_cast(microSecondsSinceEpoch_ % microSecondsPerSecond);
        snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d",
                 tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
                 tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
                 microseconds);
    }
    else
    {
        snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d",
                 tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
                 tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
    }
    return buf;
}
进程时间
  • CPU时间
    用以度量使用的CPU资源,以时钟滴答数(clock_t)计算,每秒可以取50,60,或100个时钟滴答。

当度量一个进程的执行时间时,UNIX系统为一个进程维护了3个进程时间值

  • 时钟时间
    墙上时钟时间, 流逝的时间。
  • 用户CPU时间
    执行用户模式(非内核代码)指令所用的时间量。
  • 系统CPU时间
    该进程执行内核代码所用的时间量。
#include 

struct tms
{
    clock_t tms_utime;      // user CPU time
    clock_t tms_stime;      // system CPU time
    clock_t tms_cutime;     // user CPU time of children, 
    clock_t tms_cstime;     // system CPU time of children
}

clock_t times(struct tms *buf)
    返回值:成功,返回流逝的墙上时钟时间(时钟滴答数为单位),出错,返回-1。

times函数返回的墙上时钟时间是一个相对于过去某时刻度量的,是一个相对值。调用times,稍后再调用times,相减返回的时间才是流逝的时间绝对值。

#include     // for sysconf
#include 

int g_clockTicks = static_cast(::sysconf(_SC_CLK_TCK));

struct CpuTime
{
    double userSeconds;
    double systemSeconds;

    CpuTime() : userSeconds(0.0), systemSeconds(0.0) {   }
};

CpuTime cpuTime()
{
    CpuTime t;
    struct tms tmstmp;

    if (::times(&tmstmp) >= 0)
    {
        const double hz = static_cast(g_clockTicks);
        t.userSeconds = static_cast(tmstmp.tms_utime) / hz;
        t.systemSeconds = static_cast(tmstmp.tms_stime) / hz;
    }

    return t;
}

参考资料
[1]《UNIX环境高级编程》[美] W. Richard Stevens Stephen A. Rago

你可能感兴趣的:(Unix时间和日期例程)