zoukankan      html  css  js  c++  java
  • UNIX系统的显示时间何时会到达尽头

    本文分为三个小块:

    一、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 
    ", ctime(&time_t_max)); 
      //输出: time_t_max = Tue Jan 19 11:14:07 2038
    
      return 0;  
    }

    也就是说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 
    ", asctime(gmtime(&time_t_max))); 
      //输出: time_t_max = Tue Jan 19 03:14:07 2038
      return 0;  
    }

    得到结果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 维基百科

  • 相关阅读:
    Android 布局中 如何使控件居中
    VGA, QVGA, HVGA, WVGA, FWVGA和iPhone显示分辨率
    [转+整理] Android 分辨率,密度,像素单位说明
    多线程的知识点总结
    集合的相关信息
    spring cloud详解
    iostat实时监控磁盘util
    Jenkins安装过程
    hdfs的block为什么设置成128M
    shell变量自增的几种方式
  • 原文地址:https://www.cnblogs.com/dfcao/p/expertCprogramming_intr0.html
Copyright © 2011-2022 走看看