4

My day starts at 2016-03-02 00:00:00. Not 2016-03-02 00:00:01.

How do I get the beginning of the day in POSIXct in local time?

My confusing probably comes from the fact that R sees this as the end-date of 2016-03-01? Given that R uses an ISO 8601?

For example if I try to find the beginning of the day using Sys.Date():

as.POSIXct(Sys.Date(), tz = "CET")
"2016-03-01 01:00:00 CET"

Which is not correct - but are there other ways?

I know I can hack my way out using a simple

as.POSIXct(paste(Sys.Date(), "00:00:00", sep = " "), tz = "CET")

But there has to be a more correct way to do this? Base R preferred.

Thorst
  • 1,590
  • 1
  • 21
  • 35
  • added tz, just to be clear - they are not the problem. The problem is that R counts 00:00:00 to the previous day, not the current. – Thorst Mar 01 '16 at 11:19

3 Answers3

8

It's a single command---but you want as.POSIXlt():

R> as.POSIXlt(Sys.Date())
[1] "2016-03-02 UTC"
R> format(as.POSIXlt(Sys.Date()), "%Y-%m-%d %H:%M:%S")
[1] "2016-03-02 00:00:00"
R> 

It is only when converting to POSIXct happens that the timezone offset to UTC (six hours for me) enters:

R> as.POSIXct(Sys.Date())
[1] "2016-03-01 18:00:00 CST"
R> 

Needless to say by wrapping both you get the desired type and value:

R> as.POSIXct(as.POSIXlt(Sys.Date()))
[1] "2016-03-02 UTC"
R> 

Filed under once again no need for lubridate or other non-Base R packages.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
2

Notwithstanding that you understandably prefer base R, a "smart way," for certain meaning of "smart," would be:

library(lubridate)
x <- floor_date(Sys.Date(),"day")

> format(x,"%Y-%m-%d-%H-%M-%S")
[1] "2016-03-02-00-00-00"

From ?floor_date:

floor_date takes a date-time object and rounds it down to the nearest integer value of the specified time unit.

Pretty handy.

Philip
  • 7,253
  • 3
  • 23
  • 31
0

Your example is a bit unclear.

You are talking about a 1 minute difference for the day start, but your example shows a 1 hour difference due to the timezone.

You can try

?POSIXct  

to get the functionality explained.

Using Sys.Date() withing POSIXct somehow overwrites your timezone setting.

as.POSIXct(Sys.Date(), tz="EET")  
 "2016-03-01 01:00:00 CET"  

While entering a string gives you

as.POSIXct("2016-03-01 00:00:00", tz="EET")  
 "2016-03-01 EET"

It looks like 00:00:00 is actually the beginning of the day. You can conclude it from the results of the following 2 inequalities

as.POSIXct("2016-03-02 00:00:02 CET")>as.POSIXct("2016-03-02 00:00:01 CET")

TRUE

as.POSIXct("2016-03-02 00:00:01 CET")>as.POSIXct("2016-03-02 00:00:00 CET")

TRUE

So somehow this is a timezone issue. Notice that 00:00:00 is automatically removed from the as.POSIXct result.

as.POSIXct("2016-03-02 00:00:00 CET")

"2016-03-02 CET"

Etienne Moerman
  • 331
  • 1
  • 9
  • 1
    No, `POSIXct` has a timezone attribute. It's not always in UTC. One just has to take care to use the `tz` parameter of `as.POSIXct`. – Roland Mar 01 '16 at 10:46
  • You are right, but that is not what I am saying. Apparently the internal representation is in seconds since 1-1-1970 (UTC timezone). Wouldn't that mean that the beginning of the new day starts at 00:00:00 UTC? That would explain Lasse's observation. – Etienne Moerman Mar 01 '16 at 11:01
  • Edited my original answer and removed most of the UTC references since the underlying issue seems to be with Sys.Date() in combination with as.POSIXct and **not** with UTC. – Etienne Moerman Mar 01 '16 at 11:49
  • Conversion from `Date` to `POSIXct` is done via `POSIXlt`. Try `as.POSIXct(as.POSIXlt(Sys.Date(), tz="EET"), tz="EET")`. – Roland Mar 01 '16 at 11:52
  • You're right that works. However the innermost timezone is unnecessary since Sys.Date() somehow overwrites the timezone. – Etienne Moerman Mar 01 '16 at 11:56
  • `Sys.Date` returns a `Date`. Timezones are not a concept relevant for dates. – Roland Mar 01 '16 at 12:00
  • Not really an answer? I didn't know Sys.Date() didn't have a time zone component, nor did I actually assume it did - but I still need to find the beginning of the day in a smart way. – Thorst Mar 02 '16 at 06:38
  • Thanks. What Roland posted yesterday works on my machine, so without the inner timezone and for CET that would become 'as.POSIXct(as.POSIXlt(Sys.Date()), tz="CET")' – Etienne Moerman Mar 02 '16 at 12:34