summaryrefslogtreecommitdiff
path: root/Src/Modules/datetime.c
diff options
context:
space:
mode:
authordana <dana@dana.is>2018-11-13 13:01:01 -0600
committerdana <dana@dana.is>2018-11-13 13:01:01 -0600
commit5ad76492af8931added1ae9600309d915d1427a5 (patch)
tree61450721cfc810d4154c1875c3519bc5927f8dbb /Src/Modules/datetime.c
parent0b3b52778bd7a4a2c97637c3d4739a7e66a695b1 (diff)
downloadzsh-5ad76492af8931added1ae9600309d915d1427a5.tar.gz
zsh-5ad76492af8931added1ae9600309d915d1427a5.zip
43800: Add nanosecond support to strftime built-in
Diffstat (limited to 'Src/Modules/datetime.c')
-rw-r--r--Src/Modules/datetime.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index be378b347..18c7fb58e 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -100,8 +100,8 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
{
int bufsize, x, len;
char *endptr = NULL, *scalar = NULL, *buffer;
- time_t secs;
- struct tm *t;
+ struct tm *tm;
+ struct timespec ts;
if (OPT_ISSET(ops,'s')) {
scalar = OPT_ARG(ops, 's');
@@ -110,30 +110,58 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
return 1;
}
}
- if (OPT_ISSET(ops, 'r'))
+ if (OPT_ISSET(ops, 'r')) {
+ if (!argv[1]) {
+ zwarnnam(nam, "timestring expected");
+ return 1;
+ }
return reverse_strftime(nam, argv, scalar, OPT_ISSET(ops, 'q'));
-
- errno = 0;
- secs = (time_t)strtoul(argv[1], &endptr, 10);
- if (errno != 0) {
- zwarnnam(nam, "%s: %e", argv[1], errno);
- return 1;
- } else if (*endptr != '\0') {
- zwarnnam(nam, "%s: invalid decimal number", argv[1]);
- return 1;
}
- t = localtime(&secs);
- if (!t) {
- zwarnnam(nam, "%s: unable to convert to time", argv[1]);
- return 1;
+ if (!argv[1]) {
+ zgettime(&ts);
+ tm = localtime(&ts.tv_sec);
+ } else {
+ errno = 0;
+
+ ts.tv_sec = (time_t)strtoul(argv[1], &endptr, 10);
+ if (errno != 0) {
+ zwarnnam(nam, "%s: %e", argv[1], errno);
+ return 1;
+ } else if (*argv[1] == '\0' || *endptr != '\0') {
+ zwarnnam(nam, "%s: invalid decimal number", argv[1]);
+ return 1;
+ }
+
+ tm = localtime(&ts.tv_sec);
+ if (!tm) {
+ zwarnnam(nam, "%s: unable to convert to time", argv[1]);
+ return 1;
+ }
+
+ ts.tv_nsec = 0L;
+ if (argv[2]) {
+ ts.tv_nsec = (long)zstrtol(argv[2], &endptr, 10);
+ if (errno != 0) {
+ zwarnnam(nam, "%s: %e", argv[2], errno);
+ return 1;
+ } else if (*argv[2] == '\0' || *endptr != '\0') {
+ zwarnnam(nam, "%s: invalid decimal number", argv[2]);
+ return 1;
+ } else if (ts.tv_nsec < 0) {
+ zwarnnam(nam, "%s: invalid nanosecond value", argv[2]);
+ return 1;
+ }
+ }
}
+
bufsize = strlen(argv[0]) * 8;
buffer = zalloc(bufsize);
len = 0;
for (x=0; x < 4; x++) {
- if ((len = ztrftime(buffer, bufsize, argv[0], t, 0L)) >= 0 || x==3)
+ if ((len = ztrftime(buffer, bufsize, argv[0], tm, ts.tv_nsec)) >= 0 ||
+ x==3)
break;
buffer = zrealloc(buffer, bufsize *= 2);
}
@@ -207,7 +235,7 @@ getcurrenttime(UNUSED(Param pm))
}
static struct builtin bintab[] = {
- BUILTIN("strftime", 0, bin_strftime, 2, 2, 0, "qrs:", NULL),
+ BUILTIN("strftime", 0, bin_strftime, 1, 3, 0, "qrs:", NULL),
};
static const struct gsu_integer epochseconds_gsu =