{"thread":{"id":"406","subject":"RE: Trying to use AUTHOR_DATE","startedAt":"2005-04-30T03:44:04Z","lastAt":"2005-05-03T00:38:47Z","messageCount":31,"participants":["Luck, Tony","H. Peter Anvin","Linus Torvalds","Russ Allbery","Edgar Toernig","Junio C Hamano","David Woodhouse","Kay Sievers","Juliusz Chroboczek","Randy.Dunlap","Krzysztof Halasa"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"2233","messageId":"B8E391BBE9FE384DAA4C5C003888BE6F035EDE2C@scsmsx401.amr.corp.intel.com","threadId":"406","inReplyTo":null,"subject":"RE: Trying to use AUTHOR_DATE","fromName":"Luck, Tony","fromEmail":"tony.luck@intel.com","sentAt":"2005-04-30T03:44:04Z","receivedAt":"2005-04-30T03:44:04Z","isPatch":false,"sender":{"key":"tony.luck@intel.com","avatar":"https://avatars.githubusercontent.com/u/5446021?v=4"},"body":">Another dependency :-(   I can live without http-pull but not\n>without commit-tree.\n\nYes, the extra dependency sucks ... libcurl is missing from one of\nthe systems that I'd like to use GIT on ... so I'd prefer a solution\nthat doesn't involve libcurl.\n\n>What's wrong with the patch I sent to fix this:\n>\n>\thttp://marc.theaimsgroup.com/?m=111446501003389\n>\n\nI missed it ... there is a problem that you drop the timezone.  When I\nused this patch, I ended up with a commit that said:\n\nauthor Keith Owens <kaos@sgi.com> 1114239900\ncommitter Tony Luck <tony.luck@intel.com> 1114832076 -0700\n\nSee the missing timezone on the author line :-)  This is most upsetting\nto cg-log.  It prints \"expr: syntax error\" and then\n\nauthor Keith Owens <kaos@sgi.com> Thu, 01 Jan 1970 00:00:01\n\n>> +\t/* find the timezone at the end */\n>> +\tp = date + strlen(date);\n>> +\twhile (p > date && isdigit(*--p))\n>> +\t\t;\n>> +\tif ((*p == '+' || *p == '-') && strlen(p) == 5)\n>> +\t\tsnprintf(result, maxlen, \"%lu %5.5s\", then, p);\n>\n>This will choke on dates from Linus which have a trailing comment:\n>\n>\tDate: Fri, 29 Apr 2005 15:26:14 -0700 (PDT)\n\nYou are right ... that's what comes from only looking at one e-mail\nmessage to determine that pattern to match :-)\n\nI'd much rather see your version fixed up to preserve the timezone\nthan have the libcurl dependency.\n\n-Tony\n"},{"id":"2235","messageId":"42730061.5010106@zytor.com","threadId":"406","inReplyTo":"B8E391BBE9FE384DAA4C5C003888BE6F035EDE2C@scsmsx401.amr.corp.intel.com","subject":"Re: Trying to use AUTHOR_DATE","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-04-30T03:49:53Z","receivedAt":"2005-04-30T03:49:53Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Luck, Tony wrote:\n>>Another dependency :-(   I can live without http-pull but not\n>>without commit-tree.\n> \n> Yes, the extra dependency sucks ... libcurl is missing from one of\n> the systems that I'd like to use GIT on ... so I'd prefer a solution\n> that doesn't involve libcurl.\n\n...\n\n> I'd much rather see your version fixed up to preserve the timezone\n> than have the libcurl dependency.\n\nFor gawd's sake people, just grab a copy of the working code in libcurl, \nand turn it into a standalone .c file.  It'll even let you merge in \nfuture fixes, and you could even use autoconf to use libcurl or the \nstandalone code depending on what's available.\n\n\t-hpa\n"},{"id":"2236","messageId":"Pine.LNX.4.58.0504292101230.2296@ppc970.osdl.org","threadId":"406","inReplyTo":"42730061.5010106@zytor.com","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-30T04:02:45Z","receivedAt":"2005-04-30T04:02:45Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 29 Apr 2005, H. Peter Anvin wrote:\n> \n> For gawd's sake people, just grab a copy of the working code in libcurl, \n> and turn it into a standalone .c file.  It'll even let you merge in \n> future fixes, and you could even use autoconf to use libcurl or the \n> standalone code depending on what's available.\n\nI'll happily depend on libcurl, but I put my foot down on that tool of the \ndevil called \"autoconf\".\n\nAny package that starts using autoconf eventually becomes a total mess. \nDon't do it. \n\n\t\tLinus\n"},{"id":"2237","messageId":"Pine.LNX.4.58.0504292114580.2296@ppc970.osdl.org","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504292101230.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-30T04:22:27Z","receivedAt":"2005-04-30T04:22:27Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 29 Apr 2005, Linus Torvalds wrote:\n> \n> I'll happily depend on libcurl, but I put my foot down on that tool of the \n> devil called \"autoconf\".\n\nBtw, looking at curl's \"getdate.c\", it doesn't seem to be _that_ much more \ndifferent from the date parsing we used to have. In particular, it \nactually uses \"mktime()\" twice and subtracts out the difference.\n\nIt also seems to do so in a particularly stupid way, and David Woodhouses \nsuggestion of just using mktime() on Jan 1st, 1970, seems to be much \nsimpler than what curl does.\n\n(Actually, it might make sense to modify David's version to use \"Jan 2nd,\n1970\" and subtract 24 hours, in case some mktime() implementation decides\nthat underflow is a problem...)\n\nOf course, I think we might as well go with Edgars version after all. \n\nEdgar, willing to create a separate \"parse-date.c\" with your \"my_mktime()\" \nthing and move the old date parsing there? That way we'll just use that \ninstead of libcurl..\n\n\t\tLinus\n"},{"id":"2238","messageId":"87zmvganq9.fsf@windlord.stanford.edu","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504292114580.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Russ Allbery","fromEmail":"rra@stanford.edu","sentAt":"2005-04-30T04:32:30Z","receivedAt":"2005-04-30T04:32:30Z","isPatch":false,"sender":{"key":"rra@stanford.edu","avatar":null},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> It also seems to do so in a particularly stupid way, and David\n> Woodhouses suggestion of just using mktime() on Jan 1st, 1970, seems to\n> be much simpler than what curl does.\n\nBecause of daylight savings time, this doesn't actually work.  I know from\npersonal experience; this is the tactic that I took at first when writing\nINN's date parser and was educated by test failures.\n\n-- \nRuss Allbery (rra@stanford.edu)             <http://www.eyrie.org/~eagle/>\n"},{"id":"2239","messageId":"20050430065039.21ac9a4e.froese@gmx.de","threadId":"406","inReplyTo":"B8E391BBE9FE384DAA4C5C003888BE6F035EDE2C@scsmsx401.amr.corp.intel.com","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T04:50:39Z","receivedAt":"2005-04-30T04:50:39Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"Luck, Tony wrote:\n>\n> >What's wrong with the patch I sent to fix this:\n>\n> I missed it ... there is a problem that you drop the timezone.\n\nUpps, sorry.\n\n> I'd much rather see your version fixed up to preserve the timezone\n> than have the libcurl dependency.\n\nFixed version below.\n\n--- x/commit-tree.c\tThu Apr 21 19:58:47 2005\n+++ y/commit-tree.c\tSat Apr 30 06:24:19 2005\n@@ -113,6 +113,25 @@\n \t}\n }\n \n+static time_t my_mktime(struct tm *tm)\n+{\n+\tstatic const int mdays[] = {\n+\t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n+\t};\n+\tint year = tm->tm_year - 70;\n+\tint month = tm->tm_mon;\n+\tint day = tm->tm_mday;\n+\n+\tif (year < 0 || year > 129) /* algo only works for 1970-2099 */\n+\t\treturn -1;\n+\tif (month < 0 || month > 11) /* array bounds */\n+\t\treturn -1;\n+\tif (month < 2 || (year + 2) % 4)\n+\t\tday--;\n+\treturn (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +\n+\t\ttm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;\n+}\n+\n static const char *month_names[] = {\n         \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n         \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"\n@@ -136,7 +155,7 @@\n static void parse_rfc2822_date(char *date, char *result, int maxlen)\n {\n \tstruct tm tm;\n-\tchar *p;\n+\tchar *p, *tz;\n \tint i, offset;\n \ttime_t then;\n \n@@ -194,7 +213,7 @@\n \t\treturn;\n \ttm.tm_hour = strtoul(p, &p, 10);\n \t\n-\tif (!tm.tm_hour > 23)\n+\tif (tm.tm_hour > 23)\n \t\treturn;\n \n \tif (*p != ':')\n@@ -206,14 +225,11 @@\n \t\treturn;\n \ttm.tm_min = strtoul(p, &p, 10);\n \t\n-\tif (!tm.tm_min > 59)\n+\tif (tm.tm_min > 59)\n \t\treturn;\n \n-\tif (isspace(*p))\n-\t\tgoto zone;\n-\n \tif (*p != ':')\n-\t\treturn; /* Error -- bad time */\n+\t\tgoto zone;\n \tp++;\n \n \t/* second */\n@@ -221,13 +237,13 @@\n \t\treturn;\n \ttm.tm_sec = strtoul(p, &p, 10);\n \t\n-\tif (!tm.tm_sec > 59)\n+\tif (tm.tm_sec > 59)\n \t\treturn;\n \n+ zone:\n \tif (!isspace(*p))\n \t\treturn;\n \n- zone:\n \tp = skipfws(p);\n \n \tif (*p == '-')\n@@ -240,19 +256,21 @@\n \tif (!isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3]) || !isdigit(p[4]))\n \t\treturn;\n \n+\ttz = p;\n \ti = strtoul(p+1, NULL, 10);\n \toffset *= ((i % 100) + ((i / 100) * 60));\n \n-\tif (*(skipfws(p + 5)))\n+\tp = skipfws(p + 5);\n+\tif (*p && *p != '(') /* trailing comment like (EDT) is ok */\n \t\treturn;\n \n-\tthen = mktime(&tm); /* mktime appears to ignore the GMT offset, stupidly */\n+\tthen = my_mktime(&tm); /* mktime uses local timezone */\n \tif (then == -1)\n \t\treturn;\n \n \tthen -= offset;\n \n-\tsnprintf(result, maxlen, \"%lu %5.5s\", then, p);\n+\tsnprintf(result, maxlen, \"%lu %5.5s\", then, tz);\n }\n \n static void check_valid(unsigned char *sha1, const char *expect)\n\n\nCiao, ET.\n"},{"id":"2242","messageId":"7vacng3jln.fsf@assigned-by-dhcp.cox.net","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504292114580.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-04-30T05:43:32Z","receivedAt":"2005-04-30T05:43:32Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> On Fri, 29 Apr 2005, Linus Torvalds wrote:\n>> \n>> I'll happily depend on libcurl, but I put my foot down on that tool of the \n>> devil called \"autoconf\".\n\nLT> Btw, looking at curl's \"getdate.c\", it doesn't seem to be _that_ much more \nLT> different from the date parsing we used to have. In particular, it \nLT> actually uses \"mktime()\" twice and subtracts out the difference.\n\nIf we are going to lift code from somewhere, why don't we steal\nfrom a pro who knows what he is doing?  \n\nOne careful implementation of my-mktime() I know of is the one\nby Paul Eggert, found in patch (maketime.c::tm2time).\n\n"},{"id":"2244","messageId":"1114848175.24014.35.camel@localhost.localdomain","threadId":"406","inReplyTo":"87zmvganq9.fsf@windlord.stanford.edu","subject":"Re: Trying to use AUTHOR_DATE","fromName":"David Woodhouse","fromEmail":"dwmw2@infradead.org","sentAt":"2005-04-30T08:02:54Z","receivedAt":"2005-04-30T08:02:54Z","isPatch":false,"sender":{"key":"dwmw2@infradead.org","avatar":"https://gravatar.com/avatar/7afd4f07e0cf7d7e046ae2d23678296b37777c96488e6f3451e78a5514154ebd?d=mp&s=160"},"body":"On Fri, 2005-04-29 at 21:32 -0700, Russ Allbery wrote:\n> Linus Torvalds <torvalds@osdl.org> writes:\n> > It also seems to do so in a particularly stupid way, and David\n> > Woodhouses suggestion of just using mktime() on Jan 1st, 1970, seems to\n> > be much simpler than what curl does.\n> \n> Because of daylight savings time, this doesn't actually work.  I know from\n> personal experience; this is the tactic that I took at first when writing\n> INN's date parser and was educated by test failures.\n\nEww. The time functions we have to play with _really_ suck, don't they?\nHow about this...\n\nSigned-off-by: David Woodhouse <dwmw2@infradead.org>\n\ncommit-tree.c: needs update\nIndex: commit-tree.c\n===================================================================\n--- c3aa1e6b53cc59d5fbe261f3f859584904ae3a63/commit-tree.c  (mode:100644 sha1:23de13361944ad7ba7c5320cf7cdd04e81842c60)\n+++ uncommitted/commit-tree.c  (mode:100644)\n@@ -213,10 +213,18 @@\n \tif (*(skipfws(p + 5)))\n \t\treturn;\n \n-\tthen = mktime(&tm); /* mktime appears to ignore the GMT offset, stupidly */\n+\ttm.tm_gmtoff = 0;\n+\ttm.tm_isdst = -1;\n+\n+\tthen = mktime(&tm);\n \tif (then == -1)\n \t\treturn;\n \n+\t/* mktime always uses localtime, regardless of the tm_gmtoff field.\n+\t   It does, however, honour 'tm_isdst'; stupidly. Thankfully, it does\n+\t   at least tell us the offset it decided to use, so we can compensate\n+\t   for it */\n+\tthen += tm.tm_gmtoff;\n \tthen -= offset;\n \n \tsnprintf(result, maxlen, \"%lu %5.5s\", then, p);\n\n-- \ndwmw2\n\n"},{"id":"2245","messageId":"20050430124048.79119cac.froese@gmx.de","threadId":"406","inReplyTo":"1114848175.24014.35.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T10:40:48Z","receivedAt":"2005-04-30T10:40:48Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"David Woodhouse wrote:\n>\n> Eww. The time functions we have to play with _really_ suck, don't they?\n> How about this...\n> \n> +\tthen += tm.tm_gmtoff;\n\ntm_gmtoff is not available everywhere - POSIX doesn't even mention it (BSD?).\n\nOh btw, when we are about sucking time functions: the %s and %z strftime-\nsequences used further down are also non-standard (POSIX has no %s, old\nlibc has neither %s nor %z).\n\nA possible workaround:\n\nvoid make_datestamp(char *buf)\n{\n\ttime_t now;\n\tstruct tm *tm;\n\tint tz;\n\n\ttime(&now);\n\n\ttm = localtime(&now); /* get timezone and tm_isdst */\n\ttz = -timezone / 60;\n\tif (tm->tm_isdst > 0)\n\t\ttz += 60;\n\n\tsprintf(buf, \"%lu %+05d\", now, tz/60*100+tz%60);\n}\n\nThat *should* work on any POSIX system but who knows ...\n\nCiao, ET.\n"},{"id":"2246","messageId":"20050430125333.2bd81b18.froese@gmx.de","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504292114580.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T10:53:33Z","receivedAt":"2005-04-30T10:53:33Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"Linus Torvalds wrote:\n>\n> Edgar, willing to create a separate \"parse-date.c\" with your \"my_mktime()\" \n> thing and move the old date parsing there? That way we'll just use that \n> instead of libcurl..\n\nHere it is.  I moved the strftime stuff too (workaround for non-standard\n%s %z sequence).\n\n--- k/Makefile  (mode:100644)\n+++ l/Makefile  (mode:100644)\n@@ -28,7 +28,8 @@ all: $(PROG)\n install: $(PROG) $(SCRIPTS)\n \tinstall $(PROG) $(SCRIPTS) $(HOME)/bin/\n \n-LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o tag.o\n+LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n+\t tag.o date.o\n LIB_FILE=libgit.a\n LIB_H=cache.h object.h blob.h tree.h commit.h tag.h\n \n--- k/cache.h  (mode:100644)\n+++ l/cache.h  (mode:100644)\n@@ -147,6 +160,9 @@ extern void *read_object_with_reference(\n \t\t\t\t\tconst unsigned char *required_type,\n \t\t\t\t\tunsigned long *size,\n \t\t\t\t\tunsigned char *sha1_ret);\n+\n+void parse_date(char *date, char *buf, int bufsize);\n+void datestamp(char *buf, int bufsize);\n \n static inline void *xmalloc(int size)\n {\n--- k/commit-tree.c  (mode:100644)\n+++ l/commit-tree.c  (mode:100644)\n@@ -10,7 +10,6 @@\n #include <string.h>\n #include <ctype.h>\n #include <time.h>\n-#include <curl/curl.h>\n \n #define BLOCKING (1ul << 14)\n \n@@ -81,24 +80,6 @@ static void remove_special(char *p)\n \t}\n }\n \n-/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822\n-   (i.e. English) day/month names, and it doesn't work correctly with %z. */\n-static void parse_date(char *date, time_t *now, char *result, int maxlen)\n-{\n-\tchar *p;\n-\ttime_t then;\n-\n-\tif ((then = curl_getdate(date, now)) == 0)\n-\t\treturn;\n-\n-\t/* find the timezone at the end */\n-\tp = date + strlen(date);\n-\twhile (p > date && isdigit(*--p))\n-\t\t;\n-\tif ((*p == '+' || *p == '-') && strlen(p) == 5)\n-\t\tsnprintf(result, maxlen, \"%lu %5.5s\", then, p);\n-}\n-\n static void check_valid(unsigned char *sha1, const char *expect)\n {\n \tvoid *buf;\n@@ -132,8 +113,6 @@ int main(int argc, char **argv)\n \tchar *audate;\n \tchar comment[1000];\n \tstruct passwd *pw;\n-\ttime_t now;\n-\tstruct tm *tm;\n \tchar *buffer;\n \tunsigned int size;\n \n@@ -163,10 +142,8 @@ int main(int argc, char **argv)\n \t\tstrcat(realemail, \".\");\n \t\tgetdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);\n \t}\n-\ttime(&now);\n-\ttm = localtime(&now);\n \n-\tstrftime(realdate, sizeof(realdate), \"%s %z\", tm);\n+\tdatestamp(realdate, sizeof(realdate));\n \tstrcpy(date, realdate);\n \n \tcommitgecos = getenv(\"COMMIT_AUTHOR_NAME\") ? : realgecos;\n@@ -175,7 +152,7 @@ int main(int argc, char **argv)\n \temail = getenv(\"AUTHOR_EMAIL\") ? : realemail;\n \taudate = getenv(\"AUTHOR_DATE\");\n \tif (audate)\n-\t\tparse_date(audate, &now, date, sizeof(date));\n+\t\tparse_date(audate, date, sizeof(date));\n \n \tremove_special(gecos); remove_special(realgecos); remove_special(commitgecos);\n \tremove_special(email); remove_special(realemail); remove_special(commitemail);\n--- /dev/null\n+++ l/date.c  (mode:100644)\n@@ -0,0 +1,187 @@\n+/*\n+ * GIT - The information manager from hell\n+ *\n+ * Copyright (C) Linus Torvalds, 2005\n+ */\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <time.h>\n+\n+static time_t my_mktime(struct tm *tm)\n+{\n+\tstatic const int mdays[] = {\n+\t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n+\t};\n+\tint year = tm->tm_year - 70;\n+\tint month = tm->tm_mon;\n+\tint day = tm->tm_mday;\n+\n+\tif (year < 0 || year > 129) /* algo only works for 1970-2099 */\n+\t\treturn -1;\n+\tif (month < 0 || month > 11) /* array bounds */\n+\t\treturn -1;\n+\tif (month < 2 || (year + 2) % 4)\n+\t\tday--;\n+\treturn (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +\n+\t\ttm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;\n+}\n+\n+static const char *month_names[] = {\n+        \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n+        \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"\n+};\n+\n+static const char *weekday_names[] = {\n+        \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"\n+};\n+\n+\n+static char *skipfws(char *str)\n+{\n+\twhile (isspace(*str))\n+\t\tstr++;\n+\treturn str;\n+}\n+\n+\t\n+/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822\n+   (i.e. English) day/month names, and it doesn't work correctly with %z. */\n+void parse_date(char *date, char *result, int maxlen)\n+{\n+\tstruct tm tm;\n+\tchar *p, *tz;\n+\tint i, offset;\n+\ttime_t then;\n+\n+\tmemset(&tm, 0, sizeof(tm));\n+\n+\t/* Skip day-name */\n+\tp = skipfws(date);\n+\tif (!isdigit(*p)) {\n+\t\tfor (i=0; i<7; i++) {\n+\t\t\tif (!strncmp(p,weekday_names[i],3) && p[3] == ',') {\n+\t\t\t\tp = skipfws(p+4);\n+\t\t\t\tgoto day;\n+\t\t\t}\n+\t\t}\n+\t\treturn;\n+\t}\t\t\t\t\t\n+\n+\t/* day */\n+ day:\n+\ttm.tm_mday = strtoul(p, &p, 10);\n+\n+\tif (tm.tm_mday < 1 || tm.tm_mday > 31)\n+\t\treturn;\n+\n+\tif (!isspace(*p))\n+\t\treturn;\n+\n+\tp = skipfws(p);\n+\n+\t/* month */\n+\n+\tfor (i=0; i<12; i++) {\n+\t\tif (!strncmp(p, month_names[i], 3) && isspace(p[3])) {\n+\t\t\ttm.tm_mon = i;\n+\t\t\tp = skipfws(p+strlen(month_names[i]));\n+\t\t\tgoto year;\n+\t\t}\n+\t}\n+\treturn; /* Error -- bad month */\n+\n+\t/* year */\n+ year:\t\n+\ttm.tm_year = strtoul(p, &p, 10);\n+\n+\tif (!tm.tm_year && !isspace(*p))\n+\t\treturn;\n+\n+\tif (tm.tm_year > 1900)\n+\t\ttm.tm_year -= 1900;\n+\t\t\n+\tp=skipfws(p);\n+\n+\t/* hour */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_hour = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_hour > 23)\n+\t\treturn;\n+\n+\tif (*p != ':')\n+\t\treturn; /* Error -- bad time */\n+\tp++;\n+\n+\t/* minute */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_min = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_min > 59)\n+\t\treturn;\n+\n+\tif (*p != ':')\n+\t\tgoto zone;\n+\tp++;\n+\n+\t/* second */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_sec = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_sec > 59)\n+\t\treturn;\n+\n+ zone:\n+\tif (!isspace(*p))\n+\t\treturn;\n+\n+\tp = skipfws(p);\n+\n+\tif (*p == '-')\n+\t\toffset = -60;\n+\telse if (*p == '+')\n+\t\toffset = 60;\n+\telse\n+\t       return;\n+\n+\tif (!isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3]) || !isdigit(p[4]))\n+\t\treturn;\n+\n+\ttz = p;\n+\ti = strtoul(p+1, NULL, 10);\n+\toffset *= ((i % 100) + ((i / 100) * 60));\n+\n+\tp = skipfws(p + 5);\n+\tif (*p && *p != '(') /* trailing comment like (EDT) is ok */\n+\t\treturn;\n+\n+\tthen = my_mktime(&tm); /* mktime uses local timezone */\n+\tif (then == -1)\n+\t\treturn;\n+\n+\tthen -= offset;\n+\n+\tsnprintf(result, maxlen, \"%lu %5.5s\", then, tz);\n+}\n+\n+void datestamp(char *buf, int bufsize)\n+{\n+\ttime_t now;\n+\tstruct tm *tm;\n+\tint offset;\n+\n+\ttime(&now);\n+\n+\ttm = localtime(&now); /* get timezone and tm_isdst */\n+\toffset = -timezone / 60;\n+\tif (tm->tm_isdst > 0)\n+\t\toffset += 60;\n+\n+\tsnprintf(buf, bufsize, \"%lu %+05d\", now, offset/60*100 + offset%60);\n+}\n\nCiao, ET.\n"},{"id":"2248","messageId":"1114859594.24014.60.camel@localhost.localdomain","threadId":"406","inReplyTo":"20050430125333.2bd81b18.froese@gmx.de","subject":"Re: Trying to use AUTHOR_DATE","fromName":"David Woodhouse","fromEmail":"dwmw2@infradead.org","sentAt":"2005-04-30T11:13:13Z","receivedAt":"2005-04-30T11:13:13Z","isPatch":false,"sender":{"key":"dwmw2@infradead.org","avatar":"https://gravatar.com/avatar/7afd4f07e0cf7d7e046ae2d23678296b37777c96488e6f3451e78a5514154ebd?d=mp&s=160"},"body":"On Sat, 2005-04-30 at 12:53 +0200, Edgar Toernig wrote:\n> +       tm = localtime(&now); /* get timezone and tm_isdst */\n> +       offset = -timezone / 60;\n> +       if (tm->tm_isdst > 0)\n> +               offset += 60;\n\nSome locales have DST offsets which aren't 60 minutes, don't they?\n\n-- \ndwmw2\n\n"},{"id":"2250","messageId":"1114862920.17673.1.camel@localhost.localdomain","threadId":"406","inReplyTo":"1114859594.24014.60.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Kay Sievers","fromEmail":"kay.sievers@vrfy.org","sentAt":"2005-04-30T12:08:40Z","receivedAt":"2005-04-30T12:08:40Z","isPatch":false,"sender":{"key":"kay.sievers@vrfy.org","avatar":null},"body":"On Sat, 2005-04-30 at 12:13 +0100, David Woodhouse wrote:\n> On Sat, 2005-04-30 at 12:53 +0200, Edgar Toernig wrote:\n> > +       tm = localtime(&now); /* get timezone and tm_isdst */\n> > +       offset = -timezone / 60;\n> > +       if (tm->tm_isdst > 0)\n> > +               offset += 60;\n> \n> Some locales have DST offsets which aren't 60 minutes, don't they?\n\nYes, some have half-hour offsets:\n  http://www.timeanddate.com/library/abbreviations/timezones/au/nft.html\n\nKay\n\n"},{"id":"2251","messageId":"1114863221.24014.68.camel@localhost.localdomain","threadId":"406","inReplyTo":"1114862920.17673.1.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"David Woodhouse","fromEmail":"dwmw2@infradead.org","sentAt":"2005-04-30T12:13:40Z","receivedAt":"2005-04-30T12:13:40Z","isPatch":false,"sender":{"key":"dwmw2@infradead.org","avatar":"https://gravatar.com/avatar/7afd4f07e0cf7d7e046ae2d23678296b37777c96488e6f3451e78a5514154ebd?d=mp&s=160"},"body":"On Sat, 2005-04-30 at 14:08 +0200, Kay Sievers wrote:\n> Yes, some have half-hour offsets:\n> http://www.timeanddate.com/library/abbreviations/timezones/au/nft.html\n\nThat doesn't count -- that timezone is honoured all year round. We're\ntalking about the difference between wintertime and summertime in any\ngiven locale.\n\nTBH I think I'd rather just put a gmt_mktime() which uses my trick of\nlooking at tm.tm_gmtoff after the mktime call into a separate file\nwrapped in #ifdef GLIBC and let anyone else who really cares about their\nown non-BSD-compatible system worry about whether it works there and fix\nit up accordingly.\n\n-- \ndwmw2\n\n"},{"id":"2253","messageId":"20050430144936.6b05cc90.froese@gmx.de","threadId":"406","inReplyTo":"1114859594.24014.60.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T12:49:36Z","receivedAt":"2005-04-30T12:49:36Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"David Woodhouse wrote:\n>\n> > +       if (tm->tm_isdst > 0)\n> > +               offset += 60;\n> \n> Some locales have DST offsets which aren't 60 minutes, don't they?\n\nOh shit :-/\n\nIf grepped through the tz-database and it seems there's one\n\"country\" left that has non-60-minute DST: Lord Howe Island.\nAll others dropped that before 1970.\n\nOk, here's a new version of the patch.\n\n--- k/Makefile  (mode:100644)\n+++ l/Makefile  (mode:100644)\n@@ -28,7 +28,8 @@ all: $(PROG)\n install: $(PROG) $(SCRIPTS)\n \tinstall $(PROG) $(SCRIPTS) $(HOME)/bin/\n \n-LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o tag.o\n+LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \\\n+\t tag.o date.o\n LIB_FILE=libgit.a\n LIB_H=cache.h object.h blob.h tree.h commit.h tag.h\n \n@@ -91,7 +92,6 @@ git-diff-tree-helper: diff-tree-helper.c\n git-tar-tree: tar-tree.c\n \n git-http-pull: LIBS += -lcurl\n-git-commit-tree: LIBS += -lcurl\n \n # Library objects..\n blob.o: $(LIB_H)\n--- k/cache.h  (mode:100644)\n+++ l/cache.h  (mode:100644)\n@@ -148,6 +148,9 @@ extern void *read_object_with_reference(\n \t\t\t\t\tunsigned long *size,\n \t\t\t\t\tunsigned char *sha1_ret);\n \n+void parse_date(char *date, char *buf, int bufsize);\n+void datestamp(char *buf, int bufsize);\n+\n static inline void *xmalloc(int size)\n {\n \tvoid *ret = malloc(size);\n--- k/commit-tree.c  (mode:100644)\n+++ l/commit-tree.c  (mode:100644)\n@@ -10,7 +10,6 @@\n #include <string.h>\n #include <ctype.h>\n #include <time.h>\n-#include <curl/curl.h>\n \n #define BLOCKING (1ul << 14)\n \n@@ -81,24 +80,6 @@ static void remove_special(char *p)\n \t}\n }\n \n-/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822\n-   (i.e. English) day/month names, and it doesn't work correctly with %z. */\n-static void parse_date(char *date, time_t *now, char *result, int maxlen)\n-{\n-\tchar *p;\n-\ttime_t then;\n-\n-\tif ((then = curl_getdate(date, now)) == 0)\n-\t\treturn;\n-\n-\t/* find the timezone at the end */\n-\tp = date + strlen(date);\n-\twhile (p > date && isdigit(*--p))\n-\t\t;\n-\tif ((*p == '+' || *p == '-') && strlen(p) == 5)\n-\t\tsnprintf(result, maxlen, \"%lu %5.5s\", then, p);\n-}\n-\n static void check_valid(unsigned char *sha1, const char *expect)\n {\n \tvoid *buf;\n@@ -132,8 +113,6 @@ int main(int argc, char **argv)\n \tchar *audate;\n \tchar comment[1000];\n \tstruct passwd *pw;\n-\ttime_t now;\n-\tstruct tm *tm;\n \tchar *buffer;\n \tunsigned int size;\n \n@@ -163,10 +142,8 @@ int main(int argc, char **argv)\n \t\tstrcat(realemail, \".\");\n \t\tgetdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);\n \t}\n-\ttime(&now);\n-\ttm = localtime(&now);\n \n-\tstrftime(realdate, sizeof(realdate), \"%s %z\", tm);\n+\tdatestamp(realdate, sizeof(realdate));\n \tstrcpy(date, realdate);\n \n \tcommitgecos = getenv(\"COMMIT_AUTHOR_NAME\") ? : realgecos;\n@@ -175,7 +152,7 @@ int main(int argc, char **argv)\n \temail = getenv(\"AUTHOR_EMAIL\") ? : realemail;\n \taudate = getenv(\"AUTHOR_DATE\");\n \tif (audate)\n-\t\tparse_date(audate, &now, date, sizeof(date));\n+\t\tparse_date(audate, date, sizeof(date));\n \n \tremove_special(gecos); remove_special(realgecos); remove_special(commitgecos);\n \tremove_special(email); remove_special(realemail); remove_special(commitemail);\n--- /dev/null\n+++ l/date.c  (mode:100644)\n@@ -0,0 +1,184 @@\n+/*\n+ * GIT - The information manager from hell\n+ *\n+ * Copyright (C) Linus Torvalds, 2005\n+ */\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <ctype.h>\n+#include <time.h>\n+\n+static time_t my_mktime(struct tm *tm)\n+{\n+\tstatic const int mdays[] = {\n+\t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n+\t};\n+\tint year = tm->tm_year - 70;\n+\tint month = tm->tm_mon;\n+\tint day = tm->tm_mday;\n+\n+\tif (year < 0 || year > 129) /* algo only works for 1970-2099 */\n+\t\treturn -1;\n+\tif (month < 0 || month > 11) /* array bounds */\n+\t\treturn -1;\n+\tif (month < 2 || (year + 2) % 4)\n+\t\tday--;\n+\treturn (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +\n+\t\ttm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;\n+}\n+\n+static const char *month_names[] = {\n+        \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n+        \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"\n+};\n+\n+static const char *weekday_names[] = {\n+        \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"\n+};\n+\n+\n+static char *skipfws(char *str)\n+{\n+\twhile (isspace(*str))\n+\t\tstr++;\n+\treturn str;\n+}\n+\n+\t\n+/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822\n+   (i.e. English) day/month names, and it doesn't work correctly with %z. */\n+void parse_date(char *date, char *result, int maxlen)\n+{\n+\tstruct tm tm;\n+\tchar *p, *tz;\n+\tint i, offset;\n+\ttime_t then;\n+\n+\tmemset(&tm, 0, sizeof(tm));\n+\n+\t/* Skip day-name */\n+\tp = skipfws(date);\n+\tif (!isdigit(*p)) {\n+\t\tfor (i=0; i<7; i++) {\n+\t\t\tif (!strncmp(p,weekday_names[i],3) && p[3] == ',') {\n+\t\t\t\tp = skipfws(p+4);\n+\t\t\t\tgoto day;\n+\t\t\t}\n+\t\t}\n+\t\treturn;\n+\t}\t\t\t\t\t\n+\n+\t/* day */\n+ day:\n+\ttm.tm_mday = strtoul(p, &p, 10);\n+\n+\tif (tm.tm_mday < 1 || tm.tm_mday > 31)\n+\t\treturn;\n+\n+\tif (!isspace(*p))\n+\t\treturn;\n+\n+\tp = skipfws(p);\n+\n+\t/* month */\n+\n+\tfor (i=0; i<12; i++) {\n+\t\tif (!strncmp(p, month_names[i], 3) && isspace(p[3])) {\n+\t\t\ttm.tm_mon = i;\n+\t\t\tp = skipfws(p+strlen(month_names[i]));\n+\t\t\tgoto year;\n+\t\t}\n+\t}\n+\treturn; /* Error -- bad month */\n+\n+\t/* year */\n+ year:\t\n+\ttm.tm_year = strtoul(p, &p, 10);\n+\n+\tif (!tm.tm_year && !isspace(*p))\n+\t\treturn;\n+\n+\tif (tm.tm_year > 1900)\n+\t\ttm.tm_year -= 1900;\n+\t\t\n+\tp=skipfws(p);\n+\n+\t/* hour */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_hour = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_hour > 23)\n+\t\treturn;\n+\n+\tif (*p != ':')\n+\t\treturn; /* Error -- bad time */\n+\tp++;\n+\n+\t/* minute */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_min = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_min > 59)\n+\t\treturn;\n+\n+\tif (*p != ':')\n+\t\tgoto zone;\n+\tp++;\n+\n+\t/* second */\n+\tif (!isdigit(*p))\n+\t\treturn;\n+\ttm.tm_sec = strtoul(p, &p, 10);\n+\t\n+\tif (tm.tm_sec > 59)\n+\t\treturn;\n+\n+ zone:\n+\tif (!isspace(*p))\n+\t\treturn;\n+\n+\tp = skipfws(p);\n+\n+\tif (*p == '-')\n+\t\toffset = -60;\n+\telse if (*p == '+')\n+\t\toffset = 60;\n+\telse\n+\t       return;\n+\n+\tif (!isdigit(p[1]) || !isdigit(p[2]) || !isdigit(p[3]) || !isdigit(p[4]))\n+\t\treturn;\n+\n+\ttz = p;\n+\ti = strtoul(p+1, NULL, 10);\n+\toffset *= ((i % 100) + ((i / 100) * 60));\n+\n+\tp = skipfws(p + 5);\n+\tif (*p && *p != '(') /* trailing comment like (EDT) is ok */\n+\t\treturn;\n+\n+\tthen = my_mktime(&tm); /* mktime uses local timezone */\n+\tif (then == -1)\n+\t\treturn;\n+\n+\tthen -= offset;\n+\n+\tsnprintf(result, maxlen, \"%lu %5.5s\", then, tz);\n+}\n+\n+void datestamp(char *buf, int bufsize)\n+{\n+\ttime_t now;\n+\tint offset;\n+\n+\ttime(&now);\n+\n+\toffset = my_mktime(localtime(&now)) - now;\n+\toffset /= 60;\n+\n+\tsnprintf(buf, bufsize, \"%lu %+05d\", now, offset/60*100 + offset%60);\n+}\n\nCiao, ET.\n"},{"id":"2254","messageId":"1114865964.24014.77.camel@localhost.localdomain","threadId":"406","inReplyTo":"20050430144936.6b05cc90.froese@gmx.de","subject":"Re: Trying to use AUTHOR_DATE","fromName":"David Woodhouse","fromEmail":"dwmw2@infradead.org","sentAt":"2005-04-30T12:59:23Z","receivedAt":"2005-04-30T12:59:23Z","isPatch":false,"sender":{"key":"dwmw2@infradead.org","avatar":"https://gravatar.com/avatar/7afd4f07e0cf7d7e046ae2d23678296b37777c96488e6f3451e78a5514154ebd?d=mp&s=160"},"body":"On Sat, 2005-04-30 at 14:49 +0200, Edgar Toernig wrote:\n> +       if (tm.tm_sec > 59)\n> +               return;\n\nDuring a leap second, won't tm_sec be 60? And in fact you don't seem to\nhandle leap seconds at all, so isn't my_mktime going to be out by one\nsecond for every leap second which has occurred since 1970?\n\nThere's a reason I'd rather just let glibc handle it :)\n\nIt's not as if tm_gmtoff is particularly esoteric -- we inherited it\nfrom BSD. Let's just use it and let both remaining HPUX users worry\nabout it themselves if they ever want to use git on their systems.\n\n-- \ndwmw2\n\n"},{"id":"2255","messageId":"20050430152252.0c3fd206.froese@gmx.de","threadId":"406","inReplyTo":"1114865964.24014.77.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T13:22:52Z","receivedAt":"2005-04-30T13:22:52Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"David Woodhouse wrote:\n>\n> On Sat, 2005-04-30 at 14:49 +0200, Edgar Toernig wrote:\n> > +       if (tm.tm_sec > 59)\n> > +               return;\n> \n> During a leap second, won't tm_sec be 60? And in fact you don't seem to\n> handle leap seconds at all, so isn't my_mktime going to be out by one\n> second for every leap second which has occurred since 1970?\n\nThere are no leap-seconds on POSIX systems.  They allow tm_sec\nto be 60 but thats all - 00:00:60 is the same as 00:01:00.\n\nWhether the check should be against 59 or 60?  I don't care.\nIt's Linus decision.\n\n> There's a reason I'd rather just let glibc handle it :)\n\nGood joke.\n\nCiao, ET.\n"},{"id":"2264","messageId":"87r7gs87a9.fsf@windlord.stanford.edu","threadId":"406","inReplyTo":"20050430124048.79119cac.froese@gmx.de","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Russ Allbery","fromEmail":"rra@stanford.edu","sentAt":"2005-04-30T18:10:38Z","receivedAt":"2005-04-30T18:10:38Z","isPatch":false,"sender":{"key":"rra@stanford.edu","avatar":null},"body":"Edgar Toernig <froese@gmx.de> writes:\n\n> Oh btw, when we are about sucking time functions: the %s and %z\n> strftime- sequences used further down are also non-standard (POSIX has\n> no %s, old libc has neither %s nor %z).\n\n> A possible workaround:\n\n[...]\n\n> \ttm = localtime(&now); /* get timezone and tm_isdst */\n> \ttz = -timezone / 60;\n> \tif (tm->tm_isdst > 0)\n> \t\ttz += 60;\n\nThe global timezone variable isn't available on all systems.  :)\n\nYou really cannot get portable behavior in this area without something\nakin to Autoconf probes, unfortunately.  Oh, and you can't assume daylight\nsavings time is an hour; it is sometimes two hours.  You have to instead\nuse the altzone variable to get the offset when you're in daylight savings\ntime, but this again isn't available on all systems.\n\nI posted a pointer to the INN source a while back; I'm really not sure\nthat anything less is sufficient to get full portability, although I\ncertainly trust Paul Eggart's implementation.\n\nBTW, the yacc-based thing is exactly what I wrote the INN code to get rid\nof, since I didn't want a yacc dependency.\n\n-- \nRuss Allbery (rra@stanford.edu)             <http://www.eyrie.org/~eagle/>\n"},{"id":"2265","messageId":"Pine.LNX.4.58.0504301322130.2296@ppc970.osdl.org","threadId":"406","inReplyTo":"87r7gs87a9.fsf@windlord.stanford.edu","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-30T20:32:35Z","receivedAt":"2005-04-30T20:32:35Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 30 Apr 2005, Russ Allbery wrote:\n> \n> You really cannot get portable behavior in this area without something\n> akin to Autoconf probes, unfortunately. \n\nOk, since this only really matters for AUTHOR_DATE, which we pass in as a\nrandom string anyway, and which comes from various mail programs which may\nor may not follow all RFC's, I just rewrote it to give \"almost correct \nresults\" for \"pretty much any crap you throw at it\".\n\nAs a test-bed, a \"test-date\" program that parses a date and then prints \nit out in git format _and_ in the local timezone format, here's a few \nexamples:\n\n\t./test-date \"$(date)\" \"April 4th, 1992 at 13:45\" \"13:04:09 +0100 2004 Yesterday, Friday 13th, December\"\n\nresults in\n\n\tSat Apr 30 13:26:52 PDT 2005 -> 1114892812 -0700 -> Sat Apr 30 13:26:52 2005\n\n\tApril 4th, 1992 at 13:45 -> 702395100 +0000 -> Sat Apr  4 05:45:00 1992\n\n\t13:04:09 +0100 2004 Yesterday, Friday 13th, December -> 1102939449 +0100 -> Mon Dec 13 04:04:09 2004\n\nwhich is just because it really doesn't check a hell of a lot.\n\nFor example, if you say\n\n\t\"I caught 14 fishes in December 1998\"\n\ntest-date will happily parse this as\n\n\tSun Dec 13 16:00:00 1998\n\n(That's \"0:00:00 Dec 14th, 1998 UTC\" shown in the local timezone ;). Or:\n\n\t./test-date  \"12:15 4/17/2009\"\n\n\t12:15 4/17/2009 -> 1239970500 +0000 -> Fri Apr 17 05:15:00 2009\n\nie it just greedily tries to make _some_ sense of the random strings you \nthrow at it.\n\nIt doesn't even try getting timezones right - it doesn't know about \nsummertime or anything. Besides, I probably used the wrong timezone info \nanyway.\n\nI'll probably tweak it a bit more (make \"no timezone means local \ntimezone\", for example, rather than UTC like it is now).\n\n\t\tLinus\n"},{"id":"2266","messageId":"7ism18exin.fsf@lanthane.pps.jussieu.fr","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504301322130.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Juliusz Chroboczek","fromEmail":"juliusz.chroboczek@pps.jussieu.fr","sentAt":"2005-04-30T21:59:44Z","receivedAt":"2005-04-30T21:59:44Z","isPatch":false,"sender":{"key":"juliusz.chroboczek@pps.jussieu.fr","avatar":null},"body":"Hi,\n\nHere's the code I'm using in darcs-git (copied from Polipo, another\nproject of mine).  You're welcome to use it in any way you see fit.\n\nsprintf_a is defined as strdup of sprintf.\n\n                                        Juliusz\n#if defined __GLIBC__\n#define HAVE_TM_GMTOFF\n#define HAVE_SETENV\n#ifndef __UCLIBC__\n#define HAVE_TIMEGM\n#endif\n#endif\n\n#if defined(__linux__) && (__GNU_LIBRARY__ == 1)\n/* Linux libc 5 */\n#define HAVE_TIMEGM\n#define HAVE_SETENV\n#endif\n\n#ifdef BSD\n#define HAVE_TM_GMTOFF\n#define HAVE_SETENV\n#endif\n\n#ifdef __CYGWIN__\n#define HAVE_SETENV\n#endif\n\n#if _POSIX_VERSION >= 200112L\n#define HAVE_SETENV\n#endif\n\n#define HAVE_TZSET\n\n/* Like mktime(3), but UTC rather than local time */\n#if defined(HAVE_TIMEGM)\ntime_t\nmktime_gmt(struct tm *tm)\n{\n    return timegm(tm);\n}\n#elif defined(HAVE_TM_GMTOFF)\ntime_t\nmktime_gmt(struct tm *tm)\n{\n    time_t t;\n    struct tm *ltm;\n\n    t = mktime(tm);\n    if(t < 0)\n        return -1;\n    ltm = localtime(&t);\n    if(ltm == NULL)\n        return -1;\n    return t + ltm->tm_gmtoff;\n}\n#elif defined(HAVE_TZSET)\n#ifdef HAVE_SETENV\n/* Taken from the Linux timegm(3) man page. */\ntime_t\nmktime_gmt(struct tm *tm)\n{\n    time_t t;\n    char *tz;\n\n    tz = getenv(\"TZ\");\n    setenv(\"TZ\", \"\", 1);\n    tzset();\n    t = mktime(tm);\n    if(tz)\n        setenv(\"TZ\", tz, 1);\n    else\n        unsetenv(\"TZ\");\n    tzset();\n    return t;\n}\n#else\ntime_t\nmktime_gmt(struct tm *tm)\n{\n    time_t t;\n    char *tz;\n    static char *old_tz = NULL;\n\n    tz = getenv(\"TZ\");\n    putenv(\"TZ=\");\n    tzset();\n    t = mktime(tm);\n    if(old_tz)\n        free(old_tz);\n    if(tz)\n        old_tz = sprintf_a(\"TZ=%s\", tz);\n    else\n        old_tz = strdup(\"TZ\");  /* XXX - non-portable? */\n    if(old_tz)\n        putenv(old_tz);\n    tzset();\n    return t;\n}\n#endif\n#else\n#error no mktime_gmt implementation on this platform\n#endif\n"},{"id":"2268","messageId":"20050501005434.2d47131a.froese@gmx.de","threadId":"406","inReplyTo":"Pine.LNX.4.58.0504301322130.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-04-30T22:54:34Z","receivedAt":"2005-04-30T22:54:34Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"Linus Torvalds wrote:\n>\n> [...] I just rewrote it to give \"almost correct \n> results\" for \"pretty much any crap you throw at it\".\n\nAnd I had the impression the strict checks in the original\nversion were intentionally ;-)\n\n> I'll probably tweak it a bit more (make \"no timezone means local \n> timezone\", for example, rather than UTC like it is now).\n\nHere's my try on that.  But whether it works everywhere ...\n\nBtw, your %+03d%02d printf gave wrong results for i.e. -0130 (-01-30).\n\n\n\n--- k/date.c  (mode:100644)\n+++ l/date.c  (mode:100644)\n@@ -10,7 +10,9 @@\n #include <ctype.h>\n #include <time.h>\n \n-static time_t my_mktime(struct tm *tm)\n+#define NO_TZ\t11111\n+\n+static time_t utc_mktime(struct tm *tm)\n {\n \tstatic const int mdays[] = {\n \t    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334\n@@ -23,12 +25,19 @@ static time_t my_mktime(struct tm *tm)\n \t\treturn -1;\n \tif (month < 0 || month > 11) /* array bounds */\n \t\treturn -1;\n+\tif (day < 1 || day > 31)\n+\t\treturn -1;\n \tif (month < 2 || (year + 2) % 4)\n \t\tday--;\n \treturn (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +\n \t\ttm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;\n }\n \n+static int local_offset(time_t *when)\n+{\n+\treturn (utc_mktime(localtime(when)) - *when) / 60;\n+}\n+\n static const char *month_names[] = {\n \t\"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \t\"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\n@@ -138,7 +147,8 @@ static int match_alpha(const char *date,\n \tfor (i = 0; i < NR_TZ; i++) {\n \t\tint match = match_string(date, timezone_names[i].name);\n \t\tif (match >= 3) {\n-\t\t\t*offset = 60*timezone_names[i].offset;\n+\t\t\tif (*offset == NO_TZ)\n+\t\t\t\t*offset = 60*timezone_names[i].offset;\n \t\t\treturn match;\n \t\t}\n \t}\n@@ -245,7 +255,7 @@ void parse_date(char *date, char *result\n \ttm.tm_year = -1;\n \ttm.tm_mon = -1;\n \ttm.tm_mday = -1;\n-\toffset = 0;\n+\toffset = NO_TZ;\n \n \tfor (;;) {\n \t\tint match = 0;\n@@ -270,13 +280,20 @@ void parse_date(char *date, char *result\n \t\tdate += match;\n \t}\n \n-\tthen = my_mktime(&tm); /* mktime uses local timezone */\n-\tif (then == -1)\n-\t\treturn;\n-\n-\tthen -= offset * 60;\n+\tif (offset == NO_TZ) {\n+\t\ttm.tm_isdst = -1;\n+\t\tthen = mktime(&tm);\n+\t\tif (then == -1)\n+\t\t\treturn;\n+\t\toffset = local_offset(&then);\n+\t} else {\n+\t\tthen = utc_mktime(&tm);\n+\t\tif (then == -1)\n+\t\t\treturn;\n+\t\tthen -= offset * 60;\n+\t}\n \n-\tsnprintf(result, maxlen, \"%lu %+03d%02d\", then, offset/60, offset % 60);\n+\tsnprintf(result, maxlen, \"%lu %+05d\", then, offset/60*100 + offset%60);\n }\n \n void datestamp(char *buf, int bufsize)\n@@ -285,9 +302,7 @@ void datestamp(char *buf, int bufsize)\n \tint offset;\n \n \ttime(&now);\n-\n-\toffset = my_mktime(localtime(&now)) - now;\n-\toffset /= 60;\n+\toffset = local_offset(&now);\n \n \tsnprintf(buf, bufsize, \"%lu %+05d\", now, offset/60*100 + offset%60);\n }\n\nCiao, ET.\n"},{"id":"2270","messageId":"42741173.9040507@zytor.com","threadId":"406","inReplyTo":"1114859594.24014.60.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-04-30T23:14:59Z","receivedAt":"2005-04-30T23:14:59Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"David Woodhouse wrote:\n> On Sat, 2005-04-30 at 12:53 +0200, Edgar Toernig wrote:\n> \n>>+       tm = localtime(&now); /* get timezone and tm_isdst */\n>>+       offset = -timezone / 60;\n>>+       if (tm->tm_isdst > 0)\n>>+               offset += 60;\n> \n> \n> Some locales have DST offsets which aren't 60 minutes, don't they?\n> \n\nCorrect.  I believe South Australia is among them.\n\n\t-hpa\n"},{"id":"2271","messageId":"Pine.LNX.4.58.0504301607570.2296@ppc970.osdl.org","threadId":"406","inReplyTo":"20050501005434.2d47131a.froese@gmx.de","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-04-30T23:18:11Z","receivedAt":"2005-04-30T23:18:11Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 1 May 2005, Edgar Toernig wrote:\n> \n> > I'll probably tweak it a bit more (make \"no timezone means local \n> > timezone\", for example, rather than UTC like it is now).\n> \n> Here's my try on that.  But whether it works everywhere ...\n\nI already did that part.\n\n> Btw, your %+03d%02d printf gave wrong results for i.e. -0130 (-01-30).\n\nDang. Oh, well. That's what I get for not testing.\n\nI don't much like that \"%+05s\" trick either, since that one also depends \non the direction of rounding for negative division (it just gets it right \nfor the normal case, and I guess C90 finally specified it precisely).\n\nLet's just do unsigned arithmetic and check the sign specially. I already \ndid that on input, just not on output.\n\n\t\tLinus\n"},{"id":"2299","messageId":"Pine.LNX.4.58.0505010934480.2296@ppc970.osdl.org","threadId":"406","inReplyTo":"20050501005434.2d47131a.froese@gmx.de","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-05-01T16:46:52Z","receivedAt":"2005-05-01T16:46:52Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 1 May 2005, Edgar Toernig wrote:\n> \n> And I had the impression the strict checks in the original\n> version were intentionally ;-)\n\nBtw, here's my test of every single email in my email archive (which is \nnot that big any more - after the SCO subpoena, I decided that I never \nwant to go through with that kind of crap ever again, so now it's only a \nmonth or two of things). \n\nAlmost everything seems to follow the RFC's or at least be close enough\nthat my \"accept anything\" ends up doing something sane, except for three\nemails:\n\n\tDate: Fri, 08 Apr 2005 02:20:10 0200 -> bad\n\tDate: Mon, 18 Apr 05 15:05:29 Hora oficial do Brasil -> bad\n\tDate: 2002/04/11 18:29:07 -> bad\n\nThat first one doesn't have a sign in front of the timezone (I'll fix\nthings up - right now I end up believing that it's \"year 200\"), and the\nthird one has the sane European date order that sorts nicely (and which\nI'll also fix up).\n\nThe second one is funny. Not just the \"Hora oficial do Brasil\" (hey, I \ncould add it as a real timezone and my parser would do the right thing ;) \nbut also because my parser decides that \"05\" is not a year, but the day in \nthe month, so it doesn't see the year.\n\nI can fake out that year thing pretty easily (\"if it starts with '0' it's \nnot a day of the month\"), but it does show just how _strange_ stuff \nthere's out there.\n\n(\"Hora\" is also Swedish for \"whore\", so that timezone does end up being\nmentally parsed _quite_ the wrong way for somebody like me who doesn't\nspeak spanish).\n\n\t\t\tLinus\n"},{"id":"2300","messageId":"20050501095738.5ca03d16.rddunlap@osdl.org","threadId":"406","inReplyTo":"Pine.LNX.4.58.0505010934480.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Randy.Dunlap","fromEmail":"rddunlap@osdl.org","sentAt":"2005-05-01T16:57:38Z","receivedAt":"2005-05-01T16:57:38Z","isPatch":false,"sender":{"key":"rddunlap@osdl.org","avatar":null},"body":"On Sun, 1 May 2005 09:46:52 -0700 (PDT) Linus Torvalds wrote:\n\n| \n| \n| On Sun, 1 May 2005, Edgar Toernig wrote:\n| > \n| > And I had the impression the strict checks in the original\n| > version were intentionally ;-)\n| \n| Btw, here's my test of every single email in my email archive (which is \n| not that big any more - after the SCO subpoena, I decided that I never \n| want to go through with that kind of crap ever again, so now it's only a \n| month or two of things). \n| \n| Almost everything seems to follow the RFC's or at least be close enough\n| that my \"accept anything\" ends up doing something sane, except for three\n| emails:\n| \n| \tDate: Fri, 08 Apr 2005 02:20:10 0200 -> bad\n| \tDate: Mon, 18 Apr 05 15:05:29 Hora oficial do Brasil -> bad\n| \tDate: 2002/04/11 18:29:07 -> bad\n| \n| That first one doesn't have a sign in front of the timezone (I'll fix\n| things up - right now I end up believing that it's \"year 200\"), and the\n| third one has the sane European date order that sorts nicely (and which\n| I'll also fix up).\n\nThird one is almost ISO 8601 standard date format, except that\nISO uses hyphens, e.g., 2002-04-11, so I hope that the\npunctation is a little flexible...\n\n| The second one is funny. Not just the \"Hora oficial do Brasil\" (hey, I \n| could add it as a real timezone and my parser would do the right thing ;) \n| but also because my parser decides that \"05\" is not a year, but the day in \n| the month, so it doesn't see the year.\n| \n| I can fake out that year thing pretty easily (\"if it starts with '0' it's \n| not a day of the month\"), but it does show just how _strange_ stuff \n| there's out there.\n| \n| (\"Hora\" is also Swedish for \"whore\", so that timezone does end up being\n| mentally parsed _quite_ the wrong way for somebody like me who doesn't\n| speak spanish).\n\n\n---\n~Randy\n"},{"id":"2303","messageId":"20050501192303.49ed8f0c.froese@gmx.de","threadId":"406","inReplyTo":"Pine.LNX.4.58.0505010934480.2296@ppc970.osdl.org","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Edgar Toernig","fromEmail":"froese@gmx.de","sentAt":"2005-05-01T17:23:03Z","receivedAt":"2005-05-01T17:23:03Z","isPatch":false,"sender":{"key":"froese@gmx.de","avatar":null},"body":"Linus Torvalds wrote:\n>\n> \tDate: Fri, 08 Apr 2005 02:20:10 0200 -> bad\n> \tDate: Mon, 18 Apr 05 15:05:29 Hora oficial do Brasil -> bad\n> \tDate: 2002/04/11 18:29:07 -> bad\n> \n> The second one is funny. Not just the \"Hora oficial do Brasil\" (hey, I \n> could add it as a real timezone and my parser would do the right thing ;) \n> but also because my parser decides that \"05\" is not a year, but the day in \n> the month, so it doesn't see the year.\n> \n> I can fake out that year thing pretty easily (\"if it starts with '0' it's \n> not a day of the month\"), but it does show just how _strange_ stuff \n> there's out there.\n\nAnd what happens then with the first example?  2008 Apr 2005?\n\n\nI thought about missing timezones once more.  Don't you think it's\nbetter to default to -0000?  Afaics, it was defined for just these\ncases.  Simply appending an arbitrary timezone seems wrong.\n\nCiao, ET.\n"},{"id":"2404","messageId":"m3wtqhe0t6.fsf@defiant.localdomain","threadId":"406","inReplyTo":"1114865964.24014.77.camel@localhost.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Krzysztof Halasa","fromEmail":"khc@pm.waw.pl","sentAt":"2005-05-02T22:10:45Z","receivedAt":"2005-05-02T22:10:45Z","isPatch":false,"sender":{"key":"khc@pm.waw.pl","avatar":null},"body":"David Woodhouse <dwmw2@infradead.org> writes:\n\n> During a leap second, won't tm_sec be 60?\n\nYou could rather have two 59th seconds. Or the \"seconds\" could be, say,\n0.1% longer for 1000 s. Depends on synchronization mechanism.\n\nI think 60th second could only be possible with leap-seconds aware\nthings (NTP, GPS, reference radio clocks etc.).\n\n> And in fact you don't seem to\n> handle leap seconds at all, so isn't my_mktime going to be out by one\n> second for every leap second which has occurred since 1970?\n\nNo, actually the system time (i.e., the number of seconds since 1970)\nis already corrected (minutes are seconds/60, hrs = minutes/60 etc.)\nYou are off calculating time deltas, but I guess if you need such\naccuracy your software already knows about leap seconds.\n-- \nKrzysztof Halasa\n"},{"id":"2409","messageId":"4276A906.2040403@zytor.com","threadId":"406","inReplyTo":"m3wtqhe0t6.fsf@defiant.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-02T22:26:14Z","receivedAt":"2005-05-02T22:26:14Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Krzysztof Halasa wrote:\n> David Woodhouse <dwmw2@infradead.org> writes:\n> \n>>During a leap second, won't tm_sec be 60?\n> \n> You could rather have two 59th seconds. Or the \"seconds\" could be, say,\n> 0.1% longer for 1000 s. Depends on synchronization mechanism.\n>  \n> I think 60th second could only be possible with leap-seconds aware\n> things (NTP, GPS, reference radio clocks etc.).\n> \n\nIt is, but you can't assume you don't have that.  Either way, you just \ntreat it the same as the following second.\n\n\t-hpa\n"},{"id":"2415","messageId":"m3mzrddx44.fsf@defiant.localdomain","threadId":"406","inReplyTo":"4276A906.2040403@zytor.com","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Krzysztof Halasa","fromEmail":"khc@pm.waw.pl","sentAt":"2005-05-02T23:30:35Z","receivedAt":"2005-05-02T23:30:35Z","isPatch":false,"sender":{"key":"khc@pm.waw.pl","avatar":null},"body":"\"H. Peter Anvin\" <hpa@zytor.com> writes:\n\n> It is, but you can't assume you don't have that.\n\nYes, if you use NTP time (directly - not the system time) you can get\nsecond=60 (and, in theory, even 61 - not to be expected soon).\n\n>  Either way, you just\n> treat it the same as the following second.\n\nSure, that's the safe way.\n-- \nKrzysztof Halasa\n"},{"id":"2416","messageId":"4276B8A1.7070500@zytor.com","threadId":"406","inReplyTo":"m3mzrddx44.fsf@defiant.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-02T23:32:49Z","receivedAt":"2005-05-02T23:32:49Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Krzysztof Halasa wrote:\n> \"H. Peter Anvin\" <hpa@zytor.com> writes:\n> \n> \n>>It is, but you can't assume you don't have that.\n> \n> \n> Yes, if you use NTP time (directly - not the system time) you can get\n> second=60 (and, in theory, even 61 - not to be expected soon).\n> \n\nNo.  You cannot get 61.  You can, however, get jumps from 58 to 00.\n\n> \n>> Either way, you just\n>>treat it the same as the following second.\n> \n> Sure, that's the safe way.\n"},{"id":"2423","messageId":"m38y2xdubr.fsf@defiant.localdomain","threadId":"406","inReplyTo":"4276B8A1.7070500@zytor.com","subject":"Re: Trying to use AUTHOR_DATE","fromName":"Krzysztof Halasa","fromEmail":"khc@pm.waw.pl","sentAt":"2005-05-03T00:30:48Z","receivedAt":"2005-05-03T00:30:48Z","isPatch":false,"sender":{"key":"khc@pm.waw.pl","avatar":null},"body":"\"H. Peter Anvin\" <hpa@zytor.com> writes:\n\n> No.  You cannot get 61.\n\nI was told it would be possible if two leap seconds were needed in some\npoint of time. Have never occured yet, and maybe never will.\n\nWell, it seems it would need two seconds a month (at least 13 leap seconds\na year) -> not in this century if ever, and it wouldn't be UTC anymore.\n\n> You can, however, get jumps from 58 to 00.\n\nCorrect, that would be a deletion. Not yet tried, either, but they say\nit's possible.\n-- \nKrzysztof Halasa\n"},{"id":"2425","messageId":"4276C817.3090304@zytor.com","threadId":"406","inReplyTo":"m38y2xdubr.fsf@defiant.localdomain","subject":"Re: Trying to use AUTHOR_DATE","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-05-03T00:38:47Z","receivedAt":"2005-05-03T00:38:47Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Krzysztof Halasa wrote:\n> \"H. Peter Anvin\" <hpa@zytor.com> writes:\n> \n> \n>>No.  You cannot get 61.\n> \n> I was told it would be possible if two leap seconds were needed in some\n> point of time. Have never occured yet, and maybe never will.\n> \n> Well, it seems it would need two seconds a month (at least 13 leap seconds\n> a year) -> not in this century if ever, and it wouldn't be UTC anymore.\n> \n\nIt's certainly not permitted by the current UTC definition, which only \nallows 4 leap seconds per year.  61 comes from a typo in an old version \nof the POSIX standard.\n\n>>You can, however, get jumps from 58 to 00.\n> \n> Correct, that would be a deletion. Not yet tried, either, but they say\n> it's possible.\n\n... and permitted by the current UTC standard.\n\n\t-hpa\n"}]}