-
Notifications
You must be signed in to change notification settings - Fork 40
We have noticed an issue with the validation of certain rules related to durations.
Analysis
The problem is that BT-109-Lot sometimes becomes mandatory, although the duration (BT-536-Lot / BT-537-Lot) is less than 4 years.
Examples where this occurred: 01/01/2027 - 31/12/2030 or 01/10/2026 - 30/09/2030.
Here is the corresponding EFX expression: {ND-LotTenderingProcess} ${BT-765-Lot not in ('fa-mix','fa-w-rc','fa-wo-rc') or not(((BT-537-Lot - BT-536-Lot) > P4Y) or (BT-36-Lot > P4Y))}
However, the error only occurs on certain days. The problem is the comparison between a date difference ("BT-537-Lot - BT-536-Lot") and an ISO 8601 duration ("P4Y") and/or the order in which the different units of a duration are added to a date (from large to small, i.e. first Y, then M, then D).
Example
Today’s date: 12/03/2026
Duration from: 01/10/2026
Duration to: 30/09/2030
=> Duration as ISO 8601 duration: P3Y11M29D
Comparison date 1: 12/03/2026 + P3Y11M29D = 13/03/2030, because:
12/03/2026 + 3Y = 12/03/2029, 12/03/2029 + 11M = 12/02/2030, 12/02/2030 + 29D = 13/03/2030
Condition as duration: P4Y
Comparison date 2: 12/03/2026 + P4Y = 12/03/2030
=> The supposedly shorter duration of P3Y11M29D results in a later comparison date. As a result, P3Y11M29D > P4Y is evaluated as true and BT-109-Lot becomes mandatory.
The above example with today’s date (30/04/2026):
Today’s date: 30/04/2026
Duration from: 01/10/2026
Duration to: 30/09/2030
=> Duration as ISO 8601 duration: P3Y11M29D
Comparison date 1: 30/04/2026 + P3Y11M29D = 28/04/2030, because:
30/04/2026 + 3Y = 30/04/2029, 30/04/2029 + 11M = 30/03/2029, 30/03/2029 + 29D = 28/04/2030
Condition as duration: P4Y
Comparison date 2: 30/04/2026 + P4Y = 30/04/2030
=> Here P3Y11M29D actually results in an earlier comparison date and BT-109-Lot is not mandatory.
It is questionable whether the Schematron code has the same problem: [...] boolean(for $T in (current-date()) return ($T + xs:dayTimeDuration(../cac:ProcurementProject/cac:PlannedPeriod/cbc:EndDate/xs:date(text()) - ../cac:ProcurementProject/cac:PlannedPeriod/cbc:StartDate/xs:date(text())) > $T + xs:yearMonthDuration('P4Y'))) [...]
Is this a known issue, or is it specific to our application?
All reactions
Replies: 2 comments 1 reply
It is new to me that the comparison of durations depends on the current day. It is NOT new to me that duration calculation becomes tricky when comparing years with sums of days and months. I do remember a formula in eForms with a duration in days, which slightly exceeded the exact day count.
(I feel pressed to cite XKCD #2867 -- The elapsed time between two events is "impossible to know and a sin to ask").
Perhaps one should only declare the justification technically mandatory if the duration exceeds the threshold by an error margin -- similar to the error margin regarding the decimal sum of the weights of awarding or selection criteria.
(If the justification is forbidden below the threshold, that error margin should be applied in the other direction; so allow the justification even if the duration is just below the threshold).
All reactions
Hi,
decomposing the duration in years, months and days is not appropriate and does not reflect the performed operation which involves the xs:dayTimeDuration operand. The duration of months is also highly linked to the associated date.
Using the proposed dates I get the following results:
KR
All reactions
Thanks! In the future, we will only use "days" for the calculations.