linux的系统时间,linux系统修改日期与时间
时间和日期
通常程序确定时间和日期是非常有用的。也许他想要记录它的运行时间,或者他想要一个特定的时间来改变它的形状。例如,一个游戏程序可能在工作时间不运行,或者备份计划将等待更早的工作完成后才开始自动备份。
所有Unix系统都使用相同的时间和日期起点:1970年1月1日午夜GMT。这就是Unix的起源,Linux也不例外。然而,在Linux中,所有的时间都是以秒为单位的。这类似于MS-DOS处理时间的方式,只不过MS-DOS是从1980年开始的。其他系统使用其他计时开始时间。
使用定义的time_t类型处理时间。这是一个足够大的整数类型,可以包含以秒为单位的日期和时间值。在Linux系统上,它是一个长整数,它的定义和相关操作函数都在头文件time.h中定义
不要以为时间是32位。在Unix和Linux系统上使用32位time_t类型,这个时间会在2038年重叠。到那时,我们希望所有这些系统都使用大于32位的time_t类型。
#包含时间. h
time _ t time(time _ t * tloc);
我们可以调用time函数来获得一个底层的时间值,它将返回从纪元开始的秒数。如果tloc不是空指针,函数会将返回值写入tloc指向的变量。
测试时间
下面是一个简单的时间程序envtime.c,用来演示时间函数:
#包含时间. h
#包含stdio.h
#包括unistd.h
int main()
{
int I;
时间;时间;
for(I=1;i=10i ) {
the _ time=time((time _ t *)0);
printf("时间是%ld/n ",即_ time);
睡眠(2);
}
退出(0);
}
当我们运行这个程序时,它会每2秒钟打印出底部时间值。
$ ./envtime
时间是1044695820
时间是1044695822
时间是1044695824
时间是1044695826
时间是1044695828
时间是1044695830
时间是1044695832
时间是1044695834
时间是1044695836
时间是1044695838
工作数量
这个程序使用一个空指针参数来调用time函数,该函数将以秒为单位返回时间和日期值。程序会休眠2秒,反复调用时间函数10次。
使用1970年以来以秒为单位的时间和日期值来估计某件事情持续了多长时间是非常有用的。我们只需要简单的用时间调用得到的两个时间做减法。但是ISO/ANSIC C标准委员会经过慎重考虑,并没有说应该用time_t类型来度量以秒为单位的时间间隔,于是他们开发了一个函数difftime,它会计算两个time_t值之间的间隔,并返回一个double类型:
#包含时间. h
double difftime(time_t time1,time _ t time 2);
diff函数计算两个时间值之间的间隔,并返回time1-time2的浮点值。对于Linux系统,time返回的值是秒,可以操作。但是,为了便于移植,我们应该使用difftime函数。
为了以更有意义的方式表达时间和日期,我们需要将时间值转换为可识别的时间和日期。有一些标准函数可以帮助我们做到这一点。
Gmtime函数将基础时间值分开,并将其存储在包含更多常规字段的结构中:
#包含时间. h
struct TM * GM time(const time _ t time val);
tm结构的定义至少包括以下成员:
成员描述
Int _ sec秒,0-61
Int _ min,0-59
0-23时int tm_hour
1月的Int tm_mday天,1-31
一年中的Int _ mon月,0-11(一月为0)
Int tm_year自1900年以来的年数
Int tm_wday星期几,0-6 (0在星期日)
一年中的Int tm_yday天,0-365
int tm_isdst有效的天数
测试-GMTime
下面是一个程序gmtime.c,它使用tm结构和gmtime函数打印当前时间和日期:
#包含时间. h
#包含stdio.h
int main()
{
struct tm * tm _ ptr
时间;时间;
(void)时间(the _ time);
TM _ ptr=GM time(the _ time);
printf("Raw time是%ld/n ",即_ time);
printf(" gmtime gives:/n ");
printf("日期:d/d/d/n ",
tm_ptr- tm_year,tm_ptr- tm_mon 1,TM _ ptr-TM _ mday);
printf("时间:d:d:d/n ",
tm_ptr- tm_hour,tm_ptr- tm_min,TM _ ptr-TM _ sec);
退出(0);
}
当我们运行这个程序时,我们将获得更多可读的时间和日期值:
$ ./gmtime;日期
原始时间是1044696004
gmtime给出:
日期:2008年2月103日
时间:09时20分04秒
格林威治时间2003年2月8日星期六09时20分04秒
操作原理
这个程序调用time函数来获取一个底层的时间值,然后调用gmtime将其转换成一个包含时间和日期值的结构。程序将使用printf函数打印输出。严格来说,我们不应该这样打印原始时间,因为不能保证所有系统都是长型。在gmtime函数之后,我们立即运行date命令来比较它的输出。
然而,这里我们有一个小问题。如果我们在不使用GMT的时区运行这个程序,或者如果我们的本地白天存储时间有效(问题?),我们会注意到这个时间是不正确的。这是因为gmtime是使用GMT的返回时间。Linux在Unix系统上就是这么做的,这样世界上所有的程序和系统都是同步的。在不同时区同时创建的文件将显示相同的创建时间。为了检查本地时间,我们需要使用本地时间函数。
#包含时间. h
struct TM * local time(const time _ t * time val);
localtime函数与gmtime相同,只是它返回一个已针对当地时区进行了调整的结构。如果我们再次尝试gmtime程序,但是用localtime函数替换gmtime,我们将看到一个正确的时间和日期报告。
要将加扰的tm结构转换为原始time_t值,我们可以使用mktime函数:
#包含时间. h
time _ t mktime(struct TM * time ptr);
如果该结构不能用time_t值表示,mktime函数将返回-1。
与date程序提供的时间和日期等机器值相反,我们可以使用as time和ctime函数来表示友好:
#包含时间. h
char * ASC time(const struct TM * time ptr);
char * ctime(const time _ t * time val);
asctime函数返回一个字符串,表示由tm结构timeptr给出的时间和日期。返回字符串的格式如下:
孙俊6 1999年12时30分34秒不适用
他总是有26个字符长的固定格式。函数ctime相当于下面的函数调用:
asctime(本地时间(timeval))
他使用一个原始的时间值作为参数,并将其转换成可读性更好的本地时间。
测试时间
让我们用下面的代码来看看ctime:
#包含时间. h
#包含stdio.h
int main()
{
time _ t timeval
(void)时间(time val);
printf("日期是:%s ",ctime(time val));
退出(0);
}
将其保存为ctim.c,编译并运行它,我们应该会看到以下输出:
$ ./ctime
日期是:2003年2月8日星期六09:21:17
操作原理
ctime.c程序调用time函数得到一个底层的时间值,然后让ctime做所有困难的工作,转换成可读的字符串并打印出来。
为了更多地控制实际的时间和日期字符串,Linux和现代类Unix系统提供了strftime函数。这类似于用于日期和时间的sprintf函数,其工作方式类似:
#包含时间. h
size_t strftime(char *s,size_t maxsize,const char *format,struct TM * time ptr);
strftime函数对timeptr指向的tm结构所表示的时间和日期进行格式化,并将其结构放入字符串s中,该字符串的长度至少为maxsize个字符。格式字符串用于控制写入字符串的字符。与printf类似,它包含传递给字符串的常用字符和格式化的时间和日期元素的转义描述。转义描述包括:
转义字符描述
%a的缩写周名
由% a编写的星期名称。
%b的缩写月份名
%B全名
%c日期和时间
01-31年一月的%d天
%H,00-23
% i由12小时制01-12表示的小时
一年中的%j天,001-366
一年中的第%m个月,01-12
%M点,00-59
%P上午或下午
%S秒,00-61
一周的%u天,1-7(星期一是1)
一年中的第%U周,01-53(星期日是一周的第一天)
一年中的第%V周,01-53(星期一是一周的第一天)
一周中的%w天,0-6(周日为0)
%x本地格式日期
%X本地格式时间
%y小于1900的年份数字
%Y年
%Z时区名称
%% A%个字符
因此,date程序指定的通常日期对应于strftime中的格式字符串,如下所示
" %a %b %d %H:%M:%S %Y "
为了帮助读取日期,我们可以使用strptime函数,它将表示日期和时间的字符串作为参数,并创建一个表示相同日期和时间的tm结构:
#包含时间. h
char *strptime(const char *buf,const char *format,struct TM * time ptr);
格式字符串的组成与strftime的格式字符串完全相同。strptime的作用类似于sscanf,因为它们都是搜索字符串,找到标识的域,然后写入变量。这里的变量是要根据格式化字符串填充的tm结构的成员。但是,与strptime的转义字符相比,strptime的转义字符并不严格,因为strptime在日和月中既允许缩写,也允许全名。每个表示都将匹配strptime中的%a说明符。StrTime总是将0加到小于10的数上,StrTime将其视为可选。
Strptime返回一个指针,指向转换操作中最后处理的字符之后的字符。如果遇到无法转换的字符,转换操作就此停止。调用程序需要检查以确保传递的所有字符都是可以写入tm结构的有意义的字符。
测试-strftime和strptime
让我们来看看在下面的程序中使用的转义字符:
#包含时间. h
#包含stdio.h
int main()
{
struct tm *tm_ptr,timestruct
时间;时间;
char buf[256];
char *结果;
(void)时间(the _ time);
TM _ ptr=local time(the _ time);
strftime(buf,256," %A %d %B,%I:%S %p ",TM _ ptr);
printf("strftime给定:%s/n ",buf);
strcpy(buf,“2003年7月26日星期六,17:53就可以了”);
printf("调用strptime用:%s/n ",buf);
tm _ ptr=timestruct
result=strptime(buf," %a %d %b %Y,%R ",TM _ ptr);
printf("消耗的strptime高达:%s/n ",结果);
printf(" strptime gives:/n ");
printf("日期:d/d/d/n ",
tm_ptr- tm_year % 100,tm_ptr- tm_mon 1,TM _ ptr-TM _ mday);
printf("时间:d:d/n ",
tm_ptr- tm_hour,TM _ ptr-TM _ min);
退出(0);
}
当我们运行strftime.c程序时,我们得到以下输出:
$ ./strftime
strftime给出:6月6日星期日,上午11:55
用2003年7月26日,17:53调用strptime就可以了
消耗的strp时间达到:将很好
strptime给出:
日期:26年7月3日
时间:17时53分
操作原理
strftime程序通过调用time和localtime函数来获取当前的local time。然后,他调用strftime,通过使用适当的格式化字符串作为参数,将其转换为可读格式。为了演示strptime的用法,程序设置了一个包含日期和时间的字符串,然后调用strptime来获取原始的时间和日期值,并将其打印出来。转义符%R是strptime中%H:%M的缩写形式。
这里需要注意的是,为了成功地搜索日期,strptime函数需要一个精确的格式化字符串。通常,他不会精确搜索用户阅读的时间,除非格式非常严格。
可能我们编译strftime.c的时候,编译器会警告我们。这是因为GNU库默认不声明strftime。此问题的解决方法是通过在包含time.h之前添加以下行来显示请求X/Open的标准功能:
#define _XOPEN_SOURCE