X-Recipient: archive-cygwin AT delorie DOT com DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:date:message-id:references :mime-version:content-type:content-transfer-encoding; q=dns; s= default; b=dBSSaRclJeD/1P3i2uC8Jo6jSzM3RCFnS/7u1cSts/OiMCdS/+jjC lbm3lMqXiClRe1IYxSx2TTXG9LqNZLR67/MKqRMocjFpgYmxyvPT5joItL8u6sbq 3uPms4xEzxnu5Mo4Pne5ldwStygTKrbzTz10dFYaGATByuNFslxG/w= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:date:message-id:references :mime-version:content-type:content-transfer-encoding; s=default; bh=8fJBHkD7s7eGb5nPE8G3dV4s1WE=; b=T/nQShfRp5wEpiykWh/4PSiQyHmE a7g9Q7WrTNODQkuZstupiwnWU2Tqn/EHmuZLYQmb2DYiTnJo5giZo4EfE9eXlzJ8 av/uyvi/jItNMw6NVjvCsfnGjCbNA61oj3d736acOi3bfGJl9psnWiRZUnbEC/MP Fyt1TkKkqU+azow= Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL,BAYES_05,RCVD_IN_DNSWL_LOW,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: plane.gmane.org To: cygwin AT cygwin DOT com From: Brian Inglis Subject: Re: Bash unable to print epoch timestamp Date: Thu, 22 Oct 2015 07:03:40 +0000 (UTC) Lines: 147 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit User-Agent: Loom/3.14 (http://gmane.org/) X-IsSubscribed: yes Brian Inglis SystematicSw.ab.ca> writes: > > Don Harrop effx.us> writes: > > Bash outputs no value when using it's built in method of printing an > > "epoch" timestamp. > > BashCommandLine#: printf '%(%s)T' -1 > > bash printf depends on underlying strftime in newlib, which does not support > %s, as it is conditional on _WANT_C99_TIME_FORMATS being defined, and that > is presumably not defined in the config, as %s is not shown in man strftime. > Workaround for now is use > date +%s > for current time, and > date -d $(printf '%(%T)T' -2) +%s > for shell invocation time. > %s, as it is conditional on _WANT_C99_TIME_FORMATS being defined, and that Wrong! Misread the code, strftime %s is not supported! STC and suggested patch appended (posting from gmane), compiles, but can't build STC as ld fails with undef refs, and I don't know all the correct LD..., -L and -l incantations. Email me for original files. /* newlib/time/strftime.c %s format STC */ #include #include int main( int argc, char **argv) { char ss[BUFSIZ] = ""; time_t tt = time( NULL ); struct tm *tp = gmtime( &tt ); tt = mktime( tp ); size_t st = strftime( ss, sizeof ss, "%s", tp); int rc = puts( ss ); st = strftime( ss, sizeof ss, "%T", tp); rc = puts( ss ); return rc; } --- 8< --- 2015-10-12 Brian Inglis * newlib/time/strftime.c (__strftime): add support for %s (seconds from Unix epoch) --- a/newlib/time/strftime.c 2015-08-20 03:39:24.000000000 -0600 +++ b/newlib/time/strftime.c 2015-10-21 20:15:22.367453000 -0600 @@ -166,6 +166,10 @@ notations, the result is an empty string o %R The 24-hour time, to the minute. Equivalent to "%H:%M". [tm_min, tm_hour] +o %s +The time elapsed, in seconds, since the start of the Unix epoch at +1970-01-01 00:00:00 UTC. + o %S The second, formatted with two digits (from `<<00>>' to `<<60>>'). The value 60 accounts for the occasional leap second. [tm_sec] @@ -1109,6 +1113,74 @@ recurse: tim_p->tm_hour, tim_p->tm_min); CHECK_LENGTH (); break; + case CQ('s'): +/* + * From: + * The Open Group Base Specifications Issue 7 + * IEEE Std 1003.1, 2013 Edition + * Copyright (c) 2001-2013 The IEEE and The Open Group + * XBD Base Definitions + * 4. General Concepts + * 4.15 Seconds Since the Epoch + * A value that approximates the number of seconds that have elapsed since the + * Epoch. A Coordinated Universal Time name (specified in terms of seconds + * (tm_sec), minutes (tm_min), hours (tm_hour), days since January 1 of the year + * (tm_yday), and calendar year minus 1900 (tm_year)) is related to a time + * represented as seconds since the Epoch, according to the expression below. + * If the year is <1970 or the value is negative, the relationship is undefined. + * If the year is >=1970 and the value is non-negative, the value is related to a + * Coordinated Universal Time name according to the C-language expression, where + * tm_sec, tm_min, tm_hour, tm_yday, and tm_year are all integer types: + * tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 + + * (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 - + * ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400 + * OR + * ((((tm_year-69)/4 - (tm_year-1)/100 + (tm_year+299)/400 + + * (tm_year-70)*365 + tm_yday)*24 + tm_hour)*60 + tm_min)*60 + tm_sec + */ +/* modified from %z case by hoisting offset outside if block and initializing */ + { + long offset; /* offset < 0 => W of GMT, > 0 => E of GMT: + offset = 0; subtract to get UTC */ + + if (tim_p->tm_isdst >= 0) + { + TZ_LOCK; + if (!tzset_called) + { + _tzset_unlocked (); + tzset_called = 1; + } + +#if defined (__CYGWIN__) + /* Cygwin must check if the application has been built with or + without the extra tm members for backward compatibility, and + then use either that or the old method fetching from tzinfo. + Rather than pulling in the version check infrastructure, we + just call a Cygwin function. */ + extern long __cygwin_gettzoffset (const struct tm *tmp); + offset = __cygwin_gettzoffset (tim_p); +#elif defined (__TM_GMTOFF) + offset = tim_p->__TM_GMTOFF; +#else + __tzinfo_type *tz = __gettzinfo (); + /* The sign of this is exactly opposite the envvar TZ. We + could directly use the global _timezone for tm_isdst==0, + but have to use __tzrule for daylight savings. */ + offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset; +#endif + TZ_UNLOCK; + } + len = snprintf (&s[count], maxsize - count, CQ("%lld"), + (((((long long)tim_p->tm_year - 69)/4 + - (tim_p->tm_year - 1)/100 + + (tim_p->tm_year + 299)/400 + + (tim_p->tm_year - 70)*365 + tim_p->tm_yday)*24 + + tim_p->tm_hour)*60 + tim_p->tm_min)*60 + + tim_p->tm_sec - offset); + CHECK_LENGTH (); + } + break; case CQ('S'): #ifdef _WANT_C99_TIME_FORMATS if (alt != CQ('O') || !*alt_digits @@ -1442,6 +1514,7 @@ const struct test Vec0[] = { { CQ("%p"), 2+1, EXP(CQ("AM")) }, { CQ("%r"), 11+1, EXP(CQ("09:53:47 AM")) }, { CQ("%R"), 5+1, EXP(CQ("09:53")) }, + { CQ("%s"), 2+1, EXP(CQ("1230648827")) }, { CQ("%S"), 2+1, EXP(CQ("47")) }, { CQ("%t"), 1+1, EXP(CQ("\t")) }, { CQ("%T"), 8+1, EXP(CQ("09:53:47")) }, -- 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