`
javasee
  • 浏览: 919508 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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类型。

#include <time.h>
time_t time(time_t *tloc);

我们可以调用time函数来得到一个底层的时间值,这个函数会返回由纪元起点开始的秒数。如果tloc不为空指针,函数就会将返回值写入tloc所指的变量中。

试验--时间

这里是一个简单的时间程序,envtime.c,来演示time函数:

#include <time.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int i;
time_t the_time;
for(i = 1; i <= 10; i++) {
the_time = time((time_t *)0);
printf(“The time is %ld\n”, the_time);
sleep(2);
}
exit(0);
}

当我们运行这个程序时,他会每隔2秒打印出底层时间值。

$ ./envtime
The time is 1044695820
The time is 1044695822
The time is 1044695824
The time is 1044695826
The time is 1044695828
The time is 1044695830
The time is 1044695832
The time is 1044695834
The time is 1044695836
The time is 1044695838

工作原量

这个程序使用一个空指针参数来调用time函数,这个函数会返回以秒计的时间与日期值。程序会休眠2秒,并且重复调用time函数10次。

使用由1970年开始的以秒计的时间与日期值对于估量某件事持续多少时间是十分有用的。我们只需要简单的使用两个由time调用得到的时间进行减法操作即可。然而结过仔细的考虑,ISO/ANSIC C标准委员会并没有说时time_t类型要用于计量以秒计的时间间隔值,所以他们开发了一个函数,difftime,这个函数会计算两个time_t值之间的间隔,并且返回一个double类型:

#include <time.h>
double difftime(time_t time1, time_t time2);

difftime函数计算两个时间值之间的间隔,并且返回time1-time2的浮点值。对于Linux系统而言,由time返回的值是秒数,并且可以进行操作,但是为了移植考虑,我们应使用difftime函数。

为了以更为有意义的方式来表示时间与日期,我们需要将时间值转换为可以识别的时间与日期。这有标准的函数可以帮助我们做到。

gmtime函数将底层的时间值分隔并且存放到包含更为通用域的一个结构中:

#include <time.h>
struct tm *gmtime(const time_t timeval);

tm结构的定义至少包含下列成员:

成员 描述
int tm_sec 秒,0-61
int tm_min 分,0-59
int tm_hour 时,0-23
int tm_mday 一月中的天,1-31
int tm_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函数打印当前时间与日期:

#include <time.h>
#include <stdio.h>
int main()
{
struct tm *tm_ptr;
time_t the_time;
(void) time(&the_time);
tm_ptr = gmtime(&the_time);
printf(“Raw time is %ld\n”, the_time);
printf(“gmtime gives:\n”);
printf(“date: %02d/%02d/%02d\n”,
tm_ptr->tm_year, tm_ptr->tm_mon+1, tm_ptr->tm_mday);
printf(“time: %02d:%02d:%02d\n”,
tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);
exit(0);
}

当我们运行这个程序时,我们会得到更可读的时间与日期值:

$ ./gmtime; date
Raw time is 1044696004
gmtime gives:
date: 103/02/08
time: 09:20:04
Sat Feb 8 09:20:04 GMT 2003

工作原理

这个程序调用time函数得到一个底层的时间值,然后调用gmtime将其转换为一个具有时间与日期值的结构。程序会使用printf函数打印输出。严格来讲,我们不应使用这种方式打印原始时间,因为并不能保证在所有的系统他都是一个long类型。在gmtime函数之后,我们立即运行date命令来比较其输出。

然而,在这里我们一个小问题。如果我们在一个不使用格林尼治时间的时区运行这个程序,或者是我们本地的白天存储时间是有效的(问题?),我们就会注意到这个时间并不正确。这是因为gmtime是使用GMT返回时间。Linux与Unix系统这样做,从而世界上的程序与系统都是同步的。不同时区在同一时间创建的文件会显示出具有相同的创建时间。要查看本地时间,我们需要使用localtime函数来代替。

#include <time.h>
struct tm *localtime(const time_t *timeval);

localtime函数与gmtime相同,所不同的是他会返回一个包含为本地时区进行过调整后的结构。如果我们再次试验gmtime程序,但是使用localtime函数来替换gmtime,我们就会看到一个正确的时间与日期报告。

要将一个打乱的tm结构转换为一个原始的time_t值,我们可以使用mktime函数:

#include <time.h>
time_t mktime(struct tm *timeptr);

如果结构不可以表示为一个time_t值,mktime函数会返回-1。

与date程序所提供的时间与日期等机器值相反,为了友好,我们可以使用asctime与ctime函数:

#include <time.h>
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timeval);

asctime函数返回一个代表tm结构timeptr给出的时间与日期的字符串。返回的字符串的格式如下:

Sun Jun 6 12:30:34 1999\n\0

他总是26个字符长的固定格式。函数ctime与下面的函数调用等同:

asctime(localtime(timeval))

他使用一个原始时间值作为参数,并将其转换为一个更可读的本地时间。

试验--ctime

让我们使用下面的代码来实际的看一下ctime:

#include <time.h>
#include <stdio.h>
int main()
{
time_t timeval;
(void)time(&timeval);
printf(“The date is: %s”, ctime(&timeval));
exit(0);
}

将其保存为ctim.c,编译运行,我们应可以看到下面的输出:

$ ./ctime
The date is: Sat Feb 8 09:21:17 2003

工作原理

ctime.c程序调用time函数来得到一个底层的时间值,然后让ctime来完成所有的困难工作,将其转换为一个可读的字符串并打印输出。

为了可以对实际的时间与日期字符串进行更多的控制,Linux与现代的类Unix系统提供了strftime函数。这与用在日期与时间上的sprintf函数相类似,且其工作方式也相似:

#include <time.h>
size_t strftime(char *s, size_t maxsize, const char *format, struct tm *timeptr);

strftime函数会格式化由timeptr指向的tm结构表示的时间与日期,并将其结构放在字符串s中。字符串被指明至少maxsize字符长。format字符串用来控制写入字符串的字符。与printf相似,他包含要传递到字符串的通常字符与格式化时间与日期元素的转义说明。转义说明包括:

转义符 描述
%a 简写的星期名
%A 全写的星期名
%b 简写的月名
%B 全写的月名
%c 日期与时间
%d 一月中的天,01-31
%H 时,00-23
%I 12小时时钟表示的小时,01-12
%j 一年中的天,001-366
%m 一年中的月,01-12
%M 分,00-59
%P a.m或p.m
%S 秒,00-61
%u 星期中的天,1-7(星期1为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结构:

#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *timeptr);

format字符串的组成与strftime的格式化字符串完全相同。strptime的动作形为与sscanf相似,因为他们都搜索字符串,查找标识的域,然后将他们写入变量。在这里的变量为依据格式化字符串要填充的tm结构的成员。然而,与strftime的转义字符比起来,strptime的转义字符是不严密的,因为strptime会在天与月上允许简写与全名两种形式。每一个表示都会匹配strptime中的一个%a说明符。strftime总是在小于10的数字上添加0,而strptime会将其看作可选的。

strptime会返回一个指向转换操作中最后一个处理字符之后的字符的指针。如果遇到不可以转换的字符,转换操作就简单的在那里停止。调用程序需要检测以确保所传递的字符都是可以写入tm结构的有意义的字符。

试验--strftime与strptime

下面我们看一下下面的程序中所使用的转义字符:

#include <time.h>
#include <stdio.h>
int main()
{
struct tm *tm_ptr, timestruct;
time_t the_time;
char buf[256];
char *result;
(void) time(&the_time);
tm_ptr = localtime(&the_time);
strftime(buf, 256, “%A %d %B, %I:%S %p”, tm_ptr);
printf(“strftime gives: %s\n”, buf);
strcpy(buf,”Sat 26 July 2003, 17:53 will do fine”);
printf(“calling strptime with: %s\n”, buf);
tm_ptr = &timestruct;
result = strptime(buf,”%a %d %b %Y, %R”, tm_ptr);
printf(“strptime consumed up to: %s\n”, result);
printf(“strptime gives:\n”);
printf(“date: %02d/%02d/%02d\n”,
tm_ptr->tm_year % 100, tm_ptr->tm_mon+1, tm_ptr->tm_mday);
printf(“time: %02d:%02d\n”,
tm_ptr->tm_hour, tm_ptr->tm_min);
exit(0);
}

当我们运行这个程序strftime.c时,我们会得到下面的输出:

$ ./strftime
strftime gives: Sunday 06 June, 11:55 AM
calling strptime with: Sat 26 July 2003, 17:53 will do fine
strptime consumed up to: will do fine
strptime gives:
date: 03/07/26
time: 17:53

工作原理

strftime程序通过调用time与localtime函数得到当前的本地时间。然后他通过使用一个合适的格式化字符串作为参数来调用strftime将其转换为可读的格式。为了演示strptime的用法,程序设置了一个包含日期与时间的字符串,然后调用strptime来得到原始的时间与日期值,并且打印输出。转义字符%R是strptime中%H:%M的简写形式。

在这里要注意的一点就是,为了可以成功的搜索一个日期,strptime函数需要一个精确的格式化字符串。通常,他并不会精确的搜索由用户读取的时间,除非这个格式是非常严格的。

也许当我们编译strftime.c时,编译器会提出警告。这是因为GNU库默认并没有声明strftime。这个问题的修正方法就是通过在包含time.h之前添加下面的行来显示的请求X/Open标准特征:

#define _XOPEN_SOURCE
分享到:
评论

相关推荐

    Linux-C编程常用API接口-函数

    4 日期时间篇 22 5 内存及字符串操作篇 28 6 常用数学函数篇 45 7 用户组篇 56 8 数据结构及算法篇 78 9 文件操作篇 85 10 文件内容操作篇 94 11 进程操作篇 109 12 文件权限控制篇 130 13 信号处理篇 153 14 接口...

    Linux简明教程.rar

    2.显示日期时间 3.记录会话信息 五、压缩和归档文件--------------------------------------------------------------------------------- 1.压缩文件 2.解压缩文件 3.其他压缩方法 4.打包和解包文件 六、...

    linux_c-code.zip_linux 文件操作_linux编程

    Linux 编程资料 内容:环境变量、接口处理、日期时间、文件操作、信号处理等

    Linux-C编程API函数(掌握这些足够).pdf

    4 日期时间篇 5 内存及字符串操作篇 6 常用数学函数篇 7 用户组篇 8 数据结构及算法篇 9 文件操作篇 10 文件内容操作篇 11 进程操作篇 12 文件权限控制篇 13 信号处理篇 14 接口处理篇 15 环境变量篇 16 终端控制...

    linux下配置NTP架设本地时间服务器

    在linux下,我们可以通过自带的NTP(Network Time Protocol)协议通过网络使自己的系统保持精确的时间。 NTP是用来使系统和一个精确的时间源保持时间同步的协议。建议大家在自己管理的网络中建立至少一台时间服务器来...

    LINUX操作系统(电子教案,参考答案)

    2.2.2 查询、修改日期与时间 14 2.2.3 观看月历 15 2.2.4 清屏 16 2.2.5 获取注册信息 16 2.2.6 与其他用户作简单通讯 17 2.2.7 观看主机配置情况 18 2.2.8 寻找命令使用方法 18 2.3 退出Linux 19 2.3.1 注销 19 ...

    《Linux操作系统》课程标准.doc

    移动应用开发 开设时间: 学 时 数:56学时 一、课程概述 (一)课程性质 Linux操作系统的主要任务是有关Linux操作系统的安装与使用,让学生理解操作系 统的组成及工作原理,掌握Linux操作系统的安装,图形化界面的...

    cmd操作命令和linux命令大全收集

    date /t 、 time /t 使用此参数即“DATE/T”、“TIME/T”将只显示当前日期和时间,而不必输入新日期和时间 set 指定环境变量名称=要指派给变量的字符 设置环境变量 set 显示当前所有的环境变量...

    LINUX安装与配置简明手册

    5.1.1 Linux操作系统与DOS和NT的比较 51 5.1.2 文件存取权限和所有权限 51 5.2 快速解决方案 52 5.2.1 设置日期 52 5.2.2 设置时间 52 5.2.3 列出目录的内容清单 52 5.2.4 切换目录路径 53 5.2.5 确定自己所在的位置...

    根据文件日期创建日期文件夹并移动文件.rar

    本程序能在WINDOWS环境或者LINUX下直接运行。应用举例:摄像机中有很多不同时间拍摄的文件,如果手动将文件移动到硬盘,并创建相应时间文件夹,是一件比较繁琐的工作,而通过本程序就能全自动操作。

    LINUX网站建设技术指南

    8.7.2 日期时间围数 8.7.3 PHP的数据库功能及对MySQL数据库访问 第9章 建立BBS服务器 9.1 BBS服务器概述 9.2 Firebird BBS系统建站准备 9.2.1 最初的准备工作 9.2.2 BBS相关帐号的设置 9.3 Firebird BBS服务器系统...

    Linux Shell程序设计 Ubuntu 实验二

    仅供参考,异地ing要在自己的虚拟机上面跑...这个主要是关于Ubuntu机器的一些shell程序设计的一些题,用于浙江工业大学的一个计算机学院Linux课的实验,我拿来直接用,帮我挣点分,我也想从这上面下载一点有用的知识。

    东南大学Robocup机器人比赛培训资料(包括仿真平台和基础源码)

    suse Linux 环境下编译运行,注意,必须安装好开发环境和仿真环境。 --------------------------------------------------------------- ·3.文件组成形式 格式:tar.gz 创建日期 时间 文件大小 文件名 2008-10-15 ...

    Linux操作系统实验一.doc

    1、掌握在虚拟机环境下安装 Linux系统 2、熟练掌握基本 shell命令 3、熟练掌握shel1高级操作 二、 开发工具和运行环境 Vmware15虚拟机,Centos7的iso镜像文件 三、 实验内容 1、在虚拟机环境下安装 CentOS7操作系统 ...

    linux 常用 c 库函数

    包含linux环境下的数学函数、环境变量、接口处理、进程操作、内存及字符串操作、日期时间、文件操作、信号处理、用户组、终端控制 等各种常用库函数的用法介绍 值得参考一下

    Linux查看History记录加时间戳的小技巧

    Linux查看History记录加时间戳小技巧 熟悉bash的都一定知道使用history可以输出你曾经输入过的历史命令,例如 [root@servyou_web ~]# history | more 6 ./test.sh 7 vim test.sh 8 ./test.sh 但是这里只显示了...

    RED HAT LINUX 6大全

    第一部分 Red Hat Linux的介绍与安装 第1章 Red Hat Linux和UNIX简介 1 1.1 Linux的优点 2 1.2 版权和保证 3 1.3 在哪里可以获取Red Hat Linux 3 1.4 系统需求 3 1.5 小结 4 第2章 Red Hat系统的安装 5 2.1 准备,...

    入门学习Linux常用必会60个命令实例详解doc/txt

    这是因为Linux和许多版本的Unix一样,提供了虚拟控制台的访问方式,允许用户在同一时间从控制台(系统的控制台是与系统直接相连的监视器和键盘)进行多次登录。每个虚拟控制台可以看作是一个独立的工作站,工作台...

    Linux C 函数使用手册 chm.rar

    Linux C 函数手册主要涉及内容大致如下:用户组、信号处理、内存控制、字符测试、接口处理、文件操作、日期时间、环境变量、终端控制、进程操作、数学函数、字符串转换、数据结构及算法、内存及字符串操作。...

    LINUX与UNIX SHELL编程指南(很全)

    第三部分 登录环境 第13章 登录环境 125 13.1 /etc/profile 125 13.2 用户的$HOME.profile 128 13.3 stty用法 129 13.4 创建.logout文件 131 13.5 小结 131 第14章 环境和shell变量 132 14.1 什么是shell变量 132 ...

Global site tag (gtag.js) - Google Analytics