通过终端设置时区

我想通过终端更改系统时钟的时区。
可以通过以下方式实现。
tzselect

"在终端中打开一个图形用户界面(GUI)"
sudo cp /usr/share/zoneinfo/Europe/London /etc/localtime

"

将设置为GMT

"
"

但有没有办法仅使用偏移量如-1或+5来设置时区?

"
"

我需要这样做,因为我正在编写一个应用程序来调整时间偏移量或报告日志,我唯一拥有的信息是用户IP。我可以使用Web应用程序查找IP的位置,但然后我需要设置偏移量,如果我能够获取该位置的偏移量,那将会很容易,但如果我需要找到时区和城市,那将会非常麻烦。

"
"

如果有人知道如何通过+/-小时来设置系统时钟的答案就太好了。

"

请帮助我们选出被接受的答案。我认为@Mitch的回答是最好的http://askubuntu.com/a/323163/22308 - Nam G VU
1@NamGVU 不,Mitch的解决方案并不是最好的选择,它只是一个“在终端中的图形用户界面”答案。甚至OP也说过:“这个方法行不通,因为我需要从程序中更改时区,而不需要用户输入,我需要一个可以输入到终端的命令,而不是图形界面的解决方案。”这也是大多数人在寻找“终端解决方案”时所希望达到的目标,即一个适合脚本使用的解决方案。如果你知道一个城市的话,Collin Anderson的方法更好,或者如果只是简单的GMT+-n,那么Ryan的方法更适合。 - Xen2050
在Ubuntu 18.04中,tzselect不会打开图形界面。它是基于终端的菜单选择。 - Tim Richardson
8个回答

要从终端更改时区,只需在键盘上按下Ctrl+Alt+T来打开终端。当它打开时,运行以下命令:
sudo dpkg-reconfigure tzdata

打开后,只需按照屏幕提示更改时区。


14这样行不通,因为我需要在没有用户输入的情况下从程序中更改时区。我需要一个可以输入到终端的命令,而不是图形界面解决方案。谢谢回复。 - user2155009
1谢谢!这很有帮助,但我已经手动更改了 etc/timezone =) 就像 http://php.net/manual/en/timezones.php 一样!!!完全相同!!! - Vladimir Ch
重新配置tzdata似乎也会调整硬件时钟,以便在时区切换后显示的时间保持不变。如果您的时间是正确的,但时区错误,您可能希望这样做。然而,在旅行时绝对不要触碰您的硬件时钟。timedatectl方法似乎只会更改时区。 - SnakE
@SnakE对我来说,显示的时间会相应地改变。 - RiaD
我从命令行中更改了Putty,没有任何问题,为什么你这么说呢,我的朋友?@ADTC - saber tabatabaee yazdi

你还可以使用新的timedatectl在14.04中设置时间。
sudo timedatectl set-timezone America/New_York

在Ubuntu上如何安装它? - Lex Podgorny
1它在14.04上是默认安装的。 - Collin Anderson
7要查看所有可用选项,您可以运行 ls -R --group-directories-first /usr/share/zoneinfo。(请注意不要修改或删除任何文件。)有关 posixright 前缀的更多信息,请参阅此处 - ADTC
3使用sudo timedatectl set-timezone Etc/UTC来设置为UTC时间。 - Zoltán
这样你就可以在脚本中运行,当dpkg-reconfigure tzdata无法运行时。 - DimiDak
1使用sudo timedatectl list-timezones命令来显示所有可用的时区。 - AlikElzin-kilaka

我意识到这个主题有点过时了,但我正在寻找更好的解决方案,因为我需要在用户从我们的网站下载并部署虚拟机后自动设置时区。 以下是我最终採用的方案:

echo "Setting TimeZone..."
export tz=`wget -qO - http://geoip.ubuntu.com/lookup | sed -n -e 's/.*<TimeZone>\(.*\)<\/TimeZone>.*/\1/p'` &&  timedatectl set-timezone $tz
export tz=`timedatectl status| grep Timezone | awk '{print $2}'`
echo "TimeZone set to $tz"

这将在新网络上启动后从服务器查询geoip.ubuntu.com(我的脚本首先检查连通性),然后根据响应设置服务器的时区。
“wget -q0 -”告诉wget仅将结果输出到stdout,然后将其传输到$ tz变量中。
希望它能帮助某人!

1太好了!在Ubuntu 16.04上,应该是使用"grep zone"和"print $3"。 - user334639
1我提议使用一个不同的命令行界面来获取时区。在我看来,这样会更清晰一些:curl -s 'http://geoip.ubuntu.com/lookup' | xmllint --xpath '/Response/TimeZone/text()' - - Darko Miletic

