几个关于时间的概念
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);
}
转换关系
- 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