关于linux中的时间和时区

这里主要讲述linux中时间和时区相关的原理。包括设置方法、配置、环境变量、以及库函数,及应用举例。

基本概念

系统时钟和硬件时钟

Linux时钟分为系统时钟 (System Clock)和硬件(Real Time Clock,简称RTC)时钟。系统时钟是指当前Linux Kernel中的时钟,而硬件时钟则是主板上由电池供电的时钟,这个硬件时钟可以在BIOS中进行设置。当Linux启动时,硬件时钟会去读取系统时钟的设置,然后系统时钟就会独立于硬件运作。

硬件时间和系统时间的同步

重新启动系统,硬件时间会读取系统时间,实现同步,但是在不重新启动的时候,需要用hwclock或clock命令实现同步。

时间和时区

UTC:协调世界时,又称世界标准时间,简称UTC,从英文国际时间/法文协调时间”Universal Time/Temps Cordonné”而来。

时区:反映与UTC的时差问题,中国大陆、香港、澳门、台湾、蒙古国、新加坡、马来西亚、菲律宾、澳洲西部的时间与UTC的时差均为+8,也就是UTC+8。各个地区的时间都是UTC结合地区的时区信息得到的。

整个地球分为二十四时区,每个时区都有自己的本地时间,他们的关系如下:

  1. UTC时间 与 GMT时间

    我们可以认为格林威治时间就是时间协调时间(GMT = UTC),格林威治时间和UTC时间都用秒数来计算的。

  2. UTC时间与本地时间

    UTC + 时区差 = 本地时间

    时区差东为正,西为负。

  3. UTC与Unix时间戳

    在计算机中看到的UTC时间都是从(1970年01月01日 0:00:00)开始计算秒数的。所看到的UTC时间那就是从1970年这个时间点起到具体时间共有多少秒。 这个秒数就是Unix时间戳。

例如:

本地(北京)在东八区, 东八区时区差记为 +0800,则:本地(北京)时间 = UTC + (+0800)

所以,不同地区, 其本地时间各不相同。

再如, 对于中国和格林,这两个地区的时区不同,得到的时间也不同。分别如下:

