sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit ed78aef5b180cf1d82f03e8ae43c62317f273962
parent 1b41610a820215cdc569129e1cada5c6267fcecb
Author: John Vogel <jvogel4@stny.rr.com>
Date:   Sun,  1 Jan 2017 20:09:53 -0500

date: add date/time setting capability

[Michael Forney: Moved functionality to setdate, other minor tweaks]

Diffstat:
date.1 | 52++++++++++++++++++++++++++++++++++++++++++++++++----
date.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 109 insertions(+), 10 deletions(-)

diff --git a/date.1 b/date.1 @@ -3,12 +3,17 @@ .Os sbase .Sh NAME .Nm date -.Nd print date and time +.Nd print or set date and time .Sh SYNOPSIS .Nm .Op Fl d Ar time .Op Fl u -.Op Cm + Ns Ar format +.Oo +.Cm + Ns Ar format | +.Sm off +.Ar mmddHHMM Oo Oo Ar CC Oc Ar yy Oc +.Sm on +.Oc .Sh DESCRIPTION .Nm prints the date and time according to @@ -16,7 +21,8 @@ prints the date and time according to or .Ar format using -.Xr strftime 3 . +.Xr strftime 3 +or sets the date. .Sh OPTIONS .Bl -tag -width Ds .It Fl d Ar time @@ -25,8 +31,46 @@ Print given as the number of seconds since the Unix epoch 1970-01-01T00:00:00Z. .It Fl u -Print UTC time instead of local time. +Print or set UTC time instead of local time. .El +.Pp +An operand with a leading plus +.Pq Cm + +sign signals a user-defined format string using +.Xr strftime 3 +conversion specifications. +.Pp +An operand without a leading plus sign is interpreted as a value +for setting the system's current date and time. The canonical +representation for setting the date and time is: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar mm +The month of the year, from 01 to 12. +.It Ar dd +The day of the month, from 01 to 31. +.It Ar HH +The hour of the day, from 00 to 23. +.It Ar MM +The minute of the hour, from 00 to 59. +.It Ar CC +The first two digits of the year (the century). +.It Ar yy +The second two digits of the year. +If +.Ar yy +is specified, but +.Ar CC +is not, a value for +.Ar yy +between 69 and 99 results in a +.Ar CC +value of 19. Otherwise, a +.Ar CC +value of 20 is used. +.El +.Pp +The century and year are optional. The default is the current year. .Sh STANDARDS The .Nm diff --git a/date.c b/date.c @@ -1,6 +1,8 @@ /* See LICENSE file for copyright and license details. */ +#include <ctype.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <time.h> #include "util.h" @@ -8,7 +10,55 @@ static void usage(void) { - eprintf("usage: %s [-u] [-d time] [+format]\n", argv0); + eprintf("usage: %s [-u] [-d time] [+format | mmddHHMM[[CC]yy]]\n", argv0); +} + +static int +datefield(const char *s, size_t i) +{ + if (!isdigit(s[i]) || !isdigit(s[i+1])) + eprintf("invalid date format: %s\n", s); + + return (s[i] - '0') * 10 + (s[i+1] - '0'); +} + +static void +setdate(const char *s, struct tm *now) +{ + struct tm date; + struct timespec ts; + + switch (strlen(s)) { + case 8: + date.tm_year = now->tm_year; + break; + case 10: + date.tm_year = datefield(s, 8); + if (date.tm_year < 69) + date.tm_year += 100; + break; + case 12: + date.tm_year = ((datefield(s, 8) - 19) * 100) + datefield(s, 10); + break; + default: + eprintf("invalid date format: %s\n", s); + break; + } + + date.tm_mon = datefield(s, 0) - 1; + date.tm_mday = datefield(s, 2); + date.tm_hour = datefield(s, 4); + date.tm_min = datefield(s, 6); + date.tm_sec = 0; + date.tm_isdst = -1; + + ts.tv_sec = mktime(&date); + if (ts.tv_sec == -1) + eprintf("mktime:"); + ts.tv_nsec = 0; + + if (clock_settime(CLOCK_REALTIME, &ts) == -1) + eprintf("clock_settime:"); } int @@ -19,6 +69,8 @@ main(int argc, char *argv[]) char buf[BUFSIZ], *fmt = "%c"; t = time(NULL); + if (t == -1) + eprintf("time:"); ARGBEGIN { case 'd': @@ -32,14 +84,17 @@ main(int argc, char *argv[]) usage(); } ARGEND + if (!(now = localtime(&t))) + eprintf("localtime:"); if (argc) { - if (argc != 1 || argv[0][0] != '+') + if (argc != 1) usage(); - else - fmt = &argv[0][1]; + if (argv[0][0] != '+') { + setdate(argv[0], now); + return 0; + } + fmt = &argv[0][1]; } - if (!(now = localtime(&t))) - eprintf("localtime:"); strftime(buf, sizeof(buf), fmt, now); puts(buf);