为什么TZ = UTC-8会产生UTC + 8的日期?


25

洛杉矶当前时间是18:05。但是当我跑步时TZ=UTC-8 date --iso=ns,我得到:

2013-12-07T10:05:37,788173835+0800

date实用工具告诉我时间是10:05,甚至说它报告为UTC + 8。为什么?

Answers:


33

原因是将TZ=UTC-8其解释为POSIX时区。在POSIX时区格式中,3个字母是时区的缩写(可以是任意的),数字是时区落后于 UTC 的小时数。因此,UTC-8表示时区的缩写为“ UTC”,比实际UTC晚-8小时,即UTC + 8小时。

(之所以这样工作是因为Unix是在美国开发的,它落后于UTC。这种格式允许将美国时区表示为EST5,CST6等。)

您可以看到以下示例正在发生的情况:

$ TZ=UTC-8 date +'%Z %z'
UTC +0800
$ TZ=UTC8 date +'%Z %z'
UTC -0800
$ TZ=FOO-8 date +'%Z %z'
FOO +0800

ISO -0800时区格式采用相反的方法,-指示时区在UTC后面,并+指示时区在UTC之前。


嗯,我真正想要的是TZ=PST+8 date。谢谢。我还在以下位置找到了这种解释man timezone:“标准字符串指定时区的名称,并且必须是三个或更多字母字符。偏移字符串紧随标准字符串之后,并指定要添加到本地时间以获得协调世界时( UTC)。如果当地时区在本初子午线以西,则偏移为正;如果在东部时区,则偏移为负。小时必须在0到24之间,分钟和秒在0到59之间。”
Alex Henrie 2013年

3
@Alex不,你真正想要的是TZ=America/Los_Angeles。您忘记了夏令时的太平洋时间是-7。
马特·约翰逊·品脱

3
@MattJohnson,你的意思是TZ=:America/Los_Angeles。冒号表示它是Olson时区文件。在另一条评论中,他提到他想忽略夏令时,而这不会这样做。
cjm

@cjm,谢谢,您对冒号是正确的,但我没有看到该评论。
马特·约翰逊·品脱

美国,如果这意味着我们必须成为世界,那就把它带给世界EST-5 CST-6
埃文·卡罗尔

7

每当您以+/- 00:00的格式指定时区时,就是在指定offset而不是实际时区。从GNU libc 文档(遵循POSIX标准):

偏移量指定您必须将其添加到本地时间以获得协调世界时值的时间值。它的语法类似于[+ |-] hh [:mm [:ss]]。如果当地时区在本初子午线以西,则为正;如果时区在东,则为负。小时必须在0到23之间,分钟和秒必须在0到59之间。

这就是为什么它似乎与您期望的相反的原因。


2

Why?

因为POSIX需要它

如果以“-”开头,则时区应在本初子午线以东;否则,它应该是向西的(可以用可选的前面的'+'表示)。

因此,这将使时间接近[1] Los Angeles(时区文本带有任何3个字母的标签):

$ TZ=ANY8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 ANY-0800

$ TZ=GMT+8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 GMT-0800

这应该给时间接近Shanghai, ChinaPerth, Australia

$ TZ=ANY-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-24 02:47:12 ANY+0800

$ TZ=CST-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 02:47:12 CST+0800

[1]附近,因为实际上可能会有一些DST(夏令时)有效地改变了实际的“本地时间”。


1

作为一种替代方法,您可以使用命令zdump以其他时区+偏移量显示当前时间。

Zdump在命令行上命名的每个区域名称中显示当前时间。

相同规则适用于时区。在本初子午线以西位于“后面”,而在东面则在“前方”。

$ zdump PST PST Sat Dec 7 03:25:27 2013 PST

我做了这个脚本来显示几个时区+偏移,我们有兴趣使用的zdumpdate,所以我们可以对它们进行比较。

$ cat cmd.bash
#!/bin/bash

printf "\ndate: %s\n\n" "$(date)"

for tz in EST PST PST+8 PST-8 UTC UTC+8 UTC-8; do
  echo "-- timezone $tz"
  printf "zdump: %s\n" "$(zdump $tz)"
  printf "date:         %s\n" "$(TZ=$tz date +'%a %b %d %T %Y - (%Z %z)')"
  echo ""
done

然后,当你运行它,你可以看到的比较zdumpdate

$ ./cmd.bash 

date: Sat Dec  7 02:59:05 EST 2013

-- timezone EST
zdump: EST  Sat Dec  7 02:59:05 2013 EST
date:         Sat Dec 07 02:59:05 2013 - (EST -0500)

-- timezone PST
zdump: PST  Sat Dec  7 07:59:05 2013 PST
date:         Sat Dec 07 07:59:05 2013 - (PST +0000)

-- timezone PST+8
zdump: PST+8  Fri Dec  6 23:59:05 2013 PST
date:         Fri Dec 06 23:59:05 2013 - (PST -0800)

-- timezone PST-8
zdump: PST-8  Sat Dec  7 15:59:05 2013 PST
date:         Sat Dec 07 15:59:05 2013 - (PST +0800)

-- timezone UTC
zdump: UTC  Sat Dec  7 07:59:05 2013 UTC
date:         Sat Dec 07 07:59:05 2013 - (UTC +0000)

-- timezone UTC+8
zdump: UTC+8  Fri Dec  6 23:59:05 2013 UTC
date:         Fri Dec 06 23:59:05 2013 - (UTC -0800)

-- timezone UTC-8
zdump: UTC-8  Sat Dec  7 15:59:05 2013 UTC
date:         Sat Dec 07 15:59:05 2013 - (UTC +0800)

我实际上是在尝试获取太平洋标准时间的当前时间,而忽略了夏令时。
亚历克斯·亨利

1
我不得不投票反对这个,因为您猜测“ UTC-8”是不正确的。没错,只是没有按照用户的期望去做。我不认为它能回答有关为什么这样工作的问题。
jordanm

@jordanm-进行清理。
slm

1
它仍然可以解释正在发生的事情,但不能解释为什么,OP为什么要问“为什么”。我将删除我的否决票,但我仍然觉得这不是一个很好的答案。
jordanm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.