CST:中国标准时间(China Standard Time),与UTC时差为8,这个解释可能是针对RedHat Linux。
GMT:格林尼治标准时间(旧译格林威治平均时间或格林威治标准时间;英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。

常用命令

下面给出的是常见的命令,不同系统可能有不同的命令。

有关系统时间的命令: data,ntpupdate

有关硬件时钟的命令: hwclock/clock

时区相关命令: tzselect

配置文件与环境变量

时区信息一般首先从环境变量中去读,如果没有再从 /etc/TZ 等配置文件中去读。

所涉及的配置文件和环境变量可能会根据系统有所不同,一般情况如下:

  1. 时区的配置文件: etc/localtime (可以是/usr/share/zoneinfo…的软链接), /etc/TZ, /etc/sysconfig/clock

  2. 环境变量: TZ, 使用举例如下:

    bash中   export TZ="Europe/Moscow"        date -u -s "2011-10-29 21:55:00"
    cshell中 setenv TZ Europe/Moscow
    

库函数

这些为有关时间时区的常见系统库函数。

  • time_t time(time_t *t)

    返回 time_t 类型,值为UTC时间从0时0分0秒算起到现在所经过的秒数。

  • struct tm*gmtime(const time_t*timep)

    根据传入的 time_t 返回类型为 struct tm 结构,包含时、分、秒、日、周、月、年、日光节约时间标记等信息的时间表示,该时间为GMT时间,未经时区转换。

  • struct tm *localtime(const time_t * timep)

    根据传入的 time_t 返回类型为 struct tm 结构,包含时、分、秒、日、周、月、年、日光节约时间标记等信息的时间表示,该时间为当地时间,已经时区转换。

  • time_t mktime(struct tm * timeptr)

    struct tm 类型的时间转换为 time_t 类型,值为UTC时间从0时0分0秒算起到现在所经过的秒数。

  • char *ctime(const time_t *timep)

    将传入的 time_t 类型时间转化为现实世界中的字符串表示形式,例如: Fri, 16 Oct 2015 23:12:18 +0800

  • char * asctime(const struct tm * timeptr)

    将传入的 struct tm 结构类型时间转化为现实世界中的字符串表示形式,例如: Fri Oct 16 15:15:54 2015

  • int gettimeofday ( struct timeval * tv , struct timezone * tz )

    返回当前时间信息, struct timeval *tv 存放秒和微秒信息, struct timezone *tz 存放时区信息。

  • int settimeofday ( const struct timeval *tv,const struct timezone *tz)

    根据传入的时间信息 struct timeval *tv, 和时区信息 struct timezone *tz 设置当前时间。

总之,time_t 是用秒数表示时间一般在系统时间戳中使用(一般就是UTC时间);struct tm 使用结构体表示时间,在程序中使用(不同时区可能会有不同值);而现实中使用字符串来表示时间,字符串格式可以定制。时区信息一般首先从环境变量中去读,如果没有再从 /etc/TZ 等配置文件中去读。

应用举例

在单一进程中修改时区的方法

setenv("TZ","Europe/Moscow",1);
tzset();

时间同步校准

假设安装完系统发现时间与现实时间相差8小时。

一般是如下原因:安装系统时选择的时区是上海,而系统启动后把bios时间认为是utc时间,再根据上海所处时区,将时间+8小时给我们。这个时候的bios的时间和软件的时间便出现不一致的情况。一个代表 utc 一个代表我们设置的cst(+8时区)。

可做如下调整(例如系统为center os 6):

  1. 修改配置文件,将默认环境变量更正为上海所在时区,不使用UTC时间

    $ vi /etc/sysconfig/clock  
    ZONE="Asia/Shanghai"
    UTC=false                          
    ARC=false
    

    这个文件影响系统启动后默认的时间相关环境变量值,这里主要是 UTC=false 这个选项,设置硬件时钟不是跟utc一致。

  2. 将linux的时区设置为 上海

    $ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    

    加载配置时间环境变量的文件之前,需要指定好该文件的软链接位置,通过这个可在各个时区配置文件下通用的 /etc/localtime 软链接,可使系统能够找到刚刚设置的时区配置文件,并设置好相应的环境变量。

  3. 对准时间ntp

    $ntpdate 192.43.244.18
    

    系统启动之后,系统时间通过 ntpdate 工具在网络上获取到。

  4. 设置硬件时间和软件时间的一致并校准

    /sbin/hwclock -systohc
    

    通过这个命令,将系统时间同步至硬件始终上,这样我们的linux软件和计算机硬件都是cst时间了--并且是我们设置的上海时区。

其它

实际问题的分析案例

问题描述

在设置好国家信息之后, 主页上的时间信息并没有根据时区进行调整。重启之后,有时候会管用。

设置时间的位置其情况是:通过 putenv() 设置好 TZ 环境变量,再通过 tzset() 设置好时区信息。但是最后通过 time()localtime() 函数得到的时间信息只在进程1中起作用。

需要确认的问题

  • 环境变量的获取与设置
  • 时间/时区/时钟的概念
  • 有关时区的环境变量/配置文件/调用接口

分析原因

代码还没有深入看过,根据前面的原理分析有如下可能的原因:

有两个进程, 设置时间的进程, 和显示时间的进程。

  1. 在设置时间的进程中设置时区环境变量 TZ ,时区信息在设置时间的进程中起作用;但是设置好时区信息后,显示时间的进程仍然根据原来的环境变量 TZ 显示时间,所以显示的时间和设置的时区不一致。

  2. 需要确认的是:确认设置时间的进程设置后环境变量后,设置的值是否已正确保存到合适的位置;显示时间的进程是否会及时更新环境变量并显示,并且是否是基于设置时间进程保存的配置文件中读取信息、更新环境变量再进行显示。

参考

man 3 tzset

解决嵌入式Linux中的时区问题

linux调整系统时间和时区的方法

Linux下设置时区(通过shell设置和程序中设置)及程序中设置环境变量

linux时区时间问题ntp

Linux时间时区详解与常用时间函数

linux修改系统时间和linux查看时区、修改时区的方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容