On 2017-05-01 09:25, cyg Simple wrote: > On 4/30/2017 7:19 PM, Steven Penny wrote: >> On Sun, 30 Apr 2017 17:37:00, Ken Brown wrote: >>> As a result of a failing emacs test, I came across the following: >>> >>> $ TZ='NZST-12NZDT,M9.5.0,M4.1.0/3' date -d@0 +'%Y-%m-%d %H:%M:%S %z (%Z)' >>> 1970-01-01 12:00:00 +1200 (NZST) >>> >>> The same command on Linux yields "1970-01-01 13:00:00 +1300 (NZDT)", >>> which is >>> correct according to Paul Eggert >>> (https://lists.gnu.org/archive/html/emacs-devel/2017-04/msg00881.html).
This may be a problem in: winsup/cygwin/localtime.cc not properly handling POSIX time zone specs in the S hemisphere, with DST which starts in autumn/fall and ends in spring, at the start of the time_t epoch, where the first DST transition happens with negative time_t. Neither localtime nor mktime on Cygwin properly handle these rules where both localtime and mktime on Linux do - STC and sdiff attached. On Linux, even if you comment out the localtime call, mktime sets the offset correctly; on Cygwin even using localtime and mktime fails to set the offset at 1970-01-01 correctly. Cygwin awk strftime also shows the same issue where Linux is also correct. >> I concur, here is non-esoteric example Linux: >> $ TZ=Pacific/Auckland date +%Z >> NZST >> $ TZ=NZST date +%Z >> NZST >> $ TZ=NZDT date +%Z >> NZDT >> Cygwin: >> $ TZ=Pacific/Auckland date +%Z >> NZST >> $ TZ=NZST date +%Z >> GMT >> $ TZ=NZDT date +%Z >> GMT This is just a slight difference in handling POSIX time zone specs with no explicit offset specified - the basic format is std offset. If you provide only a std abbr with no offset, Cygwin defaults to GMT, where Linux uses the abbr and sets the offset to zero. Both behave identically if you specify a +-offset: $ TZ=XXX date +"%F %a %R%z(%Z)"; TZ=XXX0 date +"%F %a %R%z(%Z)" 2017-05-01 Mon 17:13+0000(GMT) 2017-05-01 Mon 17:13+0000(XXX) $ ssh ... 'TZ=XXX date +"%F %a %R%z(%Z)"; TZ=XXX0 date +"%F %a %R%z(%Z)"' 2017-05-01 Mon 17:13+0000(XXX) 2017-05-01 Mon 17:13+0000(XXX) depends whether you prefer to see the same answer or the smart answer ;^> -- Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
NZST-12NZDT,M9.5.0,M4.1.0/3 NZST-12NZDT,M9.5.0,M4.1.0/3 1970-01-01 001 4 00:00+0000s(GMT) gm 1970-01-01 001 4 00:00+0000s(GMT) gm 1970-01-01 001 4 13:00+1300d(NZDT) local | 1970-01-01 001 4 12:00+1200s(NZST) local 1970-01-01 001 4 13:00+1300d(NZDT) mk | 1970-01-01 001 4 12:00+1200s(NZST) mk 1970-01-01 001 Thu 13:00+1300 (NZDT) | 1970-01-01 001 Thu 12:00+1200 (NZST) 1970-04-04 094 6 13:00+0000s(GMT) gm 1970-04-04 094 6 13:00+0000s(GMT) gm 1970-04-05 095 0 02:00+1300d(NZDT) local | 1970-04-05 095 0 01:00+1200s(NZST) local 1970-04-05 095 0 02:00+1300d(NZDT) mk | 1970-04-05 095 0 01:00+1200s(NZST) mk 1970-04-05 095 Sun 02:00+1300 (NZDT) | 1970-04-05 095 Sun 01:00+1200 (NZST) 1970-04-04 094 6 14:00+0000s(GMT) gm 1970-04-04 094 6 14:00+0000s(GMT) gm 1970-04-05 095 0 02:00+1200s(NZST) local 1970-04-05 095 0 02:00+1200s(NZST) local 1970-04-05 095 0 02:00+1200s(NZST) mk 1970-04-05 095 0 02:00+1200s(NZST) mk 1970-04-05 095 Sun 02:00+1200 (NZST) 1970-04-05 095 Sun 02:00+1200 (NZST) 1970-09-26 269 6 13:00+0000s(GMT) gm 1970-09-26 269 6 13:00+0000s(GMT) gm 1970-09-27 270 0 01:00+1200s(NZST) local 1970-09-27 270 0 01:00+1200s(NZST) local 1970-09-27 270 0 01:00+1200s(NZST) mk 1970-09-27 270 0 01:00+1200s(NZST) mk 1970-09-27 270 Sun 01:00+1200 (NZST) 1970-09-27 270 Sun 01:00+1200 (NZST) 1970-09-26 269 6 14:00+0000s(GMT) gm 1970-09-26 269 6 14:00+0000s(GMT) gm 1970-09-27 270 0 03:00+1300d(NZDT) local 1970-09-27 270 0 03:00+1300d(NZDT) local 1970-09-27 270 0 03:00+1300d(NZDT) mk 1970-09-27 270 0 03:00+1300d(NZDT) mk 1970-09-27 270 Sun 03:00+1300 (NZDT) 1970-09-27 270 Sun 03:00+1300 (NZDT) 1971-01-01 001 5 00:00+0000s(GMT) gm 1971-01-01 001 5 00:00+0000s(GMT) gm 1971-01-01 001 5 13:00+1300d(NZDT) local 1971-01-01 001 5 13:00+1300d(NZDT) local 1971-01-01 001 5 13:00+1300d(NZDT) mk 1971-01-01 001 5 13:00+1300d(NZDT) mk 1971-01-01 001 Fri 13:00+1300 (NZDT) 1971-01-01 001 Fri 13:00+1300 (NZDT) 1971-04-03 093 6 13:00+0000s(GMT) gm 1971-04-03 093 6 13:00+0000s(GMT) gm 1971-04-04 094 0 02:00+1300d(NZDT) local 1971-04-04 094 0 02:00+1300d(NZDT) local 1971-04-04 094 0 02:00+1300d(NZDT) mk 1971-04-04 094 0 02:00+1300d(NZDT) mk 1971-04-04 094 Sun 02:00+1300 (NZDT) 1971-04-04 094 Sun 02:00+1300 (NZDT) 1971-04-03 093 6 14:00+0000s(GMT) gm 1971-04-03 093 6 14:00+0000s(GMT) gm 1971-04-04 094 0 02:00+1200s(NZST) local 1971-04-04 094 0 02:00+1200s(NZST) local 1971-04-04 094 0 02:00+1200s(NZST) mk 1971-04-04 094 0 02:00+1200s(NZST) mk 1971-04-04 094 Sun 02:00+1200 (NZST) 1971-04-04 094 Sun 02:00+1200 (NZST) 0 0
/* newlib/libc/time/strftime.c %z format STC */ #include <stdio.h> #include <stdlib.h> #include <time.h> #define TZ "TZ=NZST-12NZDT,M9.5.0,M4.1.0/3" #define DFMT "%04d-%02d-%02d %03d %-3d %02d:%02d%+03ld00%s(%s)\t%s\n" //:%02d #define TFMT "%F %j %a %R%z (%Z)" #define EPOCH 1970 #define YADD 1900 #define MADD 1 #define DADD 1 #define YR_MTH 12 #define MTH_DAY 30 #define DAY_HR 24 #define HR_MIN 60 #define MIN_S 60 #define HR_S (HR_MIN*MIN_S) /* extra is total days over 30 in preceding months - net total 5/year */ #define S(extra,yr,mth,day,hr) \ ((((((yr) - EPOCH)*YR_MTH + ((mth) - 1))*MTH_DAY + (extra) + (day) - 1)\ *DAY_HR + (hr))*HR_S) int dump( struct tm* tp, char *label) { return printf( DFMT, tp->tm_year + YADD, tp->tm_mon + MADD, tp->tm_mday, tp->tm_yday + DADD, tp->tm_wday, tp->tm_hour, tp->tm_min, // tp->tm_sec, # ifdef __TM_GMTOFF tp->__TM_GMTOFF/HR_S, # elif __USE_BSD tp->tm_gmtoff/HR_S, # else tp->__tm_gmtoff/HR_S, # endif tp->tm_isdst < 0 ? "?" : tp->tm_isdst ? "d" : "s", # ifdef __TM_ZONE tp->__TM_ZONE, # elif __USE_BSD tp->tm_zone, # else tp->__tm_zone, # endif label ); } int test( time_t tt ) { char ss[BUFSIZ] = ""; struct tm * tp; size_t st; int rc; if (EOF == (rc = puts( "" ))) return 5; if (!(tp = gmtime( &tt ))) return 1; if ((rc = dump( tp, "gm" )) <= 0) return -rc; if (!(tp = localtime( &tt ))) return 2; if ((rc = dump( tp, "local" )) <= 0) return -rc; if (-1 == (tt = mktime( tp ))) return 3; if ((rc = dump( tp, "mk" )) <= 0) return -rc; if ((st = strftime( ss, sizeof ss, TFMT, tp)) <= 0) return 4; if (EOF == (rc = puts( ss ))) return 5; return 0; } int main( void ) { int rc; if ((rc = putenv( TZ ))) return rc; if (EOF == (rc = puts( getenv( "TZ" )))) return 6; /* extra year m day hour */ if ((rc = test( S( 0, 1970, 1, 1, 0)))) return rc; if ((rc = test( S( 0, 1970, 4, 4, 13)))) return rc; if ((rc = test( S( 0, 1970, 4, 4, 14)))) return rc; if ((rc = test( S( 3, 1970, 9, 26, 13)))) return rc; if ((rc = test( S( 3, 1970, 9, 26, 14)))) return rc; if ((rc = test( S( 5, 1971, 1, 1, 0)))) return rc; if ((rc = test( S( 5, 1971, 4, 3, 13)))) return rc; if ((rc = test( S( 5, 1971, 4, 3, 14)))) return rc; return rc; }
-- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple