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

Reply via email to