如何在 POSIXlt 时间中添加/减去时间,同时在 R 中保留其类?

发布于 2024-12-26 12:06:26 字数 376 浏览 1 评论 0原文

我正在操作一些 POSIXlt DateTime 对象。例如,我想添加一个小时:

my.lt = as.POSIXlt("2010-01-09 22:00:00")
new.lt = my.lt + 3600
new.lt
# [1] "2010-01-09 23:00:00 EST"
class(new.lt)
# [1] "POSIXct" "POSIXt" 

问题是我希望 new.lt 成为一个 POSIXlt 对象。我知道我可以使用 as.POSIXlt 将其转换回 POSIXlt,但是有没有更优雅、更有效的方法来实现这一点?

I am manipulating some POSIXlt DateTime objects. For example I would like to add an hour:

my.lt = as.POSIXlt("2010-01-09 22:00:00")
new.lt = my.lt + 3600
new.lt
# [1] "2010-01-09 23:00:00 EST"
class(new.lt)
# [1] "POSIXct" "POSIXt" 

The thing is I want new.lt to be a POSIXlt object. I know I could use as.POSIXlt to convert it back to POSIXlt, but is there a more elegant and efficient way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

彩扇题诗 2025-01-02 12:06:27

简短回答:没有

长回答:

POSIXctPOSIXlt 对象是更通用的 POSIXt 类的两种特定类型(不是严格的面向对象继承)意义上,但在准面向对象实现意义上)。代码可以在这些之间自由切换。当您添加到 POSIXlt 对象时,实际使用的函数是 +.POSIXt,而不是专门用于 POSIXlt 的函数。在此函数内,参数被转换为 POSIXct ,然后进行处理(添加)。

此外,POSIXct 是距离特定日期和时间的秒数。 POSIXlt 是日期部分的列表(秒、分钟、小时、月份、月份、年份、星期几、一年中的某一天、DST 信息),因此直接添加不会产生任何结果感觉。将其转换为秒数 (POSIXct) 并添加到它确实有意义。

Short answer: No

Long answer:

POSIXct and POSIXlt objects are two specific types of the more general POSIXt class (not in a strictly object oriented inheritance sense, but in a quasi-object oriented implementation sense). Code freely switches between these. When you add to a POSIXlt object, the actual function used is +.POSIXt, not one specifically for POSIXlt. Inside this function, the argument is converted into a POSIXct and then dealt with (added to).

Additionally, POSIXct is the number of seconds from a specific date and time. POSIXlt is a list of date parts (seconds, minutes, hours, day of month, month, year, day of week, day of year, DST info) so adding to that directly doesn't make any sense. Converting it to a number of seconds (POSIXct) and adding to that does make sense.

原谅过去的我 2025-01-02 12:06:27

它可能不会明显更优雅,但

seq.POSIXt( from=Sys.time(), by="1 hour", length.out=2 )[2]

恕我直言,它更具描述性,

Sys.time()+3600;  # 60 minutes * 60 seconds

因为代码本身记录了您要使用“POSIX”“序列”增量“1 小时”,但这是一个品味问题。在 POSIXlt 上工作得很好,但请注意,无论哪种方式它都会返回 POSIXct。也适用于“天”。有关如何处理月份、夏令时等的详细信息,请参阅 help(seq.POSIXt)。

It may not be significantly more elegant, but

seq.POSIXt( from=Sys.time(), by="1 hour", length.out=2 )[2]

IMHO is more descriptive than

Sys.time()+3600;  # 60 minutes * 60 seconds

because the code itself documents that you're going for a "POSIX" "seq"uence incremented "by 1 hour", but it's a matter of taste. Works just fine on POSIXlt, but note that it returns a POSIXct either way. Also works for "days". See help(seq.POSIXt) for details on how it handles months, daylight savings, etc.

岛徒 2025-01-02 12:06:27

?POSIXlt 告诉您:

需要在两个日期时间类之间进行的任何转换都需要时区:从“POSIXlt”到“POSIXct”的转换将验证所选时区中的时间。

所以我猜想 3600 不是一个 POSIXlt 对象,有一个自动转换。

我会坚持简单的:

new.lt = as.POSIXlt(my.lt + 3600)
class(new.lt)
[1] "POSIXlt" "POSIXt"

在时间操作之前添加 as.POSIXlt 并不是那么麻烦。

?POSIXlt tells you that:

Any conversion that needs to go between the two date-time classes requires a timezone: conversion from "POSIXlt" to "POSIXct" will validate times in the selected timezone.

So I guess that 3600 not being a POSIXlt object, there is an automatic conversion.

I would stick with simple:

new.lt = as.POSIXlt(my.lt + 3600)
class(new.lt)
[1] "POSIXlt" "POSIXt"

It's not that much of a hassle to add as.POSIXlt before your time operation.

墨落画卷 2025-01-02 12:06:26

POSIXct 类对象在内部是一个允许数字计算的数值。 POSIXlt - 对象是内部列表。不幸的是,对于您的愿望,Ops.POSIXt(当您使用“+”时所调用的)使用以下代码强制转换为 POSIXct:

if (inherits(e1, "POSIXlt") || is.character(e1)) 
        e1 <- as.POSIXct(e1)

幸运的是,如果您只想花一个小时,有一个方便的替代方案添加 3600。而是使用列表结构并向小时元素添加 1:

> my.lt$hour <- my.lt$hour +1
> my.lt
[1] "2010-01-09 23:00:00"

当您想避免有关 DST 更改的棘手问题时,这种方法非常方便,至少如果您想添加天数来获得相同的时间一天中的某个时间。

编辑(添加 @sunt 的代码,证明 Ops.POSIXlt 小心处理时间“溢出”。))

my.lt = as.POSIXlt("2010-01-09 23:05:00") 
my.lt$hour=my.lt$hour+1 
my.lt
# [1] "2010-01-10 00:05:00"

POSIXct-classed objects are internally a numeric value that allows numeric calculations. POSIXlt-objects are internally lists. Unfortunately for your desires, Ops.POSIXt (which is what is called when you use "+") coerces to POSIXct with this code:

if (inherits(e1, "POSIXlt") || is.character(e1)) 
        e1 <- as.POSIXct(e1)

Fortunately, if you just want to and an hour there is a handy alternative to adding 3600. Instead use the list structure and add 1 to the hour element:

> my.lt$hour <- my.lt$hour +1
> my.lt
[1] "2010-01-09 23:00:00"

This approach is very handy when you want to avoid thorny questions about DST changes, at least if you want adding days to give you the same time-of-day.

Edit (adding @sunt's code demonstrating that Ops.POSIXlt is careful with time "overflow".))

my.lt = as.POSIXlt("2010-01-09 23:05:00") 
my.lt$hour=my.lt$hour+1 
my.lt
# [1] "2010-01-10 00:05:00"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文