Jeff Ryan
2009-Feb-27 18:06 UTC
[Rd] POSIXlt, POSIXct, strptime, GMT and 1969-12-31 23:59:59
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 - attr(*, "tzone")= chr "GMT" # 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 - attr(*, "tzone")= chr "GMT">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 - attr(*, "tzone")= chr "GMT" 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
Seemingly Similar Threads
- Correction to vec-subset speed patch
- The presence/absence of `zone` in POSIXlt depending on time zone as a cause of possible inconsistences?
- Re: write.table() fails for POSIXlt class and NAs in another variable (PR#3242)
- Re: (PR#3241) write.table() fails for POSIXlt class and NAs in
- The presence/absence of `zone` in POSIXlt depending on time zone as a cause of possible inconsistences?