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

R 如何从POSIXct和POSIXlt对象中提取正确的时区?,r,timezone,posix,R,Timezone,Posix,但是 为什么时区呈现方式不同?这对我来说很重要,因为我需要从日期中提取时区 time2 = as.POSIXct("2010-07-01 16:00:00", tz="Europe/London") time2 # [1] "2010-07-01 16:00:00 BST" 两者都给予英国人相同的“BST”以节省时间 问题在于“BST”不能被POSIXct/POSIXlt格式识别: base::format(time1, format="%Z") # [1] "BST" base::forma

但是

为什么时区呈现方式不同?这对我来说很重要,因为我需要从日期中提取时区

time2 = as.POSIXct("2010-07-01 16:00:00", tz="Europe/London")
time2
# [1] "2010-07-01 16:00:00 BST"
两者都给予英国人相同的“BST”以节省时间

问题在于“BST”不能被POSIXct/POSIXlt格式识别:

base::format(time1, format="%Z")
# [1] "BST"
base::format(time2, format="%Z")
# [1] "BST"
as.POSIXlt(“2010-07-01 16:00:00”,tz=“BST”)
#[1]“2010-07-01 16:00:00英国夏令时”
#警告信息:

#1:在strtime(xx,f中,
unclass
ing对象有助于检查差异:

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'
因此,POSIXlt将日期包含为组件列表,而POSIXct将日期包含为数字,即UNIX历元时间

至于时区,它将超出R的范围。
请参见中的说明

至于不同的行为

> 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"

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

@Koshke已经向您展示了它

  • 两种日期类型的内部表示形式的差异,以及
  • 在内部,两个时区规范是相同的
您可以使用
attr()
以标准化的方式获取时区。这将以
zone.tab
文件中指定的格式获取时区,R使用该文件定义时区(更多信息,请参见
?timezones

例如:

我很惊讶POSIXct使用的时区指示与POSIXlt不同,而属性是相同的。显然,这个“BST”只有在POSIXct打印时才会弹出。在打印之前,POSIXct再次转换为POSIXlt,tzone属性用同义词修改:

> attr(time1,"tzone")
[1] "Europe/London"
> attr(time2,"tzone")
[1] "Europe/London"
这发生在内部R函数
as.POSIXlt
下游的某个地方,由于需要解决更尖锐的问题,我暂时无法查看该函数。不过,请随意浏览一下,看看那里到底发生了什么

另一方面,在我的Windows 7/R 2.13.0安装中,“BST”未被识别为时区(zone.tab中也未提及)

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

  • POSIXct
    是自
  • POSIXlt
    将日期时间拆分为
    %Y-%m-%d
    %Y/%m/%d%H:%m:%S
    或其他此类格式

这两个结果是来自两个不同的操作系统还是版本?@Dirk Eddelbuettel:同一台计算机,同一版本的R&packages。我使用的是windows XP。POSIXct评估时区,根据季节将欧洲/伦敦替换为GMT或BST。我设法提取了“欧洲/伦敦”从time1开始,使用技巧base::format(time1,format=“”,usetz=TRUE),但它是无用的,一旦我将此POSIXlt放在xts中,它就会转换回POSIXct,然后我松开“Europe/London”,认为警告是Windows问题…
as.POSIXlt(“2010-07-01 16:00:00”,tz=“BST”)
在操作系统上运行良好X@tim_yates:感谢您提供的信息请参见?DateTimeClass--
POSIXct
POSIXlt
的处理方式略有不同,说得温和一点,它是复杂的。时区很难处理,但没有bug,只是定义了行为。而且,它并没有“超出R的范围”但只是外包给操作系统。有些操作系统做得更好,有些做得更糟。我同意时区很复杂。你认为这是一种定义的行为吗?请比较
属性(.Internal(as.POSIXlt(Sys.Date(),“BST”))$tzone
属性(.Internal(as.POSIXlt(Sys.Date(),“Europe/London”))$tzone
我的意思是POSIX时区被外包给“超出R的范围”。感谢您澄清这一点。显然,这是“超出R的范围”,因为根据定义,“外包给OS”超出了R的范围。R在日期方面完全令人困惑,尤其是在Windows和Unix之间移动,尤其是在生产环境中具有大量时间序列的大型项目上,这也是我转向Python(Pandas)的主要原因之一.POSIXlt和POSIXct将,例如,在转换为夏令时(或返回)时,如果您没有明确管理date和POSIX类上的时区属性,则任意将您的日期索引更改1。一点也不明显。我同意,“欧洲/伦敦”更明确,应该优先考虑。感谢您的回答,这非常有帮助。
POSIXlt
不是字符串格式,而是一个列表。请参阅
unclass(as.POSIXlt(Sys.time(),“GMT”)
。您是对的,关于
POSIXct
,请参阅
unclass(as.POSIXct(Sys.time(),“GMT”))
@DanielKrizian修复了,我认为。仍然不精确,POSIXlt可以用比您建议的更多的字符串格式来表示(请参阅详细信息
?strtime
)。相反,POSIXlt表示的是与POSIXct相同的东西,但是人类可读的列表。此外,
是.list(如.POSIXlt(Sys.time(),“GMT”)
\TRUE(对于POSIXct为FALSE)@DanielKrizian我又编辑了一次,所以看起来不应该像是在试图全面。这不是重点。请注意
as.POSIXct(Sys.time(),“GMT”)
as.POSIXlt(Sys.time(),“GMT”)
get
print
ed以其中一种字符串格式显示在屏幕上,因此这不是POSIXlt的一个显著特征。引用
?POSIXlt
POSIXlt是一个命名的向量列表
。很高兴在更正后取消我的否决票
as.POSIXct("2010-07-01 16:00:00", tz="BST")
as.POSIXlt("2010-07-01 16:00:00", tz="BST")
> attr(time1,"tzone")
[1] "Europe/London"
> attr(time2,"tzone")
[1] "Europe/London"
> attr(as.POSIXlt(time2),"tzone")
[1] "Europe/london" "GMT"           "BST"