Crane
Table_bottom

Search
Loading
Table_bottom

分类
Table_bottom

随机文章
Table_bottom

标签云
Table_bottom

最新评论
Table_bottom

链接
Table_bottom

功能
Table_bottom

C/C++中的日期和时间

Crane posted @ 2009年4月14日 09:09 in Programing with tags c 时间 日期 , 6370 阅读

以前看过一个笑话,有人问一geek:Can you tell me the time now?被这样回答:Of course,it's 1229883309 seconds since 1970/1/1。

笑话归笑话,但是程序员往往能从中看出点有趣的东西出来,比如说这样的时间怎么得到,怎么用程序得到?如何将这样的时间还原成看得懂的时间?这样的计时方法有没有什么优点或者不足的地方?

其实这样的时间有个名字叫日历时间(Calendar time),要得到这样的时间很容易,C标准库就有函数可以做到,在time.h中定义了一个这样的函数:

time_t time(time_t * timer);

其中的time_t是这样定义的:

#ifndef _TIME_T_DEFINED
typedef long time_t;         /* 时间值 */
#define _TIME_T_DEFINED      /* 避免重复定义 time_t */
#endif

于是通过这样的函数调用 time(NULL) 就可以得到我们需要的东西,从上面的定义中可以看到,这个值是保存在一个长整型数中的,但是我们都知道长整数是有限制的,当这个数达到这个限制的时候会发生什么事呢?这可以算是Unix/Linux系统的千年虫问题了,现在一般都是32位系统,我们知道这个最大的数是2147483647,那么这会在什么时候发生呢,其实不用太担心,在2038年才会出现,准确的说是2038年1月19日03时14分07秒,不过在这么长的时间内,硬件的发展肯定可以补上这个漏洞,所以我们大可不必担心。

下来又有一个问题,如果我们得到了一个日历时间,怎么知道真实的时间呢?

同样的在time.h中有相应的函数:

char * ctime(const time_t *timer);

这个函数可以把日历时间格式化输出,像这样的样子

Tue Jan 19 11:14:07 2038

这就是上面说到的那个时间,有8小时的时差,是因为中国和UTC时间差了8个小时的原因。

其实在C标准中还有一个表示日期和时间的数据结构:

#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

time.h还提供了两种不同的函数将日历时间(一个用time_t表示的整数)转换为我们平时看到的把年月日时分秒分开显示的时间格式tm:

struct tm * gmtime(const time_t *timer);                                          
struct tm * localtime(const time_t * timer);

还有个函数像上面说到的ctime一样,格式输出tm结构中的日期和时间。

char * asctime(const struct tm * timeptr);

看名字就知道了,asctime嘛!

来看个程序,实战:

 

  1. #include "time.h"
  2. #include "stdio.h"
  3. int main(void)
  4. {
  5.   time_t lt;
  6.   struct tm st,*pt;
  7.   lt=time(NULL);
  8.   printf("The Calendar time now is %ld\n",lt)
  9.   lt =2147483647;
  10.   printf("The bug time(local) is %s\n",ctime(&lt));
  11.   pt=gmtime(&lt);
  12.   printf("The bug time(UTC) is %s",asctime(pt));
  13.   pt=localtime(&lt);
  14.   printf("The bug time(local) is %s\n",time(pt));
  15.   system("pause");
  16.   return 0;
  17. }

会输出:

The Calendar time now is 1239709783
The bug time(local) is Tue Jan 19 11:14:07 2038

The bug time(UTC) is Tue Jan 19 03:14:07 2038
The bug time(local) is Tue Jan 19 11:14:07 2038

不过,如果我们不喜欢像Tue Jan 19 11:14:07 2038的形式,想按我们自己的想法输出,该怎么办呢,time.h还有个函数strftime,观名知义,格式化时间,原型如下:

size_t strftime(
   char *strDest,
   size_t maxsize,
   const char *format,
   const struct tm *timeptr
);

我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。

函数strftime()的操作有些类似于sprintf():识别以百分号(%)开始的格式命令集合,格式化输出结果放在一个字符串中。格式化命令说明 串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 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号

还是来个例子:

 

  1. #include <stdio.h>
  2. #include <time.h>
  3.  
  4. main( void )
  5. {
  6.   struct tm *newtime;
  7.   char tmpbuf[128];
  8.   time_t lt1;
  9.   time( &lt1 );
  10.   newtime=localtime(&lt1);
  11.   strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
  12.   printf(tmpbuf);
  13.   system("pause");
  14. }
  15.  

程序输出:

Today is Tuesday, day 14 of April in the year 2009.

呵呵,按我们自己的意愿了。

 

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter