]> git.ipfire.org Git - thirdparty/git.git/blobdiff - date.c
git-prompt: change == to = for zsh's sake
[thirdparty/git.git] / date.c
diff --git a/date.c b/date.c
index b67c5abe24a4b484e3d3afbbe7f2e00027245071..f9ea807b3a9f9ee64a4173fa923f31b00455e840 100644 (file)
--- a/date.c
+++ b/date.c
@@ -539,6 +539,25 @@ static int set_date(int year, int month, int day, struct tm *now_tm, time_t now,
        return -1;
 }
 
+static int set_time(long hour, long minute, long second, struct tm *tm)
+{
+       /* We accept 61st second because of leap second */
+       if (0 <= hour && hour <= 24 &&
+           0 <= minute && minute < 60 &&
+           0 <= second && second <= 60) {
+               tm->tm_hour = hour;
+               tm->tm_min = minute;
+               tm->tm_sec = second;
+               return 0;
+       }
+       return -1;
+}
+
+static int is_date_known(struct tm *tm)
+{
+       return tm->tm_year != -1 && tm->tm_mon != -1 && tm->tm_mday != -1;
+}
+
 static int match_multi_number(timestamp_t num, char c, const char *date,
                              char *end, struct tm *tm, time_t now)
 {
@@ -556,10 +575,14 @@ static int match_multi_number(timestamp_t num, char c, const char *date,
        case ':':
                if (num3 < 0)
                        num3 = 0;
-               if (num < 25 && num2 >= 0 && num2 < 60 && num3 >= 0 && num3 <= 60) {
-                       tm->tm_hour = num;
-                       tm->tm_min = num2;
-                       tm->tm_sec = num3;
+               if (set_time(num, num2, num3, tm) == 0) {
+                       /*
+                        * If %H:%M:%S was just parsed followed by: .<num4>
+                        * Consider (& discard) it as fractional second
+                        * if %Y%m%d is parsed before.
+                        */
+                       if (*end == '.' && isdigit(end[1]) && is_date_known(tm))
+                               strtol(end + 1, &end, 10);
                        break;
                }
                return 0;
@@ -664,6 +687,20 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
                n++;
        } while (isdigit(date[n]));
 
+       /* 8 digits, compact style of ISO-8601's date: YYYYmmDD */
+       /* 6 digits, compact style of ISO-8601's time: HHMMSS */
+       if (n == 8 || n == 6) {
+               unsigned int num1 = num / 10000;
+               unsigned int num2 = (num % 10000) / 100;
+               unsigned int num3 = num % 100;
+               if (n == 8)
+                       set_date(num1, num2, num3, NULL, time(NULL), tm);
+               else if (n == 6 && set_time(num1, num2, num3, tm) == 0 &&
+                        *end == '.' && isdigit(end[1]))
+                       strtoul(end + 1, &end, 10);
+               return end - date;
+       }
+
        /* Four-digit year or a timezone? */
        if (n == 4) {
                if (num <= 1400 && *offset == -1) {