Interval arithmetic: the oprcode functions behind timestamp ± interval, interval ± interval, -interval, interval * n and
interval / n.
THE MONTH/DAY/MICROSECOND SPLIT IS NOT AN IMPLEMENTATION DETAIL. An
interval's three fields are added to a timestamp in three separate
stages, in a fixed order, and each stage has different semantics
(timestamp_pl_interval, timestamp.c:3070-3180):
MONTHS go through the broken-down time, with year/month carry and
then a CLAMP of the day to the target month's length. This is
what makes '2001-01-31' + '1 mon' February 28 rather than
March 3.
DAYS go through date2j/j2date -- pure Julian-day arithmetic,
no clamping, so '2001-01-31' + '30 days' is March 2.
MICROSECONDS are added to the final value.
Collapsing any of this into "a month is 30 days" gives the wrong
answer for most of the calendar. The 30-day equivalence belongs to
interval_cmp_value, which is about COMPARING two intervals, and
nowhere else.
Interval arithmetic: the `oprcode` functions behind `timestamp ±
interval`, `interval ± interval`, `-interval`, `interval * n` and
`interval / n`.
THE MONTH/DAY/MICROSECOND SPLIT IS NOT AN IMPLEMENTATION DETAIL. An
interval's three fields are added to a timestamp in three separate
stages, in a fixed order, and each stage has different semantics
(`timestamp_pl_interval`, timestamp.c:3070-3180):
MONTHS go through the broken-down time, with year/month carry and
then a CLAMP of the day to the target month's length. This is
what makes `'2001-01-31' + '1 mon'` February 28 rather than
March 3.
DAYS go through `date2j`/`j2date` -- pure Julian-day arithmetic,
no clamping, so `'2001-01-31' + '30 days'` is March 2.
MICROSECONDS are added to the final value.
Collapsing any of this into "a month is 30 days" gives the wrong
answer for most of the calendar. The 30-day equivalence belongs to
`interval_cmp_value`, which is about COMPARING two intervals, and
nowhere else.(add a b)interval_pl: field-wise addition.
`interval_pl`: field-wise addition.
(divide iv factor)interval_div. Division by zero is 22012, not an interval error.
`interval_div`. Division by zero is 22012, not an interval error.
(multiply iv factor)interval_mul. The fractional parts cascade DOWNWARD -- a fraction
of a month becomes days (at 30 per month), and a fraction of a day
becomes seconds -- which is why '1 mon' * 0.5 is 15 days and not
half a month.
`interval_mul`. The fractional parts cascade DOWNWARD -- a fraction of a month becomes days (at 30 per month), and a fraction of a day becomes seconds -- which is why `'1 mon' * 0.5` is 15 days and not half a month.
(negate iv)interval_um_internal: negate all three fields.
`interval_um_internal`: negate all three fields.
(subtract a b)interval_mi. Not add of the negation in the C, but the same
result for every finite pair; the infinity handling differs only in
which message you get, and both are interval out of range.
`interval_mi`. Not `add` of the negation in the C, but the same result for every finite pair; the infinity handling differs only in which message you get, and both are `interval out of range`.
(time-plus usec-of-day iv)time_pl_interval (date.c:1745-1762): the microseconds only, WRAPPED
into a single day. The months and days of the interval are ignored
entirely -- a time has nowhere to put them -- so
'12:00'::time + '1 mon' is 12:00.
An infinite interval is an error here, with its own message.
`time_pl_interval` (date.c:1745-1762): the microseconds only, WRAPPED into a single day. The months and days of the interval are ignored entirely -- a time has nowhere to put them -- so `'12:00'::time + '1 mon'` is 12:00. An infinite interval is an error here, with its own message.
(timestamp-minus ts iv conv)timestamp_mi_interval: plus the negation. The C negates the
interval and calls the same code, and so does this -- which is why
'2001-03-31' - '1 mon' clamps to February 28 exactly as the
addition would.
`timestamp_mi_interval`: plus the negation. The C negates the interval and calls the same code, and so does this -- which is why `'2001-03-31' - '1 mon'` clamps to February 28 exactly as the addition would.
(timestamp-plus ts iv {:keys [ts->fields fields->ts]})timestamp_pl_interval. tm->ts and ts->tm are the caller's
conversions, so this works for whichever temporal carrier the call
site holds.
An infinite interval makes the result infinite, EXCEPT against a timestamp infinite the other way, which is an error. An infinite TIMESTAMP with a finite interval is returned unchanged.
`timestamp_pl_interval`. `tm->ts` and `ts->tm` are the caller's conversions, so this works for whichever temporal carrier the call site holds. An infinite interval makes the result infinite, EXCEPT against a timestamp infinite the other way, which is an error. An infinite TIMESTAMP with a finite interval is returned unchanged.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |