525
}
526
}
527
528
- if (num > 0 && num < 32) {
529
- tm->tm_mday = num;
530
- } else if (num > 0 && num < 13) {
528
+ if (num > 0 && num < 13 && tm->tm_mon < 0)
529
tm->tm_mon = num-1;
532
- }
530
531
return n;
532
}
654
date_string(now, offset, buf, bufsize);
655
}
656
660
-static void update_tm(struct tm *tm, unsigned long sec)
657
+/*
658
+ * Relative time update (eg "2 days ago"). If we haven't set the time
659
+ * yet, we need to set it from current time.
660
+ */
661
+static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
662
{
662
- time_t n = mktime(tm) - sec;
663
+ time_t n;
664
+
665
+ if (tm->tm_mday < 0)
666
+ tm->tm_mday = now->tm_mday;
667
+ if (tm->tm_mon < 0)
668
+ tm->tm_mon = now->tm_mon;
669
+ if (tm->tm_year < 0) {
670
+ tm->tm_year = now->tm_year;
671
+ if (tm->tm_mon > now->tm_mon)
672
+ tm->tm_year--;
673
+ }
674
+
675
+ n = mktime(tm) - sec;
676
localtime_r(&n, tm);
677
+ return n;
678
}
679
666
-static void date_yesterday(struct tm *tm, int *num)
680
+static void date_yesterday(struct tm *tm, struct tm *now, int *num)
681
{
668
- update_tm(tm, 24*60*60);
682
+ update_tm(tm, now, 24*60*60);
683
}
684
671
-static void date_time(struct tm *tm, int hour)
685
+static void date_time(struct tm *tm, struct tm *now, int hour)
686
{
687
if (tm->tm_hour < hour)
674
- date_yesterday(tm, NULL);
688
+ date_yesterday(tm, now, NULL);
689
tm->tm_hour = hour;
690
tm->tm_min = 0;
691
tm->tm_sec = 0;
692
}
693
680
-static void date_midnight(struct tm *tm, int *num)
694
+static void date_midnight(struct tm *tm, struct tm *now, int *num)
695
{
682
- date_time(tm, 0);
696
+ date_time(tm, now, 0);
697
}
698
685
-static void date_noon(struct tm *tm, int *num)
699
+static void date_noon(struct tm *tm, struct tm *now, int *num)
700
{
687
- date_time(tm, 12);
701
+ date_time(tm, now, 12);
702
}
703
690
-static void date_tea(struct tm *tm, int *num)
704
+static void date_tea(struct tm *tm, struct tm *now, int *num)
705
{
692
- date_time(tm, 17);
706
+ date_time(tm, now, 17);
707
}
708
695
-static void date_pm(struct tm *tm, int *num)
709
+static void date_pm(struct tm *tm, struct tm *now, int *num)
710
{
711
int hour, n = *num;
712
*num = 0;
720
tm->tm_hour = (hour % 12) + 12;
721
}
722
709
-static void date_am(struct tm *tm, int *num)
723
+static void date_am(struct tm *tm, struct tm *now, int *num)
724
{
725
int hour, n = *num;
726
*num = 0;
734
tm->tm_hour = (hour % 12);
735
}
736
723
-static void date_never(struct tm *tm, int *num)
737
+static void date_never(struct tm *tm, struct tm *now, int *num)
738
{
739
time_t n = 0;
740
localtime_r(&n, tm);
742
743
static const struct special {
744
const char *name;
731
- void (*fn)(struct tm *, int *);
745
+ void (*fn)(struct tm *, struct tm *, int *);
746
} special[] = {
747
{ "yesterday", date_yesterday },
748
{ "noon", date_noon },
771
{ NULL }
772
};
773
760
-static const char *approxidate_alpha(const char *date, struct tm *tm, int *num)
774
+static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm *now, int *num)
775
{
776
const struct typelen *tl;
777
const struct special *s;
792
for (s = special; s->name; s++) {
793
int len = strlen(s->name);
794
if (match_string(date, s->name) == len) {
781
- s->fn(tm, num);
795
+ s->fn(tm, now, num);
796
return end;
797
}
798
}
814
while (tl->type) {
815
int len = strlen(tl->type);
816
if (match_string(date, tl->type) >= len-1) {
803
- update_tm(tm, tl->length * *num);
817
+ update_tm(tm, now, tl->length * *num);
818
*num = 0;
819
return end;
820
}
832
n++;
833
diff += 7*n;
834
821
- update_tm(tm, diff * 24 * 60 * 60);
835
+ update_tm(tm, now, diff * 24 * 60 * 60);
836
return end;
837
}
838
}
880
return end;
881
}
882
883
+/*
884
+ * Do we have a pending number at the end, or when
885
+ * we see a new one? Let's assume it's a month day,
886
+ * as in "Dec 6, 1992"
887
+ */
888
+static void pending_number(struct tm *tm, int *num)
889
+{
890
+ int number = *num;
891
+
892
+ if (number) {
893
+ *num = 0;
894
+ if (tm->tm_mday < 0 && number < 32)
895
+ tm->tm_mday = number;
896
+ }
897
+}
898
+
899
unsigned long approxidate(const char *date)
900
{
901
int number = 0;
911
time_sec = tv.tv_sec;
912
localtime_r(&time_sec, &tm);
913
now = tm;
914
+
915
+ tm.tm_year = -1;
916
+ tm.tm_mon = -1;
917
+ tm.tm_mday = -1;
918
+
919
for (;;) {
920
unsigned char c = *date;
921
if (!c)
922
break;
923
date++;
924
if (isdigit(c)) {
925
+ pending_number(&tm, &number);
926
date = approxidate_digit(date-1, &tm, &number);
927
continue;
928
}
929
if (isalpha(c))
894
- date = approxidate_alpha(date-1, &tm, &number);
930
+ date = approxidate_alpha(date-1, &tm, &now, &number);
931
}
896
- if (number > 0 && number < 32)
897
- tm.tm_mday = number;
898
- if (tm.tm_mon > now.tm_mon && tm.tm_year == now.tm_year)
899
- tm.tm_year--;
900
- return mktime(&tm);
932
+ pending_number(&tm, &number);
933
+ return update_tm(&tm, &now, 0);
934
}