经验体会:解决Ubuntu 18.04+Windows双系统时间不同步的问题

Ubuntu和Windows双系统,开发娱乐两不误,随用随切换,岂不美哉?

然而,在美的背后,存在一个让人抓狂的Bug:从一个系统切换到另一个系统后,时间就会出错,表现为——

时差8小时。

例如:

  • Ubuntu中时间正常,但是切换回Windows后,后者的时间慢8个小时。
  • Windows中时间正常,但是切换回Ubuntu后,后者的时间快8个小时。

一个系统中时间错乱,尚可通过互联网时间同步(NTP服务器)来解决。但是切换到另一个系统后,时差问题照样如故。

为什么会出现时差?

在了解时差出现的原因之前,我们先了解以下几个时钟的概念:

系统时间 / 本地时间(System time / Local time)

指Linux系统内部的时间。我们在系统任务栏中能直接看到的时间就是系统时间。

实时时钟(Real-Time Clock, RTC)

实时时钟是PC主板上的晶振及相关电路组成的时钟电路的生成脉冲,它控制着计算机系统的时间。操作系统中所提到的RTC,指的就是在计算机主板控制下的时间,即系统时间,为计算机硬件的内部时钟。

协调世界时(Coordinated Universal Time, UTC)

协调世界时(英语:Coordinated Universal Time,法语:Temps Universel Coordonné,简称UTC)是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。

——以上描述摘自维基百科

实践中,UTC与GMT大致重合,其时间的值基本一致,但是它们在本质上各不相同。前者以原子时为依据,是确定时间值的标准,而后者则是时区上的概念,作为世界上不同地区人口生活的时间参照。

UTC也是计算机系统中的一个时间衡量标准,Ubuntu默认就将机器时间视为UTC[1]。Ubuntu 16.04及更高版本的时间管理工具timedatectl中,UTC时间被单独列出来.

CST

CST同时是以下两个时区的英文缩写:

  • 中国标准时间:China Standard Time
  • 中部标准时间(美国):Central Standard Time

如此缩写相同,在没有明确区分的情况下极易混淆,例如,笔者在小米Max上使用date命令查看时区时,输出以下结果:

$ date
Tue Sep  4 16:51:00 CST 2018

timedatectl工具的输出也不会那么明智。如果不知道这两个时区缩写相同,我还真以为系统拿美国的CST作为时区参照,使得这里的CST指的是美国标准时间了。幸好,为了避免歧义,Ubuntu的时区设置界面中特别标明了当前时区相对UTC的时差。

格林尼治标准时间(Greenwich Mean Time, GMT)

