Allow date -s to accept a format specifier

Some examples:
  # Set the date to time_t=1343286000 (which is July 26, 2012)
  date +%s -s 1343286000

  # Set the date to the first day of the year 2012.
  date +%Y -s 2012

Change-Id: I493f98ba6216b59375e999f744ecf2434c606a10
diff --git a/date.c b/date.c
index ae9282f..467e1e4 100644
--- a/date.c
+++ b/date.c
@@ -48,18 +48,39 @@
 #endif
 }
 
+static void settime_fmt(char *s, const char *fmt) {
+     struct tm tm;
+     struct timeval tv;
+
+     memset(&tm, 0, sizeof(tm));
+     if (strptime(s, fmt, &tm) == NULL) {
+       fprintf(stderr, "Unable to parse date '%s' as format '%s'\n", s, fmt);
+       exit(1);
+     }
+
+     tv.tv_sec = mktime(&tm);
+     tv.tv_usec = 0;
+     if (settimeofday(&tv, NULL)) {
+       char buf[80];
+       snprintf(buf, sizeof(buf), "settimeofday(%ld)", tv.tv_sec);
+       perror(buf);
+       exit(1);
+     }
+}
+
 int date_main(int argc, char *argv[])
 {
-	int c;
+    int c;
     int res;
-	struct tm tm;
-	time_t t;
-	struct timeval tv;
+    struct tm tm;
+    time_t t;
+    struct timeval tv;
     struct timespec ts;
-	char strbuf[260];
+    char strbuf[260];
     int fd;
 
     int useutc = 0;
+    void *settime_arg = NULL;
 
     tzset();
 
@@ -72,7 +93,7 @@
             useutc = 1;
             break;
         case 's':
-            settime(optarg);
+            settime_arg = optarg;
             break;
         case '?':
             fprintf(stderr, "%s: invalid option -%c\n",
@@ -86,7 +107,13 @@
     }
 
     int hasfmt = argc == optind + 1 && argv[optind][0] == '+';
-    if(optind == argc || hasfmt) {
+    if (settime_arg) {
+        if (hasfmt) {
+          settime_fmt(settime_arg, argv[optind] + 1);
+        } else{
+          settime(settime_arg);
+        }
+    } else if(optind == argc || hasfmt) {
         char buf[2000];
         time(&t);
         if (useutc) {