/*
* Relative time update (eg "2 days ago"). If we haven't set the time
* yet, we need to set it from current time.
+ *
+ * The tm->tm_mday field has an additional logic of using negative values
+ * for date adjustments: -2 means yesterday and -3 the day before that,
+ * and so on. The idea is to deref such adjustments until we are sure
+ * there's no explicit mday specification in the approxidate string.
*/
static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
{
time_t n;
- if (tm->tm_mday < 0)
+ if (tm->tm_mday < 0) {
+ int offset = tm->tm_mday + 1;
+ if (sec == 0 && offset < 0)
+ sec = -offset * 24*60*60;
tm->tm_mday = now->tm_mday;
+ }
if (tm->tm_mon < 0)
tm->tm_mon = now->tm_mon;
if (tm->tm_year < 0) {
static void date_yesterday(struct tm *tm, struct tm *now, int *num)
{
*num = 0;
+ tm->tm_mday = -1;
update_tm(tm, now, 24*60*60);
}
-static void date_time(struct tm *tm, struct tm *now, int hour)
+static void date_time(struct tm *tm, int hour)
{
/*
* If we do not yet have a specified day, we'll use the most recent
* version of "hour" relative to now. But that may be yesterday.
*/
if (tm->tm_mday < 0 && tm->tm_hour < hour)
- update_tm(tm, now, 24*60*60);
+ tm->tm_mday = -2; /* eventually handled by update_tm() */
tm->tm_hour = hour;
tm->tm_min = 0;
tm->tm_sec = 0;
}
-static void date_midnight(struct tm *tm, struct tm *now, int *num)
+static void date_midnight(struct tm *tm, struct tm *now UNUSED, int *num)
{
pending_number(tm, num);
- date_time(tm, now, 0);
+ date_time(tm, 0);
}
-static void date_noon(struct tm *tm, struct tm *now, int *num)
+static void date_noon(struct tm *tm, struct tm *now UNUSED, int *num)
{
pending_number(tm, num);
- date_time(tm, now, 12);
+ date_time(tm, 12);
}
-static void date_tea(struct tm *tm, struct tm *now, int *num)
+static void date_tea(struct tm *tm, struct tm *now UNUSED, int *num)
{
pending_number(tm, num);
- date_time(tm, now, 17);
+ date_time(tm, 17);
}
static void date_pm(struct tm *tm, struct tm *now UNUSED, int *num)
if (tm->tm_hour == now->tm_hour &&
tm->tm_min == now->tm_min &&
tm->tm_sec == now->tm_sec)
- date_time(tm, now, 0);
+ date_time(tm, 0);
*num = 0;
+ tm->tm_mday = -1;
update_tm(tm, now, 0);
}
check_approxidate '15:00' '2009-08-30 15:00:00'
check_approxidate 'noon today' '2009-08-30 12:00:00'
check_approxidate 'today at noon' '2009-08-30 12:00:00' '-12 hours'
+check_approxidate 'noon today' '2009-09-01 12:00:00' '+36 hours'
check_approxidate 'noon yesterday' '2009-08-29 12:00:00'
+check_approxidate 'noon yesterday' '2009-08-29 12:00:00' '-12 hours'
check_approxidate 'last Friday at noon' '2009-08-28 12:00:00'
check_approxidate 'last Friday at noon' '2009-08-28 12:00:00' '-12 hours'
+check_approxidate 'tea last saturday' '2009-08-29 17:00:00'
+check_approxidate 'tea last saturday' '2009-08-29 17:00:00' '-12 hours'
check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00'
check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00' '-12 hours'
check_approxidate 'January 5th today pm' '2009-01-30 12:00:00'