本文分为三个小块:

一、UNIX系统中时间的存储形式;

二、 time_t 的最大值是多少;

三、 将time_t 的最大值转化为真实世界的时间;

#---------------------#

#  欢迎诸位园友指正 #

#---------------------#

一、 时间的存储形式

UNIX下存储时间常见的有两种存储方式:

一种是time_t 这种类型,存储了从1970年到现在经过了多少秒,在UNIX系统中,time_t 是 long 类型的typedef 形式,它的定义位于文件/usr/include/time.h中。要想更精确一点,可以用结构体 struct timeval,它精确到微秒,见下列代码。

struct timeval
{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};

另一种是用一个结构体 struct tm 来分别存储年月日时分秒的,见下列代码。

struct tm
{
int tm_sec; /*秒,正常范围0-59, 但允许至61*/
int tm_min; /*分钟,0-59*/
int tm_hour; /*小时, 0-23*/
int tm_mday; /*日,即一个月中的第几天,1-31*/
int tm_mon; /*月, 从一月算起,0-11*/int tm_year; /*年, 从1900至今已经多少年*/int tm_wday; /*星期,一周中的第几天, 从星期日算起,0-6*/
int tm_yday; /*从今年1月1日到目前的天数,范围0-365*/
int tm_isdst;/*日光节约时间的旗标*/
};

需要特别注意的是,年份是从1900年起至今多少年,而不是直接存储如2011年,月份从0开始的,0表示一月,星期也是从0开始的, 0表示星期日,1表示星期一。

二、 time_t 的最大值是多少?

这个问题不难。由于time_t 是 long 类型的typedef 形式,所以time_t的最大值也即 long 类型的最大值;

对于32位操作系统,long类型的最大值为0x7FFFFFFF,转化为十进制约为21亿,而unsigned long的最大值约为42亿。见下列代码。

#include<iostream>
#include<time.h>
#include<iomanip>
using namespace std; int main(){
long long_max = 0x7FFFFFFF;
cout << dec << long_max << endl; //以十进制输出long_max的值,输出: 2147483647 time_t time_t_max = 0x7FFFFFFF;
cout << dec << time_t_max << endl; //输出: 2147483647 unsigned long unsigned_long_max = 0xFFFFFFFF;
cout << dec << unsigned_long_max << endl; //输出: 4294967295
}

三、 time_t 的最大值转化为时间

time_t的最大值已经知道了,那么如何将此最大值转化为时间呢? 库time.h 已经为我们准备了很多函数来实现这个目的。

常用的时间函数:
#include <time.h>

char *ctime(const time_t *timep);

将time_t 类型转换为真实世界的时间,以字符串显示,得到的时间是经过时区转换的时间。

 

char *asctime(const struct tm *timeptr);

将struct tm 类型转换为真实世界的时间,以字符串的形式显示,它和ctime不同在于: 1,传入的参数形式不一样; 2,不经过时区转换。

struct tm* gmtime(const time_t *timep);

将time_t 类型转换为一个struct tm 类型,得到的是没有经过时区转换的UTC时间(译为世界标准时间 or 世界协调时间)。

 

stuct tm* localtime(const time_t *timep);

将time_t 类型转换为一个struct tm 类型,和gmtime类似,但是它是经过时区转换的时间,得到的是本地时间。

有了这些函数,我们就可以将time_t 类型的最大值转换为真实世界的时间了。

最简单的一个方案: 用ctime() 函数将time_t 转换为真实时间,见下代码。

#include<stdio.h>
#include<time.h>int main() {
time_t time_t_max = 0x7FFFFFFF; printf("time_t_max = %s \n", ctime(&time_t_max));
//输出: time_t_max = Tue Jan 19 11:14:07 2038 return ;
}

也就是说32位UNIX计算机能够显示的时间最多到2038年1月19号11点14分07秒(北京时间)。但是这里有一个问题,ctime() 函数把参数转换为当地时间,它跟世界标准时间UTC并不一致,而我们要得到的是世界通用的UTC时间。

修订后方案: 用gmtime() 函数将time_h 的最大值转换成UTC时间值,再将这个strct tm 类型的数据用asctime() 函数转换成真是世界的时间。见下代码。

#include<stdio.h>
#include<time.h> int main() {
time_t time_t_max = 0x7FFFFFFF;
printf("time_t_max = %s \n", asctime(gmtime(&time_t_max)));
//输出: time_t_max = Tue Jan 19 03:14:07 2038
return ;
}

得到结果2038年1月19号03点14分07秒(UTC时间),这与北京时间有八小时的时差。

也就是说,到2038年1月19号03点14分07秒(UTC时间)这个点,32位计算机在UNIX平台存放的时间变量将溢出,超过此一瞬间,时间将会“绕回”且在内部被表示为一个负数,并造成程序无法工作,因为它们无法将此时间识别为2038年,而可能会依个别实现而跳回1970年或1901年,错误的计算及动作可能因此产生。这就是著名的2038年问题。直到2006年,仍然有数以亿计的32位系统在运行中,特别是许多嵌入式系统。相对于一般计算机科技18至24个月的革命性更新,嵌入式系统可能直至使用寿命终结都不会改变。

当然了,64位操作系统可以记录至约2900亿年后的292,277,026,596年12月4日15:30:08,星期日(UTC),完全不存在这个2038年问题。

