如何从POSIXct和POSIXlt对象中提取正确的时区?

Roc*_*nce 18 timezone posix r

time1 = as.POSIXlt("2010-07-01 16:00:00", tz="Europe/London")
time1
# [1] "2010-07-01 16:00:00 Europe/London"
Run Code Online (Sandbox Code Playgroud)

time2 = as.POSIXct("2010-07-01 16:00:00", tz="Europe/London")
time2
# [1] "2010-07-01 16:00:00 BST"
Run Code Online (Sandbox Code Playgroud)

为什么时区呈现不同?这对我很重要,因为我需要从我的约会时间中提取时区.

base::format(time1, format="%Z")
# [1] "BST"
base::format(time2, format="%Z")
# [1] "BST"
Run Code Online (Sandbox Code Playgroud)

英国拯救时间都给予同样的"BST"!

问题是"BST"不会被POSIXct/POSIXlt格式识别:

as.POSIXlt("2010-07-01 16:00:00", tz="BST")
# [1] "2010-07-01 16:00:00 BST"
# Warning messages:
# 1: In strptime(xx, f <- "%Y-%m-%d %H:%M:%OS", tz = tz) :
#   unknown timezone 'BST'
# 2: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 3: In strptime(x, f, tz = tz) : unknown timezone 'BST'
as.POSIXct("2010-07-01 16:00:00", tz="BST")
# [1] "2010-07-01 16:00:00 GMT"
# Warning messages:
# 1: In strptime(xx, f <- "%Y-%m-%d %H:%M:%OS", tz = tz) :
#   unknown timezone 'BST'
# 2: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 3: In strptime(x, f, tz = tz) : unknown timezone 'BST'
# 4: In structure(xx, class = c("POSIXct", "POSIXt"), tzone = tz) :
#   unknown timezone 'BST'
# 5: In as.POSIXlt.POSIXct(x, tz) : unknown timezone 'BST'
Run Code Online (Sandbox Code Playgroud)

我真的很困惑.我有两个问题:

1/POSIXct和POSIXlt格式有什么区别

2 /任何人都知道我可以使用的时区?

"Europe/London"适用于POSIXlt,但不适用于POSIXct.再加上它不能从一个时间使用碱::格式提取
"BST"不被识别为一个有效的时区as.POSIXctas.POSIXlt功能.

Jor*_*eys 14

@Koshke已经告诉你了

  • 两种日期类型的内部表示的差异,和
  • 在内部,两个时区规格是相同的.

您可以使用标准化方式获取时区attr().这将获得zone.tab文件中指定格式的时区,R用于定义时区(更多信息?timezones).

例如:

> attr(time1,"tzone")
[1] "Europe/London"
> attr(time2,"tzone")
[1] "Europe/London"
Run Code Online (Sandbox Code Playgroud)

虽然POSIXct使用与POSIXlt不同的时区指示,但是属性相同,我感到非常惊讶.显然,这个"BST"只在打印POSIXct时弹出.在打印之前,POSIXct再次转换为POSIXlt,并使用同义词修改tzone属性:

> attr(as.POSIXlt(time2),"tzone")
[1] "Europe/london" "GMT"           "BST"   
Run Code Online (Sandbox Code Playgroud)

这发生在内部 R函数的下游某处as.POSIXlt,由于需要解决更严重的问题,我暂时无法查看.但请随意浏览它,看看到底发生了什么.

在旁注中,在我的Windows 7/R 2.13.0安装中,"BST"不被识别为时区(在zone.tab中也没有提及).


koh*_*ske 7

或许,unclass对象可以帮助您检查差异:

> unclass(time1)
$sec
[1] 0

$min
[1] 0

... snip

$yday
[1] 181

$isdst
[1] 1

attr(,"tzone")
[1] "Europe/London"

> unclass(time2)
[1] 1277996400
attr(,"tzone")
[1] "Europe/London"
Run Code Online (Sandbox Code Playgroud)

因此,POSIXlt包含日期作为组件列表,而POSIXct包含它作为数字,即UNIX纪元时间.

至于时区,它将超出R的范围.
参见http://en.wikipedia.org/wiki/Tz_database中的解释

至于不同的行为

as.POSIXct("2010-07-01 16:00:00", tz="BST")
as.POSIXlt("2010-07-01 16:00:00", tz="BST")
Run Code Online (Sandbox Code Playgroud)

我怀疑as.POSIXct中有一个错误,它不处理tz参数.

  • 此外,它不是*"超出R的范围",而只是外包给操作系统.有些操作系统做得更好,有些操作系统做得更糟. (2认同)