approxidate: handle pending number for "specials"
The approxidate parser has a table of special keywords like "yesterday", "noon", "pm", etc. Some of these, like "pm", do the right thing if we've recently seen a number: "3pm" is what you'd think. However, most of them do not look at or modify the pending-number flag at all, which means a number may "jump" across a significant keyword and be used unexpectedly. For example, when parsing: January 5th noon pm we'd connect the "5" to "pm", and ignore it as a day-of-month. This is obviously a bit silly, as "noon" already implies "pm". And other mis-parsed things are generally as silly ("January 5th noon, years ago" would connect the 5 to "years", but probably nobody would type that). However, the fix is simple: when we see a keyword like "noon", we should flush the pending number (as we would if we hit another number, or the end of the string). In a few of the specials that actually modify the day, we can simply throw away the number (saying "Jan 5 yesterday" should not respect the number at all). Note that we have to either move or forward-declare the static pending_number() to make it accessible to these functions; this patch moves it. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
b4cfcde4db
commit
c27cc94fad
60
date.c
60
date.c
@ -887,13 +887,42 @@ static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do we have a pending number at the end, or when
|
||||||
|
* we see a new one? Let's assume it's a month day,
|
||||||
|
* as in "Dec 6, 1992"
|
||||||
|
*/
|
||||||
|
static void pending_number(struct tm *tm, int *num)
|
||||||
|
{
|
||||||
|
int number = *num;
|
||||||
|
|
||||||
|
if (number) {
|
||||||
|
*num = 0;
|
||||||
|
if (tm->tm_mday < 0 && number < 32)
|
||||||
|
tm->tm_mday = number;
|
||||||
|
else if (tm->tm_mon < 0 && number < 13)
|
||||||
|
tm->tm_mon = number-1;
|
||||||
|
else if (tm->tm_year < 0) {
|
||||||
|
if (number > 1969 && number < 2100)
|
||||||
|
tm->tm_year = number - 1900;
|
||||||
|
else if (number > 69 && number < 100)
|
||||||
|
tm->tm_year = number;
|
||||||
|
else if (number < 38)
|
||||||
|
tm->tm_year = 100 + number;
|
||||||
|
/* We screw up for number = 00 ? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void date_now(struct tm *tm, struct tm *now, int *num)
|
static void date_now(struct tm *tm, struct tm *now, int *num)
|
||||||
{
|
{
|
||||||
|
*num = 0;
|
||||||
update_tm(tm, now, 0);
|
update_tm(tm, now, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void date_yesterday(struct tm *tm, struct tm *now, int *num)
|
static void date_yesterday(struct tm *tm, struct tm *now, int *num)
|
||||||
{
|
{
|
||||||
|
*num = 0;
|
||||||
update_tm(tm, now, 24*60*60);
|
update_tm(tm, now, 24*60*60);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,16 +937,19 @@ static void date_time(struct tm *tm, struct tm *now, int hour)
|
|||||||
|
|
||||||
static void date_midnight(struct tm *tm, struct tm *now, int *num)
|
static void date_midnight(struct tm *tm, struct tm *now, int *num)
|
||||||
{
|
{
|
||||||
|
pending_number(tm, num);
|
||||||
date_time(tm, now, 0);
|
date_time(tm, now, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void date_noon(struct tm *tm, struct tm *now, int *num)
|
static void date_noon(struct tm *tm, struct tm *now, int *num)
|
||||||
{
|
{
|
||||||
|
pending_number(tm, num);
|
||||||
date_time(tm, now, 12);
|
date_time(tm, now, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void date_tea(struct tm *tm, struct tm *now, int *num)
|
static void date_tea(struct tm *tm, struct tm *now, int *num)
|
||||||
{
|
{
|
||||||
|
pending_number(tm, num);
|
||||||
date_time(tm, now, 17);
|
date_time(tm, now, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,6 +985,7 @@ static void date_never(struct tm *tm, struct tm *now, int *num)
|
|||||||
{
|
{
|
||||||
time_t n = 0;
|
time_t n = 0;
|
||||||
localtime_r(&n, tm);
|
localtime_r(&n, tm);
|
||||||
|
*num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct special {
|
static const struct special {
|
||||||
@ -1110,33 +1143,6 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num,
|
|||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Do we have a pending number at the end, or when
|
|
||||||
* we see a new one? Let's assume it's a month day,
|
|
||||||
* as in "Dec 6, 1992"
|
|
||||||
*/
|
|
||||||
static void pending_number(struct tm *tm, int *num)
|
|
||||||
{
|
|
||||||
int number = *num;
|
|
||||||
|
|
||||||
if (number) {
|
|
||||||
*num = 0;
|
|
||||||
if (tm->tm_mday < 0 && number < 32)
|
|
||||||
tm->tm_mday = number;
|
|
||||||
else if (tm->tm_mon < 0 && number < 13)
|
|
||||||
tm->tm_mon = number-1;
|
|
||||||
else if (tm->tm_year < 0) {
|
|
||||||
if (number > 1969 && number < 2100)
|
|
||||||
tm->tm_year = number - 1900;
|
|
||||||
else if (number > 69 && number < 100)
|
|
||||||
tm->tm_year = number;
|
|
||||||
else if (number < 38)
|
|
||||||
tm->tm_year = 100 + number;
|
|
||||||
/* We screw up for number = 00 ? */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static timestamp_t approxidate_str(const char *date,
|
static timestamp_t approxidate_str(const char *date,
|
||||||
const struct timeval *tv,
|
const struct timeval *tv,
|
||||||
int *error_ret)
|
int *error_ret)
|
||||||
|
@ -113,6 +113,7 @@ check_approxidate '3:00' '2009-08-30 03:00:00'
|
|||||||
check_approxidate '15:00' '2009-08-30 15:00:00'
|
check_approxidate '15:00' '2009-08-30 15:00:00'
|
||||||
check_approxidate 'noon today' '2009-08-30 12:00:00'
|
check_approxidate 'noon today' '2009-08-30 12:00:00'
|
||||||
check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
|
check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
|
||||||
|
check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
|
||||||
|
|
||||||
check_approxidate 'last tuesday' '2009-08-25 19:20:00'
|
check_approxidate 'last tuesday' '2009-08-25 19:20:00'
|
||||||
check_approxidate 'July 5th' '2009-07-05 19:20:00'
|
check_approxidate 'July 5th' '2009-07-05 19:20:00'
|
||||||
|
Loading…
Reference in New Issue
Block a user