#---------------------------------------------------------------------------------#

参考文献

《C专家编程》, Peter Van Der Linden 著, 徐波 译

cousera course: Introduction to Computing, by Li Ge

"c++ 时间类型详解 time_t", by kakaka2011

"2038年问题", by 维基百科

UNIX系统的显示时间何时会到达尽头的更多相关文章

  1. UNIX系统的显示时间何时会到尽头

    本文转载自:http://www.cnblogs.com/dfcao/p/expertCprogramming_intr0.html 本文分为三个小块: 一.UNIX系统中时间的存储形式: 二. ti ...

  2. linux 系统文件类型、系统安装时间、系统启动时间、系统运行时间、设置及显示时间、系统时间和硬件时间

    系统文件类型: 1) $mout 2) df -l:仅列出本地文件系统:-h (--human-readable):-T:文件系统类型 $df -lhf 3) file -s (--special-f ...

  3. 如何让history显示时间

    linux和unix上都提供了history命令,可以查询以前执行的命令历史记录但是,这个记录并不包含时间项目因此只能看到命令,但是不知道什么时间执行的如何让history记录时间呢? 解决方案 注意 ...

  4. 《Linux/Unix系统编程手册》读书笔记6

    <Linux/Unix系统编程手册>读书笔记 目录 第9章 这章主要讲了一堆关于进程的ID.实际用户(组)ID.有效用户(组)ID.保存设置用户(组)ID.文件系统用户(组)ID.和辅助组 ...

  5. 《Linux/Unix系统编程手册》 时间子系统

    Linux下操作系统编程有两本经典APUE即<Advanced Programming in the UNIX Environment>和TLPI<The Linux Program ...

  6. Linux date命令 - 显示和设置系统日期与时间

    操作系统上的时间也许只是当做一个时钟.特别在控制台下, 我们通常并不认为时间有什么重要的.但是对于管理员,这种认识是错误的.你知道错误的日期和时间会导致你不能编译程序么? 因为日期和时间很重要,这或许 ...

  7. CentOS下date命令 - 显示和设置系统日期与时间

    显示系统日期 要显示系统日期,只要输入: $ date Thu Dec 5 22:55:41 WIB 2013 格式化显示日期 日期有很多格式.如果你不喜欢默认的格式,你可以换一种格式.你可能会想&q ...

  8. Unix及类Unix系统文本编辑器的介绍

    概述 Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.VIM是纯粹的自由软件. Vim普遍被推崇为类Vi编辑器中最好的一个,事实上真正的劲敌来自Em ...

  9. UNIX 系统上的文本操作简介

    http://www.oschina.net/question/129540_53561 UNIX 的基本哲学之一就是创建只做一件事并将这一件事做好的程序(或进程).这一哲学要求认真考虑接口以及结合这 ...

随机推荐

  1. C# 操作数据库表和数据库

    <1>c#创建数据库表: private void CreatTable(string name)      //创建数据库源数据表,name为表名 { con.ConnectionStr ...

  2. [转]Teach Yourself Programming in Ten Years——用十年教会自己编程

    作者:Peter Norvig 译者:刘海粟 本文原文为:http://norvig.com/21-days.html 该翻译文档的PDF版可以在这里获得:http://download.csdn.n ...

  3. 基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用

    在前面介绍了三篇关于MongoDB数据库的开发使用文章,严格来讲这个不能归类于MongoDB数据库开发,不过Redis又有着和MongoDB数据库非常密切的关系,它们两者很接近,Redis主要是内存中 ...

  4. Genesis2000使用c#开发脚本

    这是我自学程序以来在博客园的第一篇博客,如有不好的地方请大家指正,谢谢! 这边文章的目的是给予那些在PCB使用Genesis2000程序脚本开发的人员提供.net平台下的开发方法. 目前genesis ...

  5. C#~异步编程再续~await与async引起的w3wp.exe崩溃

    返回目录 最近怪事又开始发生了,IIS的应用程序池无做挂掉,都指向同一个矛头,async,threadPool,Task,还有一个System.NullReferenceException,所以这些都 ...

  6. Struts2运行流程

    解释:首先浏览器发送一个请求.给/StrutsPrepareAndExecuteFilter调用doFilter()方法.创建/StrutsActionProxy执行execute()方法.有一个引用 ...

  7. 【PHP夯实基础系列】PHP日期,文件系统等知识点

    1. PHP时间 1)strtotime() //日期转成时间戳 2) date()//时间戳变成日期 <?php date_default_timezone_set("PRC&quo ...

  8. 9、ASP.NET MVC入门到精通——Controller(控制器)

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 Controller主要负责响应用户的输入.主要关注的是应用程序流,输入数据的处理,以及对相关视图(View)输出数据的提供. 继承自:Sy ...

  9. javascript中的prototype(原型)认识

    prototype实现了对象与对象的继承,在JS中变量,函数,几乎一切都是对象,而对象又有_ptoro_属性,这个属性就是通常说的原型,是用来指向这个对象的prototype对象,prototype对 ...

  10. 自己动手写ORM的感受

    之前看到奋斗前辈和时不我待前辈的自己动手写ORM系列博客,感觉讲解的通俗易懂,清晰透彻.作为一个菜鸟,闲来也想着自己写一个ORM,一来加深自己对 ORM的理解,以求对EF,NHibernate等ROM ...