[R] Time zones in POSIClt objects

Rui Barradas ru|pb@rr@d@@ @end|ng |rom @@po@pt
Fri Oct 11 11:56:43 CEST 2024


Às 15:13 de 10/10/2024, Jeff Newmiller via R-help escreveu:
> POSIXt vectors do not support different time zones element-to-element.
> 
> If you want to keep track of timezones per element, you have to create a vector of timestamps (I would recommend POSIXct using UTC) and a parallel vector of timezone strings. How you manipulate these depends on your use cases, but from R's perspective you will have to manipulate them element-by-element.
> 
> I complained about this on this list a couple of decades ago, and was chastised for it. Evidently handling timezones per element was considered to be too impractically slow to be a standard feature.
> 
> On October 10, 2024 6:46:19 AM PDT, Jan van der Laan <rhelp using eoos.dds.nl> wrote:
>>
>> It is not completely clear to me how time zones work with POSIXlt objects. For POSIXct, I can understand what happens: time is always stored in GMT, the `tzone` attribute only affects how the times are displayed. All computations etc. are done in GMT.
>>
>> POSIXlt objects have both a `tzone` attribute and a `zone` field. It seems that the `zone` field is largely ignored. It only seems to be used for displaying the times, but does not seem to play a role when doing arithmetic and conversions of the times.
>>
>> For example below, we have the same times in two different time zones. The following seems to do what I expect: when we subtract the two times we get the difference in time between the two time zones:
>>
>> t1 <- as.POSIXlt(c("2024-01-01 12:30", "2024-01-01 12:30"), tz = "GMT")
>> t1$zone
>> # [1] "GMT" "GMT"
>>
>> t2 <- as.POSIXlt(c("2024-01-01 12:30", "2024-01-01 12:30"))
>> t2$zone
>> # [1] "CET" "CET"
>>
>> t1 - t2
>> # Time differences in hours
>> # [1] 1 1
>>
>>
>> When I change the `tzone` attribute of t1 to that of t2:
>>
>> attr(t1, "tzone") <- attr(t2, "tzone")
>> t1
>> #[1] "2024-01-01 12:30:00 GMT" "2024-01-01 12:30:00 GMT"
>>
>> The times are still displayed as being in GMT, however when I take the difference:
>>
>> t1 - t2
>> #Time differences in secs
>> #[1] 0 0
>>
>> We get a difference of 0. So it seems that the difference is only based on the `tzone` attribute. The value of `zone` is completely ignored.
>>
>> I am aware of the following remark in ?POSIXlt on arithmetic operations
>> | Be aware that ‘"POSIXlt"’ objects will be interpreted as being in
>> | the current time zone for these operations unless a time zone has
>> | been specified.
>>
>> but this does not explain this, I think.
>>
>> One of the reasons, I ask, is that I have (potentially) times in different time zones. Using POXIXlt objects seems like they could store/support this. But working with this seems unpractical as the `zone` field does not seem to do anything:
>>
>> t1$zone <- c("CET", "GMT")
>> t1 - t2
>> #Time differences in secs
>> #[1] 0 0
>>
>> Also the `gmtoff` field does not seem to do anything. For what/where is this field used?
>>
>> t1$gmtoff <- c(3600, 0)
>> t1
>> #[1] "2024-01-01 12:30:00 CET" "2024-01-01 12:30:00 GMT"
>>
>> t1 - t2
>> #Time differences in secs
>> #[1] 0 0
>>
>> as.POSIXct(t1)
>> #[1] "2024-01-01 12:30:00 CET" "2024-01-01 12:30:00 CET"
>>
>> So, I am not sure what purpose the zone and gmtoff fields have. Do they have a purpose? Am I using them wrong? The reason I am asking, is that I have some times in potentially different time zones. The data I get is something like:
>>
>> times <- list(
>>   year = c(2024L, 2024L),
>>   month = c(1L, 1L),
>>   day = c(1L, 1L),
>>   hour = c(12L, 12L),
>>   minutes = c(30L, 30L),
>>   seconds = c(0, 0),
>>   timezone = c("", "GMT")
>> )
>>
>> I am looking for ways to convert this into a practical date format for working with in R. Possible time zones are only local time or UTC/GMT. I would be fine with either converting local time to GMT. What would be a good way to convert these to a format R can work with?
>>
>> Thanks for the help.
>>
>> Jan
>>
>> ______________________________________________
>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide https://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
> 
Hello,

A way to have different time zones is to store t1 and t2 in list, which 
are vectors. Just not atomic vectors.
I think it complicates what should be simple, but here it is.



# create two lists
t1 <- lapply(c("2024-01-01 12:30", "2024-01-01 12:30"), as.POSIXlt, tz = 
"GMT")
t2 <- lapply(c("2024-01-01 12:30", "2024-01-01 12:30"), as.POSIXlt, tz = 
"CET")

# this works but is it a wanted way of making simple computations?
Map(`-`, t1, t2)
#> [[1]]
#> Time difference of 1 hours
#>
#> [[2]]
#> Time difference of 1 hours

# mapply default is to simplify the result, if possible
mapply(`-`, t1, t2)
#> [1] 1 1

t1 <- lapply(c("2024-01-01 12:30", "2024-01-01 12:30"), as.POSIXlt, tz = 
"GMT")
t2 <- lapply(c("2024-01-01 12:30", "2024-01-01 12:30"), as.POSIXlt, tz = 
"CET")

# as documented in ?mapply > sapply, all attributes are lost,
# after simplification the class attribute follows the hierarchy
# NULL < raw < logical < integer < double < complex < character < list < 
expression
mapply(`-`, t1, t2) |> str()
#>  num [1:2] 1 1


# now change only one member of the list t1
attr(t1[[2]], "tzone") <- attr(t2[[2]], "tzone")

# t1 has two different time zones and the Map/mapply loops
# above still give the expected results
Map(`-`, t1, t2)
#> [[1]]
#> Time difference of 1 hours
#>
#> [[2]]
#> Time difference of 0 secs

mapply(`-`, t1, t2)
#> [1] 1 0


Hope this helps,

Rui Barradas


-- 
Este e-mail foi analisado pelo software antivírus AVG para verificar a presença de vírus.
www.avg.com



More information about the R-help mailing list