This series aims to extend support for ISO-8601 datetime format to allow compact version, and fractional part of ISO-8601. Change in v5 from v4: * cleanup [3/4] following Junio's suggestion. Changes in v4 from v3: * s/is_date/set_date/ the function's name suggest it only does validation, but it does more than that. Junio suggested to me to use it for validation, When I looked more into it, I think it's better to not use it, and rename the function to reduce the confusion * Extract the validate and set time to its own function * Correct a check for time in compact ISO-8601 Changes in v3 from v2: * Add example for fractional parts of second in documentation * Add/Fix regression test on 12:34:56.7.days.ago Đoàn Trần Công Danh (4): date.c: s/is_date/set_date/ date.c: validate and set time in a helper function date.c: skip fractional second part of ISO-8601 date.c: allow compact version of ISO-8601 datetime Đoàn Trần Công Danh (4): date.c: s/is_date/set_date/ date.c: validate and set time in a helper function date.c: skip fractional second part of ISO-8601 date.c: allow compact version of ISO-8601 datetime Documentation/date-formats.txt | 5 ++- date.c | 67 ++++++++++++++++++++++++++-------- t/t0006-date.sh | 6 +++ 3 files changed, 62 insertions(+), 16 deletions(-) Range-diff against v4: 1: 1fe69008fc = 1: 1fe69008fc date.c: s/is_date/set_date/ 2: 0d0e4d8edc ! 2: a6b97b19f2 date.c: validate and set time in a helper function @@ Commit message Signed-off-by: Đoàn Trần Công Danh <congdanhqx@xxxxxxxxx> + + ## Notes ## + I intentionally leave a pair of bracket around if (set_time(...)) + to reduce the noise in next patch + ## date.c ## @@ date.c: static int set_date(int year, int month, int day, struct tm *now_tm, time_t now, return -1; @@ date.c: static int set_date(int year, int month, int day, struct tm *now_tm, tim +static int set_time(long hour, long minute, long second, struct tm *tm) +{ -+ /* C90 and old POSIX accepts 2 leap seconds, it's a defect, -+ * ignore second number 61 -+ */ ++ /* We accept 61st second because of leap second */ + if (0 <= hour && hour <= 24 && + 0 <= minute && minute < 60 && + 0 <= second && second <= 60) { @@ date.c: static int match_multi_number(timestamp_t num, char c, const char *date, - tm->tm_hour = num; - tm->tm_min = num2; - tm->tm_sec = num3; -+ if (set_time(num, num2, num3, tm) == 0) ++ if (set_time(num, num2, num3, tm) == 0) { break; -- } + } return 0; - - case '-': 3: 8b18d0ee5d ! 3: f21aa2dcf5 date.c: skip fractional second part of ISO-8601 @@ Commit message relative to current time. Reported-by: Brian M. Carlson <sandals@xxxxxxxxxxxxxxxxxxxx> + Helped-by: Junio C Hamano <gitster@xxxxxxxxx> Signed-off-by: Đoàn Trần Công Danh <congdanhqx@xxxxxxxxx> ## Documentation/date-formats.txt ## @@ Documentation/date-formats.txt: RFC 2822:: `YYYY.MM.DD`, `MM/DD/YYYY` and `DD.MM.YYYY`. ## date.c ## +@@ date.c: static int set_time(long hour, long minute, long second, struct tm *tm) + 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) + { @@ date.c: static int match_multi_number(timestamp_t num, char c, const char *date, - /* Time? Date? */ - switch (c) { - case ':': -- if (num3 < 0) -+ if (num3 < 0) { + if (num3 < 0) num3 = 0; -+ } else if (*end == '.' && isdigit(end[1]) && -+ tm->tm_year != -1 && tm->tm_mon != -1 && tm->tm_mday != -1 && -+ set_time(num, num2, num3, tm) == 0) { -+ /* %Y%m%d is known, ignore fractional <num4> in HHMMSS.<num4> */ -+ strtol(end + 1, &end, 10); -+ } - if (set_time(num, num2, num3, tm) == 0) + 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; ## t/t0006-date.sh ## 4: 2812439a26 = 4: 51aa60c069 date.c: allow compact version of ISO-8601 datetime -- 2.26.2.384.g435bf60bd5