about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README7
-rw-r--r--wcal.17
-rw-r--r--wcal.c37
3 files changed, 43 insertions, 8 deletions
diff --git a/README b/README
index ee15776..9f0a548 100644
--- a/README
+++ b/README
@@ -4,7 +4,7 @@ NAME
      wcal – ISO weekly calendar
 
 SYNOPSIS
-     wcal [-13yci] [-d YYYY-MM-DD]
+     wcal [-13yci] [-d YYYY[-MM[-DD]]]
 
 DESCRIPTION
      The wcal utility prints a week-oriented calendar.  Each week is prefixed
@@ -24,8 +24,9 @@ DESCRIPTION
 
      -i      Show the calendar starting from the current week indefinitely.
 
-     -d YYYY-MM-DDD
-             Show the calendar for a different date than today.
+     -d YYYY[-MM[-DD]]
+             Show the calendar for a different date than today.  Implies -y in
+             case only a year is passed.
 
 EXIT STATUS
      The wcal utility exits 0 on success, and >0 if an error occurs.
diff --git a/wcal.1 b/wcal.1
index 4371958..28885bf 100644
--- a/wcal.1
+++ b/wcal.1
@@ -7,7 +7,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl 13yci
-.Op Fl d Ar YYYY-MM-DD
+.Op Fl d Ar YYYY Ns Op Ar -MM Ns Op Ar -DD
 .Sh DESCRIPTION
 The
 .Nm
@@ -29,8 +29,11 @@ Show the calendar for the whole year.
 Show the calendar for the current week.
 .It Fl i
 Show the calendar starting from the current week indefinitely.
-.It Fl d Ar YYYY-MM-DDD
+.It Fl d Ar YYYY Ns Op Ar -MM Ns Op Ar -DD
 Show the calendar for a different date than today.
+Implies
+.Fl y
+in case only a year is passed.
 .El
 .Sh EXIT STATUS
 .Ex -std
diff --git a/wcal.c b/wcal.c
index 9390f22..1435996 100644
--- a/wcal.c
+++ b/wcal.c
@@ -16,12 +16,44 @@
  */
 
 #define _XOPEN_SOURCE 700
-#include <time.h>
+#include <ctype.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
 #include <unistd.h>
 
 int flag1, flag3, flagc, flagi, flagy;
 
+void
+parse_isodate(char *optarg, struct tm *tm)
+{
+	tm->tm_hour = 12;  /* avoid DST problems */
+	tm->tm_min = tm->tm_sec = 0;
+	tm->tm_mday = 1;
+	tm->tm_mon = 0;
+
+	if (isdigit(optarg[0]) &&
+	    isdigit(optarg[1]) &&
+	    isdigit(optarg[2]) &&
+	    isdigit(optarg[3]) &&
+	    (!optarg[4] || optarg[4] == '-')) {
+		tm->tm_year = atoi(optarg) - 1900;
+
+		if (!optarg[4]) {
+			flagy = 1;
+		} else if (isdigit(optarg[5]) && isdigit(optarg[6]) &&
+		    (!optarg[7] || optarg[7] == '-')) {
+			tm->tm_mon = atoi(optarg+5) - 1;
+
+			if (isdigit(optarg[8]) && isdigit(optarg[9]) &&
+			    (!optarg[10] || optarg[10] == '-'))
+				tm->tm_mday = atoi(optarg+8);
+		}
+	}
+
+	mktime(tm);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -36,8 +68,7 @@ main(int argc, char *argv[])
 		case 'c': flagc = 1; break;
 		case 'y': flagy = 1; break;
 		case 'i': flagi = 1; break;
-		// XXX error handling, or write a parser oneself...
-		case 'd': strptime(optarg, "%Y-%m-%d", tm); break;
+		case 'd': parse_isodate(optarg, tm); break;
 		}
 
 	tm->tm_hour = 12;  /* avoid DST problems */