您可以在/usr/share/zoneinfo/Etc中使用GMT±x文件。
sudo ln -fs /usr/share/zoneinfo/Etc/GMT$offset /etc/localtime

1这个方法有点用,但是不会更新/etc/timezone文件中的时区名称。 - poolie
1要更新/etc/timezone文件,请运行sudo dpkg-reconfigure --frontend noninteractive tzdata命令。 - Pierre Gramme

TL;DR /etc/localtime 是一个符号链接,指向 /usr/share/zoneinfo/Continent/City 中的一个文件。通过改变它所指向的位置,您可以改变时区。

为了更改时区,删除 /etc/localtime 并将符号链接分配给您想要的城市。例如,ls -l /etc/localtime 报告该文件指向 /usr/share/zoneinfo/America/Denver。要将其更改为纽约,我执行以下操作:

  1. sudo rm /etc/localtime
  2. sudo ln -s /usr/share/zoneinfo/America/New_York /etc/localtime
  3. 等待一分钟,让我的时钟更新

下面的截图显示了步骤和来自 timedatectl 的确认信息

enter image description here


了解幕后发生的事情是很好的,但你不觉得建议使用指定的工具会更好吗?比如dpkg-reconfigure tzdata等。 - Patrick Cornelissen
首先,已经有关于tzdata的答案了,因此建议同样的事情是毫无意义的。其次,tzdata几乎可以做到相同的功能。这取决于用户自己决定他们更喜欢什么,所以并没有更好或更差之分 - 只是个人喜好而已。 - Sergiy Kolodyazhnyy
1嗯,与分发工具对抗往往会导致问题,所以如果可能的话,我会避免采用你的方法,但是说实话,你的解决方案(目前)确实可行。 - Patrick Cornelissen
我所理解的是,这个解决方案可以在不同的发行版上运行。但仍然需要在 /usr/share/zoneinfo 目录中获取时区数据库。是否有一种方法可以在不安装 tzdata 包的情况下获取时区数据库? - andho
@andho 根据/var/lib/dpkg/info/tzdata.list的建议,所有位于/usr/share/zoneinfo中的项目都应该随该软件包一起安装。我会假设您确实需要安装该软件包才能获得所有项目,但老实说,我并不太确定,而且对其他发行版的工作方式也不太熟悉。建议您在[unix.se]上提出这个问题,并随时引用本帖以提供问题的背景信息。 - Sergiy Kolodyazhnyy

更新时区的简单方法是使用sudo dpkg-reconfigure tzdata。但这并不容易脚本化。
如果您想通过脚本明确设置时区(例如,用于设置虚拟机),以下是一个步骤:
为您想要的时区设置一个变量,例如其中之一:
tz=Europe/London
tz=America/Anchorage
tz=Etc/GMT+6

有效值是/usr/share/zoneinfo下的目录和文件名。
然后简单地。
sudo cp -vf /usr/share/zoneinfo/$tz /etc/localtime
echo $tz | sudo tee /etc/timezone

请注意,/etc/localtime/etc/timezone必须保持一致。
可能现在重新启动以确保所有服务都得到更新(例如cron)。

永远不要使用cp命令来设置/etc/localtime。/etc/localtime是一个指向正确文件的符号链接。如果你使用cp来更改它,实际上会覆盖当前指向的tzdata文件的内容,这样一来,UTC tzdata文件将包含Europe/London的时区数据,而不是UTC的时区数据,这是不好的(并且非常烦人,我可以从个人经验中说)。 - Foogod

这是我使用的方法,它以美国为中心,因此不需要担心非美国时区。

如果我需要确定当前时区,我会执行以下操作:

cat /etc/timezone  

或者
sudo hwclock --show  

我接下来做的是:
timedatectl set-timezone <_designation_>

其中<_designation_>是以下之一:
US/Eastern US/Central US/Mountain US/Pacific US/Alaska US/Aleutian US/Arizona US/East-Indiana US/Hawaii US/Indiana-Starke US/Michigan US/Pacific-New US/Samoa

E.G.:

timedatectl set-timezone US/Eastern  

其他时区标识可以在这里找到: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones


tzselect 是一个很好的获取时区字符串的方法。 - Martin Thoma

除非您选择要与每个时区偏移相对应的时区文件,否则无法执行此操作。

有些答案建议使用 /usr/share/zoneinfo/Etc 中的文件,但这些文件的问题在于它们不考虑夏令时。

因此,除非您选择某个时区配置来匹配每个偏移量,或者您不关心夏令时,否则无法通用地执行此操作。