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

but

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

Why is the timezone presented differently? It is important for me because I need to extract the time zones from my date.

base::format(time1, format="%Z")
# [1] "BST"
base::format(time2, format="%Z")
# [1] "BST"

both give the same "BST" for British Saving Time!

The issue is that "BST" does not seam to be recognized by POSIXct/POSIXlt format:

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'

I am really confused. I have 2 questions:

1/ What is the difference between POSIXct and POSIXlt formats

2/ Any one knows what time zone I can use?

"Europe/London" works with POSIXlt but not POSIXct. Plus it cannot be extracted from a time using base::format
"BST" is not recognized as a valid timezone in as.POSIXct or as.POSIXlt functions.

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
RockScience
  • 17,932
  • 26
  • 89
  • 125
  • Are the two results coming from two different operating systems, or versions? – Dirk Eddelbuettel May 20 '11 at 11:43
  • @Dirk Eddelbuettel: same computer, same version of R&packages. I am on windows XP. It seams that POSIXct evaluates the timezone, replacing Europe/London into either GMT or BST depending on the season – RockScience May 20 '11 at 11:43
  • I managed to extract the "Europe/London" from time1 with a trick *base::format(time1, format=" ", usetz = TRUE)* but it is useless it seams that as soon as I put this POSIXlt in a xts it is converted back to POSIXct and then I loose the "Europe/London" – RockScience May 20 '11 at 11:47
  • Think the warning is a Windows issue... `as.POSIXlt("2010-07-01 16:00:00", tz="BST")` works fine on OS X – tim_yates May 20 '11 at 11:49
  • @RockScience : edited your title to indicate the real problem. – Joris Meys May 20 '11 at 14:25

3 Answers3

17

@Koshke showed you already

  • the difference in internal representation of both date types, and
  • that internally, both timezone specifications are the same.

You can get the timezone out in a standardized manner using attr(). This will get the timezone in the form specified in the zone.tab file, which is used by R to define the timezones (More info in ?timezones ).

eg :

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

I am quite amazed though that POSIXct uses different indications for the timezones than POSIXlt, whereas the attributes are equal. Apparently, this "BST" only pops up when the POSIXct is printed. Before it gets printed, POSIXct gets converted again to POSIXlt, and the tzone attribute gets amended with synonyms :

> attr(as.POSIXlt(time2),"tzone")
[1] "Europe/london" "GMT"           "BST"   

This happens somewhere downstream of the internal R function as.POSIXlt, which I'm not able to look at for the moment due to more acute problems to solve. But feel free to go through it and see what exactly is going on there.

On a sidenote, "BST" is not recognized as a timezone (and it is not mentioned in zone.tab either) on my Windows 7 / R 2.13.0 install.

Joris Meys
  • 106,551
  • 31
  • 221
  • 263
7

perhaps, unclassing the objects helps you to inspect the differences:

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

thus, the POSIXlt contains the date as a list of component, while the POSIXct contains it as a numeric, i.e., UNIX epoch time.

As for the timezone, it would be beyond the scope of R.
See the explanation in http://en.wikipedia.org/wiki/Tz_database

As for the different behavior of

as.POSIXct("2010-07-01 16:00:00", tz="BST")
as.POSIXlt("2010-07-01 16:00:00", tz="BST")

I suspect there is a bug in as.POSIXct, which does not process the tz argument.

kohske
  • 65,572
  • 8
  • 165
  • 155
  • See ?DateTimeClasses -- `POSIXct` and `POSIXlt` are treated slighly differently, and, to put it mildly, *it is complicated*. Timezones are difficult to deal with, but there is no bug but just defined behaviour. – Dirk Eddelbuettel May 20 '11 at 13:14
  • 2
    Also, it is *not* "beyond the scope of R" but simply outsourced to the OS. Some OSs do it better, some do it worse. – Dirk Eddelbuettel May 20 '11 at 13:15
  • I agree that timezone is complicated. Do you think this is a defined behaviour? Please compare `attributes(.Internal(as.POSIXlt(Sys.Date(), "BST")))$tzone` with `attributes(.Internal(as.POSIXlt(Sys.Date(), "Europe/London")))$tzone ` – kohske May 20 '11 at 13:31
  • 1
    And also I meant that POSIX timezone is outsourced by "beyond the scope of R." Thanks for clarifying that. – kohske May 20 '11 at 13:35
  • 1
    obviously it is "beyond the scope of R" since by definition, "outsourced to the OS" is beyond the scope of R. R is completely confusing when it comes to dates, especially moving between Windows and Unix, and very especially on large projects with lots of timeseries in a production setting, and is one of the main reasons I have moved to Python (Pandas). POSIXlt and POSIXct will, for example, arbitrarily change your date indices by one on changeover to daylight savings time (and back) if you do not explicitly manage the timezone attributes on both Date and POSIX classes. Not obvious at all. – Thomas Browne Apr 24 '14 at 06:33
-2

1/ What is the difference between POSIXct and POSIXlt formats

  • POSIXct is seconds since the epoch
  • POSIXlt splits datetimes into %Y-%m-%d or %Y/%m/%d %H:%M:%S or other such formats
isomorphismes
  • 8,233
  • 9
  • 59
  • 70
  • `POSIXlt` is not string format, rather a list. See `unclass(as.POSIXlt(Sys.time(), "GMT"))`. You are right re `POSIXct`, see `unclass(as.POSIXct(Sys.time(), "GMT"))`. – Daniel Krizian Jan 29 '14 at 12:45
  • @DanielKrizian Fixed, I think. – isomorphismes Jan 30 '14 at 04:09
  • 1
    Still not precise, POSIXlt can be expressed in many more string formats than you suggested (see Details `?strptime`). Rather, POSIXlt is expressing the same thing as POSIXct, but in human-readable list. Also, `is.list(as.POSIXlt(Sys.time(),"GMT"))` #TRUE (FALSE for POSIXct) – Daniel Krizian Jan 30 '14 at 13:07
  • @DanielKrizian I edited again so it shouldn't look like I'm trying to be comprehensive. – isomorphismes Jan 30 '14 at 18:21
  • 1
    That's not the point. Please note that both `as.POSIXct(Sys.time(),"GMT")` and `as.POSIXlt(Sys.time(),"GMT")` get `print`ed on the screen in one of those string formats, so this is not a distinctive feature of POSIXlt. To quote from `?POSIXlt`: `POSIXlt is a named list of vectors`. Happy to lift my downvote upon correction – Daniel Krizian Jan 31 '14 at 09:32
  • @DanielKrizian from `?POSIXlt`: """ ‘"POSIXct"’ objects may also have an attribute ‘"tzone"’, a character vector of length one. If set to a non-empty value, it will determine how the object is converted to class ‘"POSIXlt"’ and in particular how it is printed. """ I'm not really worried about downvotes, thanks for the mark of good will though. – isomorphismes Jan 31 '14 at 19:10
  • @DanielKrizian No offence but lists -vs- strings seems like nit picking. I like my short, to the point answer. It's what I would want someone to tell me if I asked the quoted question. – isomorphismes Jan 31 '14 at 19:11