Simon Urbanek
2005-Jan-19 22:54 UTC
[Rd] Re: [R-SIG-Mac] Formatting of time zone for POSIXct
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
Prof Brian Ripley
2005-Jan-19 23:39 UTC
[Rd] Re: [R-SIG-Mac] Formatting of time zone for POSIXct
Simon, There is _no_ tm_tzone component in a POSIX nor C99 tm structure (and I have just checked both), so if a system requires it to be set, the bug is not in R but in the standards-compliance of the system. So> 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 shouldis `somewhat wierd' to me. glibc2 (at least as documented in man mktime) like the standards it references has no such component, so if the header file defines one it should be private and strftime seems incorrectly implemented. What we implemented as from the POSIX standard, and at least one Solaris system complies (but it seems few others these days). I am happy to zero the structure, much less happy to reference undocumented non-POSIX/C99 components. Brian On Wed, 19 Jan 2005, Simon Urbanek wrote:> 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 > >-- Brian D. Ripley, ripley@stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Seemingly Similar Threads
- strange behaviour when converting from char to POSIX (PR#6427)
- segfault during build of 2.1.0 on RH9; print.POSIXct implicated (PR#7827)
- print.POSIXct doesn't seem to use tz argument, as per its example
- (PR#7826) segfault during build of 2.1.0 on RH9; print.POSIXct
- strftime fails on POSIXct objects (PR#10695)