[Rd] POSIXlt, POSIXct, strptime, GMT and 1969-12-31 23:59:59

From: Jeff Ryan <jeff.a.ryan_at_gmail.com>
Date: Fri, 27 Feb 2009 12:06:18 -0600


R-devel:

Some very inconsistent behavior, that I can't seem to find documented.

Sys.setenv(TZ="GMT")

str(unclass(strptime("1969-12-31 23:59:59","%Y-%m-%d %H:%M:%S"))) List of 9
$ sec : num 59
$ min : int 59
$ hour : int 23
$ mday : int 31
$ mon : int 11
$ year : int 69
$ wday : int 3
$ yday : int 364
$ isdst: int 0

# setting to 59 seconds now reports 0
str(unclass(as.POSIXlt("1969-12-31 23:59:59"))) List of 9
$ sec : num 0
$ min : int 59
$ hour : int 23
$ mday : int 31
$ mon : int 11
$ year : int 69
$ wday : int 3
$ yday : int 364
$ isdst: int 0

Setting the secs in the string to 58 returns a correct structure: str(unclass(as.POSIXlt("1969-12-31 23:59:58"))) List of 9
$ sec : num 58
$ min : int 59
$ hour : int 23
$ mday : int 31
$ mon : int 11
$ year : int 69
$ wday : int 3
$ yday : int 364
$ isdst: int 0

Some additional strangeness occurs once as.POSIXct is called:

str(as.POSIXct(as.POSIXlt("1969-12-31 23:59:58")))  POSIXct[1:1], format: "1969-12-31 23:59:58"

# this incorrectly ignores the secs
str(as.POSIXct(as.POSIXlt("1969-12-31 23:59:59")))  POSIXct[1:1], format: "1969-12-31 23:59:00"

# this should be -1, if I am not mistaken str(as.POSIXct(strptime("1969-12-31 23:59:59","%Y-%m-%d %H:%M:%S")))  POSIXct[1:1], format: NA

According to ?strptime NA should be returned if the time doesn't exist. As far as I can tell, 1969-12-31 23:59:59 does exists.

Using a simple C program (source follows this message):

[veblen:~/Rforge/xts] jryan% ./a.out
Date as tm struct (POSIXlt):1969-12-31 23:59:59

   sec: 59
   min: 59
  hour: 23
  mday: 31
   mon: 11
  year: 69
  wday: 3
  yday: 364

seconds since the Epoch: -1

Which gives the -1. This is all run on a Intel Mac, though has been tested on FreeBSD and Ubuntu as well with the same outcome. It does seem to work fine on Windows though. I think the workaround for Windows is what is causing the failure elsewhere.

As far as I can see, the code that is causing this is do_asPOSIXct in datetime.c:

 695     if(!R_FINITE(secs) || tm.tm_min == NA_INTEGER ||
 696        tm.tm_hour == NA_INTEGER || tm.tm_mday == NA_INTEGER ||
 697        tm.tm_mon == NA_INTEGER || tm.tm_year == NA_INTEGER)
 698         REAL(ans)[i] = NA_REAL;
 699     else {
 700         errno = 0;
 701         tmp = mktime0(&tm, 1 - isgmt);
 702 #ifdef MKTIME_SETS_ERRNO
 703         REAL(ans)[i] = errno ? NA_REAL : tmp + (secs - fsecs);
 704 #else
 705         REAL(ans)[i] = (tmp == (double)(-1)) ?
 706         NA_REAL : tmp + (secs - fsecs);
 707 #endif
 708     }

I haven't been able to look further into this logic, but the test for -1 strikes me as where this is happening.

Thank you for any insight you can provide.

Jeff

> sessionInfo()
R version 2.9.0 Under development (unstable) (2009-02-27 r48020) i386-apple-darwin8.11.1

locale:
C

attached base packages:
[1] stats graphics grDevices utils datasets methods base

######### C PROGRAM ######### #include <time.h>
#include <stdio.h>
/*

   code modified from:

   http://www.opengroup.org/onlinepubs/009695399/functions/strptime.html    by Jeff Ryan
*/

struct tm tm;
time_t t;

int main()
{
char DATE[] = "1969-12-31 23:59:59";
printf("Date as tm struct (POSIXlt):%s\n", DATE);

strptime(DATE, "%Y-%m-%d %H:%M:%S", &tm);

tm.tm_isdst = -1;      /* Not set by strptime(); tells mktime()
                          to determine whether daylight saving time
                          is in effect */
t = mktime(&tm);
printf(
       "   sec: %d\n"
       "   min: %d\n"
       "  hour: %d\n"
       "  mday: %d\n"
       "   mon: %d\n"
       "  year: %d\n"
       "  wday: %d\n"
       "  yday: %d\n",
       tm.tm_sec,
       tm.tm_min,
       tm.tm_hour,
       tm.tm_mday,
       tm.tm_mon,
       tm.tm_year,
       tm.tm_wday,
       tm.tm_yday);

printf("seconds since the Epoch: %d\n", t); return 0;
}

-- 
Jeffrey Ryan
jeffrey.ryan_at_insightalgo.com

ia: insight algorithmics
www.insightalgo.com

______________________________________________
R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Received on Fri 27 Feb 2009 - 17:07:53 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Sat 28 Feb 2009 - 01:30:49 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive