# Narrowing a years and months duration

[Narrowing](../narrowing.md) › years and months duration. The names in the examples are those of [section 2](../narrowing.md#2-the-names-in-the-examples).

A `years and months duration` alternative is the bare kind or `{:years_and_months_duration, set}`: a `Feel.Type.NumberSet` of the **image** of the values, their number of **months** (`Feel.Type.Image`, D-109). The image is one-to-one and keeps the order, so a comparison is read as a number's is. A years and months duration is a different kind from a days and time duration: they are never compared, and there is no `duration` that holds both.

## Comparisons

| Condition | `ym` when true | `ym` when not true |
| --- | --- | --- |
| `ym < @"P1Y"` | `years and months duration in [-max..P1Y)` | `years and months duration in [P1Y..max] \| Null` |
| `ym > @"P0M"` | `years and months duration in (P0M..max]` | `years and months duration in [-max..P0M] \| Null` |
| `ym = @"P6M"` | `years and months duration = P6M` | `years and months duration in [-max..P6M), (P6M..max] \| Null` |
| `ym < dd` | — | `years and months duration \| Null` |
| `ym = dd` | `Null` | `years and months duration \| Null` |
| `ym instance of years and months duration` | `years and months duration` | `Null` |
| `ym instance of days and time duration` | — | `years and months duration \| Null` |

`ym < dd` compares kinds with no order between them, so it is never true; `ym = dd` is true only when both are `null`. The `null` rules are those of every kind ([the rule](../narrowing.md#4-then-else-and-null)).

## Properties

`years` and `months` (Table 67) are worked out from the **magnitude** of the amount, `m` months, and take its sign: `years` is `m div 12` and `months` is `m rem 12`. `value` is the amount itself. A fact about a property is a fact about the duration: the amounts whose property is what the fact leaves (D-194).

The years leave one interval, in a row; the months come back every year and leave **a piece for each**. So a fact about `years` or `value` is exact, and one about `months` narrows only a bounded set:

| Condition | `ym` when true | `ym` when not true |
| --- | --- | --- |
| `ym.years >= 2` | `years and months duration in [P2Y..max]` | `years and months duration in [-max..P1Y11M] \| Null` |
| `ym.years = 0` | `years and months duration in [-P11M..P11M]` | `years and months duration in [-max..-P1Y], [P1Y..max] \| Null` |
| `ym.years < 0` | `years and months duration in [-max..-P1Y]` | `years and months duration in [-P11M..max] \| Null` |
| `ym.value > 12` | `years and months duration in (P1Y..max]` | `years and months duration in [-max..P1Y] \| Null` |
| `ym.months = 3` | `years and months duration` | `years and months duration \| Null` |
| `ym.years = 1 and ym.months = 6` | `years and months duration = P1Y6M` | `years and months duration \| Null` |

`ym.years = 0` is symmetric because the sign is put back: eleven months either way. `ym.months = 3` on an unbounded value would need a piece for every year.

With allowed values the set is bounded, and the months have pieces to keep (`yms` is in `[P0M..P5Y]`):

| Condition | `yms` when true | `yms` when not true |
| --- | --- | --- |
| `yms > @"P1Y"` | `years and months duration in (P1Y..P5Y]` | `years and months duration in [P0M..P1Y] \| Null` |
| `yms.years >= 2` | `years and months duration in [P2Y..P5Y]` | `years and months duration in [P0M..P1Y11M] \| Null` |
| `yms.value >= 24` | `years and months duration in [P2Y..P5Y]` | `years and months duration in [P0M..P2Y) \| Null` |
| `yms.months = 3` | `years and months duration in P3M, P1Y3M, P2Y3M, P3Y3M, P4Y3M` | `years and months duration in [P0M..P2M], [P4M..P1Y2M], [P1Y4M..P2Y2M], [P2Y4M..P3Y2M], [P3Y4M..P4Y2M], [P4Y4M..P5Y] \| Null` |
| `yms.years = 1 and yms.months = 6` | `years and months duration = P1Y6M` | `years and months duration in [P0M..P5Y] \| Null` |

`yms.months = 3` is five single months, one in each year of the set. The `else` of a conjunction is the whole set, since only one side's facts are certain there ([and and or](../narrowing.md#5-and-and-or)).

## Arithmetic in a comparison

Two years and months durations add and subtract exactly, and the months do not overflow, so a sum or a difference in a comparison narrows the operand by the preimage of the images, as for numbers ([number](number.md#operations-in-the-comparison)). A years and months duration multiplied or divided by a number is **rounded** (D-54), so its months are not a product of images: `Feel.Analysis.MonthScaling` (D-109) works out the set as the run rounds it.

| Condition | `ym` when true | `ym` when not true |
| --- | --- | --- |
| `ym + @"P1M" > @"P1Y"` | `years and months duration in [P1Y..max]` | `years and months duration in [-max..P11M] \| Null` |
| `ym - @"P1M" <= @"P2Y"` | `years and months duration in [-max..P2Y1M]` | `years and months duration in [P2Y2M..max] \| Null` |
| `@"P5Y" - ym < @"P1Y"` | `years and months duration in [P4Y1M..max]` | `years and months duration in [-max..P4Y] \| Null` |
| `-ym > @"P1Y"` | `years and months duration in [-max..-P1Y)` | `years and months duration in [-P1Y..max] \| Null` |

As everywhere, the `else` branch of an operation is read where the operation cannot be `null` for the operand.

## One value read twice

Full analysis recognizes repeated reads of a name or supported member (D-170, D-207). Subtraction gives zero months. Self-division gives one when the month count is nonzero and its magnitude is less than `10^34`; zero and larger magnitudes give null, the latter because runtime numeric conversion fails. Null input also gives null. These failures are still possible even for a non-null duration.

| Expression | Type | Warnings |
| --- | --- | --- |
| `ym - ym` | `years and months duration = P0M \| Null` | — |
| `ym / ym` | `number = 1 \| Null` | — |
| `yms / yms` | `number = 1 \| Null` | — |

The core analysis tier keeps independent-operand types for repeated reads.

## Limits

- A set of more than **16 pieces** is replaced by the one interval that holds them (`months` of a range of 12 months or more has every value of a remainder).
- A bound of more than 34 digits is the end of the range of numbers.
- A multiplication or division by a number gives sets with large ends, because the amounts are as large as a number goes.
- Repeated addition still sums independent intervals. If a duration is either one or six months, `ym + ym` has a type containing seven months, although only two or twelve months can be returned.

See also: [days and time duration](days-and-time-duration.md), [date](date.md), [number](number.md).
