Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: strftime -r (strptime)



This makes strftime -r in the zsh/datetime module do a reverse match,
turning a string into an epoch time via strptime().  This small addition
is enough to allow quite powerful functions, which I may get around to
writing.

Index: ChangeLog
===================================================================
RCS file: /cvsroot/zsh/zsh/ChangeLog,v
retrieving revision 1.3227
diff -u -r1.3227 ChangeLog
--- ChangeLog	17 Aug 2006 09:34:11 -0000	1.3227
+++ ChangeLog	17 Aug 2006 15:16:35 -0000
@@ -19,7 +19,7 @@
 
 2006-08-14  Peter Stephenson  <pws@xxxxxxx>
 
-	* 22608: Doc/Zsh/contrib.yo: improvments on 22606.
+	* 22608: Doc/Zsh/contrib.yo: improvements on 22606.
 
 	* 22606: Doc/Zsh/contrib.yo, Functions/Zle/match-word-context,
 	Functions/Zle/match-words-by-style, Functions/Zle/.distfiles: new
Index: configure.ac
===================================================================
RCS file: /cvsroot/zsh/zsh/configure.ac,v
retrieving revision 1.56
diff -u -r1.56 configure.ac
--- configure.ac	4 Aug 2006 09:20:25 -0000	1.56
+++ configure.ac	17 Aug 2006 15:16:39 -0000
@@ -1096,7 +1096,8 @@
 dnl need to integrate this function
 dnl AC_FUNC_STRFTIME
 
-AC_CHECK_FUNCS(strftime difftime gettimeofday \
+AC_CHECK_FUNCS(strftime strptime mktime timelocal \
+	       difftime gettimeofday \
 	       select poll \
 	       readlink faccessx fchdir ftruncate \
 	       fstat lstat lchown fchown fchmod \
Index: Doc/Zsh/mod_datetime.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_datetime.yo,v
retrieving revision 1.2
diff -u -r1.2 mod_datetime.yo
--- Doc/Zsh/mod_datetime.yo	22 Jan 2004 17:51:06 -0000	1.2
+++ Doc/Zsh/mod_datetime.yo	17 Aug 2006 15:16:40 -0000
@@ -6,12 +6,27 @@
 startitem()
 findex(strftime)
 cindex(date string, printing)
-item(tt(strftime) [ tt(-s) var(scalar) ] var(format) var(epochtime) )(
+xitem(tt(strftime) [ tt(-s) var(scalar) ] var(format) var(epochtime) )
+item(tt(strftime) tt(-r) [ tt(-q) ] [ tt(-s) var(scalar) ] var(format) var(timestring) )(
 Output the date denoted by var(epochtime) in the var(format)
 specified.
 
-If tt(-s) var(scalar) is given, assign the date to var(scalar) instead
-of printing it.
+With the option tt(-r) (reverse), use the format var(format) to parse the
+input string var(timestring) and output the number of seconds since the
+epoch at which the time occurred.  If no timezone is parsed, the current
+timezone is used; other parameters are set to zero if not present.  If
+var(timestring) does not match var(format) the command returns status 1; it
+will additionally print an error message unless the option tt(-q) (quiet)
+is given.  If var(timestring) matches var(format) but not all characters in
+var(timestring) were used, the conversion succeeds; however, a warning is
+issued unless the option tt(-q) is given.  The matching is implemented by
+the system function tt(strptime); see manref(strptime)(3).  This means that
+zsh format extensions are not available, however for reverse lookup they
+are not required.  If the function is not implemented, the command returns
+status 2 and (unless tt(-q) is given) prints a message.
+
+If tt(-s) var(scalar) is given, assign the date string (or epoch time
+in seconds if tt(-r) is given) to var(scalar) instead of printing it.
 )
 enditem()
 
Index: Src/Modules/datetime.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/datetime.c,v
retrieving revision 1.14
diff -u -r1.14 datetime.c
--- Src/Modules/datetime.c	30 May 2006 22:35:03 -0000	1.14
+++ Src/Modules/datetime.c	17 Aug 2006 15:16:40 -0000
@@ -31,6 +31,68 @@
 #include "datetime.pro"
 #include <time.h>
 
+#ifndef HAVE_MKTIME
+#ifdef HAVE_TIMELOCAL
+#define	mktime(x)	timelocal(x)
+#define HAVE_MKTIME	1
+#endif
+#endif
+
+static int
+reverse_strftime(char *nam, char **argv, char *scalar, int quiet)
+{
+#if defined(HAVE_STRPTIME) && defined(HAVE_MKTIME)
+    struct tm tm;
+    zlong mytime;
+    char *endp;
+
+    /*
+     * Initialise all parameters to zero; there's no floating point
+     * so memset() will do the trick.  The exception is that tm_isdst
+     * is set to -1 which, if not overridden, will cause mktime()
+     * to use the current timezone.  This is probably the best guess;
+     * it's the one that will cause dates and times output by strftime
+     * without the -r option and without an explicit timezone to be
+     * converted back correctly.
+     */
+    (void)memset(&tm, 0, sizeof(tm));
+    tm.tm_isdst = -1;
+    endp = strptime(argv[1], argv[0], &tm);
+
+    if (!endp) {
+	/* Conversion failed completely. */
+	if (!quiet)
+	    zwarnnam(nam, "format not matched");
+	return 1;
+    }
+
+    mytime = (zlong)mktime(&tm);
+
+    if (scalar)
+	setiparam(scalar, mytime);
+    else {
+	char buf[DIGBUFSIZE];
+	convbase(buf, mytime, 10);
+	printf("%s\n", buf);
+    }
+
+    if (*endp && !quiet) {
+	/*
+	 * Not everything in the input string was converted.
+	 * This is probably benign, since the format has been satisfied,
+	 * but issue a warning unless the quiet flag is set.
+	 */
+	zwarnnam(nam, "warning: input string not completely matched");
+    }
+
+    return 0;
+#else
+    if (!quiet)
+	zwarnnam(nam, "not implemented on this system");
+    return 2;
+#endif
+}
+
 static int
 bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
 {
@@ -46,6 +108,8 @@
 	    return 1;
 	}
     }
+    if (OPT_ISSET(ops, 'r'))
+	return reverse_strftime(nam, argv, scalar, OPT_ISSET(ops, 'q'));
 
     secs = (time_t)strtoul(argv[1], &endptr, 10);
     if (secs == (time_t)ULONG_MAX) {
@@ -83,7 +147,7 @@
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("strftime",    0, bin_strftime,    2,   2, 0, "s:", NULL),
+    BUILTIN("strftime",    0, bin_strftime,    2,   2, 0, "qrs:", NULL),
 };
 
 static const struct gsu_integer epochseconds_gsu =

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php



Messages sorted by: Reverse Date, Date, Thread, Author