← All functions

DURATION

Quirk found

Category: Financial · Last tested 2026-09-01

Real compatibility results for the DURATION function: executed in Excel for the web, Google Sheets and LibreOffice Calc, with desktop Excel behavior from Microsoft’s official documentation (we do not run desktop Excel — Excel for the web is a different application and is executed separately). Syntax and links to that documentation are below.

Support matrix

EngineDocumentedLive-testedVerdict
Excel (desktop)Yes No — documented only n/a
Excel for the web— Yes (recalc, 2026-09-01) Supported, behaves as documented
Google SheetsYes Yes (Drive import, 2026-08-31) Supported, behaves as documented
LibreOffice CalcYes Yes (25.8.7.3, 2026-08-31) Quirk found

LibreOffice version history

We executed the same test cases under each LibreOffice release to show exactly when DURATION’s support changed — not documentation claims, real results.

LibreOffice versionVerdictTested
24.2.0.3 Quirk found 2026-08-31
24.8.7.2 Quirk found 2026-08-31
25.2.0.3 Quirk found 2026-08-31
25.8.7.3 Quirk found 2026-08-31

Why isn't DURATION working in LibreOffice?

DURATION exists in LibreOffice 25.8.7.3, but it is not a drop-in match for Excel — our executed tests found real behavioral differences (detailed in the test results on this page). If a formula that works in Excel or Google Sheets misbehaves in LibreOffice, compare your usage against the failing cases above before assuming your data is wrong.

Discovered quirks

Executed test cases

Excel for the web (executed 2026-09-01 via OneDrive recalculation)

These values come from Excel for the web, not from desktop Excel. They are two different implementations of the calculation engine, and this run measured only the web one: the corpus was uploaded to OneDrive as .xlsx, recalculated by Excel for the web on open, and downloaded again for readback. Excel for the web is a rolling service with no pinnable version, so the run is identified by its date. Where a value here disagrees with the Expected column — which is Microsoft’s documentation of the desktop product — we cannot tell you whether the web engine diverges from the desktop one or the documentation is wrong about both, because we do not run desktop Excel.

FormulaDescriptionResultExpectedVerdict
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,1),7) Microsoft's documented worked example: a 30-year 8% bond yielding 9%, semiannual, actual/actual basis 10.9191453 10.9191453
Provenance

Microsoft's page publishes this example's result as 10.9191453. Derived independently from the documented definition, "the Macauley duration for an assumed par value of $100 ... the weighted average of the present value of cash flows". Settlement 2018-07-01 falls exactly on a coupon date of the 2048-01-01 maturity at semiannual frequency, so there are 59 remaining coupons at times 0.5, 1.0, ... 29.5 years; discounting each 4.00 coupon (plus 100 redemption at t = 29.5) at 9% nominal semiannual and taking the cash-flow-weighted mean time gives 10.919145281591925, which rounds to the published 10.9191453 at 7 dp. EXECUTED RESULT -- SILENT WRONG VALUE, the most serious class in this batch. All four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return 10.9215739665694 where both Microsoft's published figure and the independent derivation give 10.919145281591925: a plausible number, no error, wrong in the third decimal (2.2e-4 relative). The mechanism is pinned down exactly rather than guessed. The discrepancy is 10.9215739665694 - 10.9191452815919 = 0.0024286849775, and YEARFRAC over the same two dates on the same basis 1 returns 29.5024286849775 where the coupon schedule gives 59 coupons / 2 per year = 29.5 exactly -- the excess, 0.0024286849775, matches the error to twelve digits. LibreOffice is therefore taking the cash-flow times from an actual/actual year fraction instead of from the coupon count, which shifts EVERY cash flow later by the same amount and so shifts the weighted average by that amount. The companion case DURATION_basis_30_360 is the control: on basis 0, where YEARFRAC over these dates is exactly 29.5, all four builds return 10.9191452815919 and agree with the documented value.

Matched
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,0),7) The same bond on the US 30/360 basis instead of actual/actual 10.9191453 10.9191453
Provenance

Derived, not published: this case exists as a controlled comparison against DURATION_doc_example. Because settlement lands exactly on a coupon date, the cash-flow schedule is identical under every basis, so the Macaulay duration is the same 10.919145281591925 whichever basis is chosen -- and the two cases together therefore isolate whether an engine's basis handling leaks into the duration. Note that YEARFRAC over the same two dates is exactly 29.5 on basis 0 but 29.50242868497748 on basis 1, which is the quantity that separates the two cases on an engine that derives the schedule from a year fraction. EXECUTED RESULT: all four LibreOffice builds return 10.9191452815919, matching the derivation exactly -- while the otherwise identical actual/actual case (DURATION_doc_example) does not. The pair isolates the defect to LibreOffice's basis-1 year fraction; see that case's note for the arithmetic.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,3,1) A coupon frequency of 3, which is not one of the documented values #NUM! #NUM!
Provenance

Excel documents: "If frequency is any number other than 1, 2, or 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),-0.08,0.09,2,1) A negative coupon rate, which the documentation excludes #NUM! #NUM!
Provenance

Excel documents: "If coupon < 0 or if yld < 0, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2048,1,1),DATE(2018,7,1),0.08,0.09,2,1) Settlement later than maturity, which the documentation excludes #NUM! #NUM!
Provenance

Excel documents: "If settlement >= maturity, DURATION returns the #NUM! error value." The example's two dates are simply swapped. EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,5) A day-count basis above the documented range #NUM! #NUM!
Provenance

Excel documents five bases (0-4) and: "If basis < 0 or if basis > 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched

Google Sheets (executed 2026-08-31 via Drive import)

Google Sheets is a rolling service with no pinnable version, so this run is identified by its date. The corpus was imported to Drive as .xlsx, recalculated by Sheets, and exported back for readback.

FormulaDescriptionResultExpectedVerdict
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,1),7) Microsoft's documented worked example: a 30-year 8% bond yielding 9%, semiannual, actual/actual basis 10.9191453 10.9191453
Provenance

Microsoft's page publishes this example's result as 10.9191453. Derived independently from the documented definition, "the Macauley duration for an assumed par value of $100 ... the weighted average of the present value of cash flows". Settlement 2018-07-01 falls exactly on a coupon date of the 2048-01-01 maturity at semiannual frequency, so there are 59 remaining coupons at times 0.5, 1.0, ... 29.5 years; discounting each 4.00 coupon (plus 100 redemption at t = 29.5) at 9% nominal semiannual and taking the cash-flow-weighted mean time gives 10.919145281591925, which rounds to the published 10.9191453 at 7 dp. EXECUTED RESULT -- SILENT WRONG VALUE, the most serious class in this batch. All four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return 10.9215739665694 where both Microsoft's published figure and the independent derivation give 10.919145281591925: a plausible number, no error, wrong in the third decimal (2.2e-4 relative). The mechanism is pinned down exactly rather than guessed. The discrepancy is 10.9215739665694 - 10.9191452815919 = 0.0024286849775, and YEARFRAC over the same two dates on the same basis 1 returns 29.5024286849775 where the coupon schedule gives 59 coupons / 2 per year = 29.5 exactly -- the excess, 0.0024286849775, matches the error to twelve digits. LibreOffice is therefore taking the cash-flow times from an actual/actual year fraction instead of from the coupon count, which shifts EVERY cash flow later by the same amount and so shifts the weighted average by that amount. The companion case DURATION_basis_30_360 is the control: on basis 0, where YEARFRAC over these dates is exactly 29.5, all four builds return 10.9191452815919 and agree with the documented value.

Matched
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,0),7) The same bond on the US 30/360 basis instead of actual/actual 10.9191453 10.9191453
Provenance

Derived, not published: this case exists as a controlled comparison against DURATION_doc_example. Because settlement lands exactly on a coupon date, the cash-flow schedule is identical under every basis, so the Macaulay duration is the same 10.919145281591925 whichever basis is chosen -- and the two cases together therefore isolate whether an engine's basis handling leaks into the duration. Note that YEARFRAC over the same two dates is exactly 29.5 on basis 0 but 29.50242868497748 on basis 1, which is the quantity that separates the two cases on an engine that derives the schedule from a year fraction. EXECUTED RESULT: all four LibreOffice builds return 10.9191452815919, matching the derivation exactly -- while the otherwise identical actual/actual case (DURATION_doc_example) does not. The pair isolates the defect to LibreOffice's basis-1 year fraction; see that case's note for the arithmetic.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,3,1) A coupon frequency of 3, which is not one of the documented values #NUM! #NUM!
Provenance

Excel documents: "If frequency is any number other than 1, 2, or 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),-0.08,0.09,2,1) A negative coupon rate, which the documentation excludes #NUM! #NUM!
Provenance

Excel documents: "If coupon < 0 or if yld < 0, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2048,1,1),DATE(2018,7,1),0.08,0.09,2,1) Settlement later than maturity, which the documentation excludes #NUM! #NUM!
Provenance

Excel documents: "If settlement >= maturity, DURATION returns the #NUM! error value." The example's two dates are simply swapped. EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,5) A day-count basis above the documented range #NUM! #NUM!
Provenance

Excel documents five bases (0-4) and: "If basis < 0 or if basis > 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Matched

LibreOffice Calc 25.8.7.3 (tested 2026-08-31)

FormulaDescriptionResultExpectedVerdict
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,1),7) Microsoft's documented worked example: a 30-year 8% bond yielding 9%, semiannual, actual/actual basis 10.921574 10.9191453
Provenance

Microsoft's page publishes this example's result as 10.9191453. Derived independently from the documented definition, "the Macauley duration for an assumed par value of $100 ... the weighted average of the present value of cash flows". Settlement 2018-07-01 falls exactly on a coupon date of the 2048-01-01 maturity at semiannual frequency, so there are 59 remaining coupons at times 0.5, 1.0, ... 29.5 years; discounting each 4.00 coupon (plus 100 redemption at t = 29.5) at 9% nominal semiannual and taking the cash-flow-weighted mean time gives 10.919145281591925, which rounds to the published 10.9191453 at 7 dp. EXECUTED RESULT -- SILENT WRONG VALUE, the most serious class in this batch. All four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return 10.9215739665694 where both Microsoft's published figure and the independent derivation give 10.919145281591925: a plausible number, no error, wrong in the third decimal (2.2e-4 relative). The mechanism is pinned down exactly rather than guessed. The discrepancy is 10.9215739665694 - 10.9191452815919 = 0.0024286849775, and YEARFRAC over the same two dates on the same basis 1 returns 29.5024286849775 where the coupon schedule gives 59 coupons / 2 per year = 29.5 exactly -- the excess, 0.0024286849775, matches the error to twelve digits. LibreOffice is therefore taking the cash-flow times from an actual/actual year fraction instead of from the coupon count, which shifts EVERY cash flow later by the same amount and so shifts the weighted average by that amount. The companion case DURATION_basis_30_360 is the control: on basis 0, where YEARFRAC over these dates is exactly 29.5, all four builds return 10.9191452815919 and agree with the documented value.

Mismatch
=ROUND(DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,0),7) The same bond on the US 30/360 basis instead of actual/actual 10.9191453 10.9191453
Provenance

Derived, not published: this case exists as a controlled comparison against DURATION_doc_example. Because settlement lands exactly on a coupon date, the cash-flow schedule is identical under every basis, so the Macaulay duration is the same 10.919145281591925 whichever basis is chosen -- and the two cases together therefore isolate whether an engine's basis handling leaks into the duration. Note that YEARFRAC over the same two dates is exactly 29.5 on basis 0 but 29.50242868497748 on basis 1, which is the quantity that separates the two cases on an engine that derives the schedule from a year fraction. EXECUTED RESULT: all four LibreOffice builds return 10.9191452815919, matching the derivation exactly -- while the otherwise identical actual/actual case (DURATION_doc_example) does not. The pair isolates the defect to LibreOffice's basis-1 year fraction; see that case's note for the arithmetic.

Matched
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,3,1) A coupon frequency of 3, which is not one of the documented values #VALUE! #NUM!
Provenance

Excel documents: "If frequency is any number other than 1, 2, or 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Mismatch
=DURATION(DATE(2018,7,1),DATE(2048,1,1),-0.08,0.09,2,1) A negative coupon rate, which the documentation excludes #VALUE! #NUM!
Provenance

Excel documents: "If coupon < 0 or if yld < 0, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Mismatch
=DURATION(DATE(2048,1,1),DATE(2018,7,1),0.08,0.09,2,1) Settlement later than maturity, which the documentation excludes #VALUE! #NUM!
Provenance

Excel documents: "If settlement >= maturity, DURATION returns the #NUM! error value." The example's two dates are simply swapped. EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Mismatch
=DURATION(DATE(2018,7,1),DATE(2048,1,1),0.08,0.09,2,5) A day-count basis above the documented range #VALUE! #NUM!
Provenance

Excel documents five bases (0-4) and: "If basis < 0 or if basis > 4, DURATION returns the #NUM! error value." EXECUTED RESULT: all four LibreOffice builds (24.2.0.3, 24.8.7.2, 25.2.0.3, 25.8.7.3) return #VALUE! here instead of the documented #NUM! -- the same systemic #VALUE!-substitution pattern already recorded across this corpus, an error-code difference rather than a computation one.

Mismatch

Docs & syntax

Where DURATION behaves differently