Don,
thanks for your report.
On Jan 19, 2005, at 12:41 PM, Don MacQueen wrote:
I'm encountering a problem formatting POSIXct objects in R 2.0.1 on OS X.
For reference, on a Solaris system, R 2.0.1 (2004-11-15), formatting is correct:
Sys.time()[1] "2005-01-19 09:12:33 PST"format(Sys.time(),'%H:%M %Z')[1] "09:12 PST"
On Mac OS X, however,
R 2.0.1 Patched 2005-01-19
Sys.time()[1] "2005-01-19 09:18:27 PST"format(Sys.time(),'%H:%M %Z')[1] "09:18 P"
The man pages says: usetz: logical. Should the timezone be appended to the output? This is used in printing time, and as a workaround for problems with using '"%Z"' on most Linux systems.
so after reading that, you get the correct result:
> format(Sys.time(),'%H:%M',usetz=TRUE) [1] "15:57 EST"
Now, the reason why I'm CCing this to R-devel is that in fact the datetime.c is somewhat weird for non-GlibC2 systems as tm.tm_zone is not initialized at all, which I suspect is a bug. Either the docs should state that %Z should not be used at all or I'd propose the following patch to make it work (warning, it's a patch against R-devel):
Index: src/main/datetime.c =================================================================== --- src/main/datetime.c (revision 32715) +++ src/main/datetime.c (working copy) @@ -581,15 +581,8 @@ error("invalid `usetz' argument"); tz = getAttrib(x, install("tzone"));
- /* workaround for glibc bug in strftime */ -#if defined HAVE_GLIBC2 -#ifdef __USE_BSD - tm.tm_zone = NULL; -#else - tm.__tm_zone = NULL; -#endif -#endif - + memset(&tm, 0, sizeof(tm)); + /* coerce fields to integer, find length of longest one */ for(i = 0; i < 9; i++) { nlen[i] = LENGTH(VECTOR_ELT(x, i));
This just zeroes out tm before use - it should also fix the problems on Linux. Just in case I overlooked something and it's not feasible to zero out the struct tm (e.g. if the size may be unknown), then the following, more paranoid patch could be used:
Index: src/main/datetime.c =================================================================== --- src/main/datetime.c (revision 32715) +++ src/main/datetime.c (working copy) @@ -588,7 +588,11 @@ #else tm.__tm_zone = NULL; #endif +#else +#ifdef HAVE_STRUCT_TM_TM_ZONE + tm.tm_zone = NULL; #endif +#endif
/* coerce fields to integer, find length of longest one */ for(i = 0; i < 9; i++) { Index: configure.ac =================================================================== --- configure.ac (revision 32715) +++ configure.ac (working copy) @@ -551,7 +551,7 @@ fpu_control.h grp.h ieee754.h ieeefp.h limits.h locale.h \ netdb.h netinet/in.h pwd.h strings.h \ sys/param.h sys/select.h sys/socket.h sys/stat.h sys/time.h \ - sys/times.h sys/utsname.h unistd.h) + sys/times.h sys/utsname.h time.h unistd.h) ## </NOTE> ## <NOTE> ## These are ANSI C headers but some C code (written to work also @@ -1333,6 +1333,13 @@ ## POSIX times. R_SYS_POSIX_LEAPSECONDS
+dnl some Solaris systems don't have a tm_zone member in struct tm. +AC_CHECK_MEMBERS([struct tm.tm_zone],,,[ +#if defined(HAVE_TIME_H) +#include <time.h> +#endif +]) + ## R profiling. if test "${want_R_profiling}" = yes; then AC_CHECK_FUNCS(setitimer,
The configure patch makes sure we know that struct tm.tm_zone exists and the other patch makes sure it's reset before calling strftime. Any variation hereof would help, too ;)
Changing the TZ environment variable, from the default of "" to "US/Pacific" does not help.
Doing so has no effect for you, because the time zone is correct as you demonstrated yourself in the above output.
Cheers, Simon
______________________________________________ R-devel@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-devel