Coordinated Universal Time(UTC):协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(Greenwich Mean Time,GMT)。比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。美国是UTC-5。
Epoch(新纪元)被定义为协调世界时(也成为UTC或格林尼治标准时间或者GMT)的1970年1月1日的午夜0:00。
Calendar time 是自Epoch以来所经过的秒数。
time_t (即long)
#ifndef _TIME_T_DEFINED
typedef long time_t; /* time value */
#define _TIME_T_DEFINED /* avoid multiple defines of time_t */
#endif
头文件::time.h
函数原型:time_t time(time_t *timer)
功能:获取当前系统时间
tm
#ifndef _TM_DEFINED
struct tm {
int tm_sec; /* 秒 – 取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_year; /* 年份,其值等于实际年份减去1900 */
int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/
};
#define _TM_DEFINED
#endif
struct tm {
int tm_sec; /* 秒 – 取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_year; /* 年份,其值等于实际年份减去1900 */
int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/
};
#define _TM_DEFINED
#endif
struct tm *gmtime(const time_t *timep) // covert time_t to GMT
char *asctime(const struct tm *tm) // converts the broken-down time value tm into a string with the same format as ctime().
char *ctime(const time_t *timep)
struct tm *localtime(const time_t *timep)
我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,两者的返回值都是char*型的字符串。返回的时间格式为:
星期几 月份 日期 时:分:秒 年\n\0
例如:Wed Jan 02 02:03:55 1980\n\0
星期几 月份 日期 时:分:秒 年\n\0
例如:Wed Jan 02 02:03:55 1980\n\0
size_t
无符号整数的C / C + +类型,stddef.h头文件
经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。
自定义时间格式
size_t strftime(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timep
)
我们可以根据format指向字符串中格式命令把timep中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。
%a 星期几的简写
%A 星期几的全称
%b 月分的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字,使用基于周的年
%G 年分,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%n 新行符
%p 本地的AM或PM的等价显示
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
%U 第年的第几周,把星期日做为第一天(值从0到53)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十制年份
%z,%Z 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号
%A 星期几的全称
%b 月分的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字,使用基于周的年
%G 年分,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%n 新行符
%p 本地的AM或PM的等价显示
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
%U 第年的第几周,把星期日做为第一天(值从0到53)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十制年份
%z,%Z 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号
#include <stdio.h>
#include <time.h>
void main( void )
{
struct tm *newtime;
char buf[128];
time_t time;
time( &time); // time=time(NULL);
newtime=localtime(&time);
strftime( buf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
printf(buf);
}
运行结果:
Today is Saturday, day 30 of July in the year 2005.
#include <time.h>
void main( void )
{
struct tm *newtime;
char buf[128];
time_t time;
time( &time); // time=time(NULL);
newtime=localtime(&time);
strftime( buf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
printf(buf);
}
运行结果:
Today is Saturday, day 30 of July in the year 2005.
#include <stdlib.h>
int system(const char *command);
计算时间差
NAME
difftime - calculate time difference
SYNOPSIS
#include <time.h>
double difftime(time_t time1, time_t time0);
单位为秒。
分解转化时间
time_t mktime(struct tm *tm);
Linux kernel time
kernel/include/linux/time.h
#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
struct timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#define _STRUCT_TIMESPEC
struct timespec {
__kernel_time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
struct timeval {
__kernel_time_t tv_sec; /* seconds */
__kernel_suseconds_t tv_usec; /* microseconds */
};
source/arch/x86/include/asm/posix_types_32.h
typedef long
__kernel_time_t;
typedef long
__kernel_suseconds_t;
当系统启动时,内核通过读取RTC(实时时钟)来初始化实际的时间,该时间存放在xtime变量中。
xtime是内核中的全局变量:extern struct timespec xtime;
节拍率(tick rate):一秒内系统产生多少次时钟中断,内核中用HZ表示。
#define HZ 1000 // i386
节拍(tick):两次时钟中断的间隔时间。
全局变量jiffies用来记录自系统启动以来产生的节拍的总数。定义于<linux/jiffies.h>
extern unsigned long volatile jiffies;
volatile指示编译器每次访问变量时都从主内存中获得,而不是通过寄存器中的变量别名来访问。
系统自启动以来的运行时间=jiffies/HZ,单位为秒。
内核代码
asmlinkage long sys_time(time_t __user *tloc);
asmlinkage long sys_stime(time_t __user *tptr);
asmlinkage long sys_gettimeofday(struct timeval __user *tv,
struct timezone __user *tz);
asmlinkage long sys_settimeofday(struct timeval __user *tv,
struct timezone __user *tz);
asmlinkage long sys_stime(time_t __user *tptr);
asmlinkage long sys_gettimeofday(struct timeval __user *tv,
struct timezone __user *tz);
asmlinkage long sys_settimeofday(struct timeval __user *tv,
struct timezone __user *tz);
在source/include/linux/types.h中,有众多内核类型的定义。
typedef int __kernel_ timer_t;
typedef __kernel_timer_t timer_t;