summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2006-08-17 15:28:11 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2006-08-17 15:28:11 +0000
commitd0b9eddd9a320bed6d87c07d26048bbf6816115c (patch)
tree10759c39d2a13bd1d4749e6fd5da87c3eb94c643
parent1a42aadd81240fdb7f0acc38ddeef38898b705ab (diff)
downloadzsh-d0b9eddd9a320bed6d87c07d26048bbf6816115c.tar.gz
zsh-d0b9eddd9a320bed6d87c07d26048bbf6816115c.zip
22613: add strftime -r to use strptime() if available
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/mod_datetime.yo21
-rw-r--r--Src/Modules/datetime.c66
-rw-r--r--configure.ac3
4 files changed, 90 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index ef0d8f7c7..e80bf8314 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2006-08-17 Peter Stephenson <pws@csr.com>
+ * 22613: configure.ac, Doc/Zsh/mod_datetime.yo,
+ Src/Modules/datetime.c: add strftime -r to use strptime()
+ if available.
+
* 22612: Src/Zle/complist.c: comment the static variables.
2006-08-16 Peter Stephenson <pws@csr.com>
@@ -19,7 +23,7 @@
2006-08-14 Peter Stephenson <pws@csr.com>
- * 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
diff --git a/Doc/Zsh/mod_datetime.yo b/Doc/Zsh/mod_datetime.yo
index b006baf89..145d4a181 100644
--- a/Doc/Zsh/mod_datetime.yo
+++ b/Doc/Zsh/mod_datetime.yo
@@ -6,12 +6,27 @@ The tt(zsh/datetime) module makes available one builtin command:
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()
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 8b5ff5d68..add4b303b 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -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 @@ bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
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 @@ getcurrentsecs()
}
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 =
diff --git a/configure.ac b/configure.ac
index 75f4d7687..21e7764e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1096,7 +1096,8 @@ dnl ---------------
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 \