格林尼治平时(英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台当地的平太阳时,因为本初子午线被定义为通过那里的经线。

——以上描述摘自维基百科

为什么时差刚好是8个小时?

在中国,双系统导致的时差不多不少,正好是8个小时。而这8个小时的时差,正是中国所在时区东八区(GMT+8)相对于GMT的时间差。UTC正与GMT重合,加上其又是Ubuntu系统的时间依据(Ubuntu认为机器时间是UTC),因此对于时区设置为东八区的中国用户来说,这八个小时,不多不少,“刚刚好”。

前辈的解决方案

时间不同步的问题,已经是Ubuntu使用上的一个经典问题了,很多前辈都给出了解决办法,例如CSDN上 @Bruceoxl 的解决方案,点此浏览

笔者参考的就是这篇教程,根据原教程,我在下面给出进一步的解说。

方法一:Ubuntu中的设置

需要注意的是,Ubuntu会自动设置时区和时间,此时如果不进行后续的设置,机器时间就会被改写。本地时间(Local Time)就是我们在系统中使用的时间,它的值虽然正确,但这是以UTC为参照的,与机器时间存在8小时的时差。一旦重启进入仍然将机器时间视为RTC的Windows,则必会导致时间不统一。

自16.04版本起,timedatectl成为Ubuntu的时间管理工具。不带参数运行时,它会输出当前的时间,以及系统时间的一些配置参数。

以下为设置前的timedatectl输出,本地时间为笔者的实际时间,注意观察时差:

                      Local time: Fri 2018-09-07 22:32:18 CST
                  Universal time: Fri 2018-09-07 14:32:18 UTC
                        RTC time: Fri 2018-09-07 14:32:18
                       Time zone: Asia/Shanghai (CST, +0800)
       System clock synchronized: yes
systemd-timesyncd.service active: yes
                 RTC in local TZ: no

具体的操作如下:

第一步:更改硬件时间标准。为了让Ubuntu能正确显示时间,需要运行以下命令,将硬件时间由UTC改为CST。设置完成后,重启电脑生效:

sudo timedatectl set-local-rtc 1

这里要注意的是,Ubuntu官方其实是不推荐如此设置的。再次运行timedatectl,你会发现输出的下方多了一段很长的警告,还加粗了:

Warning: The system is configured to read the RTC time in the local time zone.
         This mode can not be fully supported. It will create various problems
         with time zone changes and daylight saving time adjustments. The RTC
         time is never updated, it relies on external facilities to maintain it.
         If at all possible, use RTC in UTC by calling
         'timedatectl set-local-rtc 0'.

意思是:

给出翻译

不过这一警告我们不必理会,毕竟电脑上共存的是两套构造完全不同的系统。

第二步:同步本地时间。联网打开“Ubuntu设置”→“详细信息”→“日期和时间”,开启前两个选项(“自动设置时间”和“自动设置日期”),稍等片刻。

第三步:同步机器时间。运行以下命令,将本地时间更新到硬件时间上:

最终设置的结果如下,注意观察时差:

                      Local time: Fri 2018-09-07 23:15:47 CST
                  Universal time: Fri 2018-09-07 15:15:47 UTC
                        RTC time: Fri 2018-09-07 23:15:47
                       Time zone: Asia/Shanghai (CST, +0800)
       System clock synchronized: no
systemd-timesyncd.service active: yes
                 RTC in local TZ: yes

Warning: The system is configured to read the RTC time in the local time zone.
         This mode can not be fully supported. It will create various problems
         with time zone changes and daylight saving time adjustments. The RTC
         time is never updated, it relies on external facilities to maintain it.
         If at all possible, use RTC in UTC by calling
         'timedatectl set-local-rtc 0'.
sudo hwclock --localtime --systohc 

方法二:在Windows中设置

Bruceoxl提供了另一种解决思路,在Windows中设置。打开管理员模式的命令提示符或PowerShell(在Windows+X快捷菜单中),输入以下命令[2]

reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_DWORD /d 1

原理就是:在注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation中添加一个名为RealTimeIsUniversal的值,类型为REG_DWORD,数据为1。此项的作用就是让Windows将硬件时间当作UTC,与Ubuntu的默认设置一致。

重启系统后即可生效。

总结

采用上述方法,可完美解决Ubuntu 16.04及以上版本与Windows共存时所造成的时差问题,而时差问题的根源就在于默认情况下两个操作系统对待硬件时间的标准不一致。默认地,Ubuntu会将硬件时间视为UTC,而Windows则将其视为本地时间。

注意事项

切勿在两个系统中同时设置

上述两种系统的方法不能同时适用,否则会导致两款系统的时间标准不统一。因为在Ubuntu中,我们是要把默认的机器时间标准从UTC改动出去,但在Windows中却刚好相反。时间标准不统一,造成的后果与适用本教程前一模一样,只是错乱的系统变成了Windows。

同时,若在时间标准不统一的情况下设置系统时间,还会连同硬件时间也一同产生时差,提前或延后八个小时。

参考文献


  1. Bruceoxl. Windows + Ubuntu双系统时间不一致. https://blog.csdn.net/u013162035/article/details/79151640

  2. 下面的HKEY_LOCAL_MACHINE缩写为HKLM

推荐阅读更多精彩内容