I wrote: > Hmm, yeah. The "stride_usecs > 1" test seems like it's a partial > attempt to account for this that is probably redundant given the > additional condition. Also, can we avoid computing tm_diff % > stride_usecs twice? Maybe the compiler is smart enough to remove the > common subexpression, but it's a mighty expensive computation if not.
I think we could do it like this: tm_diff = timestamp - origin; tm_modulo = tm_diff % stride_usecs; tm_delta = tm_diff - tm_modulo; /* We want to round towards -infinity when tm_diff is negative */ if (tm_modulo < 0) tm_delta -= stride_usecs; Excluding tm_modulo == 0 from the correction is what fixes the problem. > I'm also itching a bit over whether there are integer-overflow > hazards here. Maybe the range of timestamp is constrained enough > that there aren't, but I didn't look hard. Hmm, it's not. For instance this triggers the overflow check in timestamp_mi: regression=# select '294000-01-01'::timestamp - '4714-11-24 00:00:00 BC'; ERROR: interval out of range regression=# \errverbose ERROR: 22008: interval out of range LOCATION: timestamp_mi, timestamp.c:2832 So we ought to guard the subtraction that produces tm_diff similarly. I suspect it's also possible to overflow int64 while computing stride_usecs. regards, tom lane