Skip to content

Date conversion with as.POSIXct and as.POSIXlt (PR#9196)

8 messages · Erich Neuwirth, Brian Ripley, Gabor Grothendieck +2 more

#
Full_Name: Erich Neuwirth
Version: 2.3.1
OS: Windows XP, Linux
Submission from: (NULL) (131.130.135.167)


Converting Sys.Date() to a POSIX compliant time type in different ways 
produces inconsistent results:
[1] "2006-09-01"
[1] "2006-09-01 02:00:00 CEST"
[1] "2006-09-01"
[1] "2006-09-01 01:00:00 CEST"

Applying as.POSIXct directly or first applying as.POSIXlt and then
applying as.POSIXct produces different results.

This happens on Linux with timezone "CEST"
[1] "2006-09-01 11:03:36 CEST"
and on Windows with timezone "W. Europe Daylight Time"
[1] "2006-09-01 11:11:15 W. Europe Daylight Time"
#
erich.neuwirth at univie.ac.at writes:
Or,
Time difference of 1 hours
Time difference of -0.0003409386 secs

Whereas
Time difference of 0 secs

and
Time difference of -5 hours

So the difference is that as.POSIXct works in GMT whereas as.POSIXlt
works in the local timezone w/o DST corrections, the point of the
latter likely being that
Time difference of 181 days

comes out as an integer number of days.

BTW, the habit of format.POSIXlt dropping off the time when it is
exactly 01:00 in CEST (i.e. would have been midnight, save for
Daylight Savings Time) is a bit confusing too...  

I'm not sure any of this is actual bugs (Brian will tell us soon
enough), but it does appear at least to be underdocumented.
#
You misunderstand the role of timezones.

as.POSIXct(Sys.Date())

is in UTC, as documented.

as.POSIXlt(Sys.Date())

does not have a timezone (POSIXlt objects do not need one).

as.POSIXct(as.POSIXlt(Sys.Date()))

means

as.POSIXct(as.POSIXlt(Sys.Date()), tz="")

which is asking to interpret this in the local timezone.

I've expanded the documentation, but I see no sign you had studied it so 
that it unlikely to help you.
On Fri, 1 Sep 2006, erich.neuwirth at univie.ac.at wrote:

            

  
    
#
Note that there is some discussion in the help desk article
in R News 4/1 and a table of tested conversions at
the end of that article.    If x is of class "Date" then for
converting from Date to POSIXct the table suggests
as.POSIXct(format(x)) or as.POSIXct(format(x), tz = "GMT")
according to whether you want the current time zone or GMT.
On 9/1/06, erich.neuwirth at univie.ac.at <erich.neuwirth at univie.ac.at> wrote:
#
On Fri, 1 Sep 2006, Peter Dalgaard wrote:
[...]
(Your message crossed mine.)

I think it is not a bug and actually explicitly documented in ?as.POSIXlt.  
What may help those who have not read that documentation is to stick the 
UTC timezone on the conversion to POSIXlt.  Getting
[1] "2006-09-01 UTC"
[1] "2006-09-01 UTC"
[1] "2006-09-01 01:00:00 GMT Daylight Time"

might be helpful to non-readers.
#
Prof Brian Ripley <ripley at stats.ox.ac.uk> writes:
Hmmm, which part of ?as.POSIXlt didn't I understand? I can't seem to
spot anything pointing to -lt being different from -ct conversion (in
a week-old version of r-devel). What I do see is:


    The 'as.POSIX*' functions convert an object to one of the two
     classes used to represent date/times (calendar dates plus time to
     the nearest second).  They can convert a wide variety of objects,
     including objects of the other class and of classes '"Date"',
     '"date"' (from package 'date' or 'survival'), '"chron"' and
     '"dates"' (from package 'chron') to these classes.  Dates are
     treated as being at midnight UTC.

The last sentence would appear not to be true for as.POSIXlt; dates
are treated as midnight in the _current_ timezone ignoring DST (which
of course is undetectable in Oxford because that _is_ UTC in your
timezone) .
I have
[1] "2006-09-01 01:00:00 CEST"

and of course the whole issue is that
structure(list(sec = 0, min = 0, hour = 0, mday = 1, mon = 8,
    year = 106, wday = 5, yday = 243, isdst = 0), .Names = c("sec",
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst"
), class = c("POSIXt", "POSIXlt"))
structure(list(sec = 0, min = 0, hour = 0, mday = 1, mon = 8,
    year = 106, wday = 5, yday = 243, isdst = 0), .Names = c("sec",
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst"
), class = c("POSIXt", "POSIXlt"))

are exactly the same -- the tz arg is ignored.

The documentation in ?POSIXlt does have some hints about POSIXlt being
converted to current locale, but I still find the whole thing a bit
unclear.
#
On Fri, 1 Sep 2006, Peter Dalgaard wrote:

            
As it tells you it was treated as being in UTC, you need to tell 
subsequent conversions that it is a time in UTC, e.g.

   as.POSIXct(as.POSIXlt(Sys.Date()), tz="UTC")

It is as.POSIXct() that is doing 'dates are treated as midnight in the 
_current_ timezone ignoring DST', and that is what the documentation of 
argument 'tz' says will happen.  (Since UTC has no DST, it has specified 
that DST is not in effect, as that is part of a POSIXlt object.)

In your version of R, as.POSIXlt(Sys.Date()) did not specify a timezone 
(they are optional).  Now it does.
Which is why I have (I hope) clarified it so tz="UTC" is not needed 
explicitly anymore.
#
On 1 September 2006 at 06:25, Gabor Grothendieck wrote:
| Note that there is some discussion in the help desk article
| in R News 4/1 and a table of tested conversions at
| the end of that article.    If x is of class "Date" then for
| converting from Date to POSIXct the table suggests
| as.POSIXct(format(x)) or as.POSIXct(format(x), tz = "GMT")
| according to whether you want the current time zone or GMT.

Could we get something like this table into the on-line documentation?
Incidentally, just yesterday I was just mud-wrestling the same DST and TZ
issue ...

Dirk