Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ The `micro` format displays relative dates in a more compact format. Similar to

If the `threshold` attribute is explicitly set, `micro` will display compact relative dates within the threshold and absolute dates outside of it. If `threshold` is not set, `micro` will continue to display compact relative dates without applying the default threshold.

When `tense` is set to `past` or `future`, `micro` uses `Intl.RelativeTimeFormat` with `style: 'narrow'` to include localized tense phrasing such as `2w ago` or `in 3d`. With the default `tense=auto`, `micro` preserves the compact duration output such as `2w`.
Comment thread
liuliu-dev marked this conversation as resolved.

Code that uses `format=micro` should consider migrating to `format=relative` (perhaps with `formatStyle=narrow`), as `format=micro` can be difficult for users to understand, and can cause issues with assistive technologies. For example some screen readers (such as VoiceOver for mac) will read out `1m` as `1 meter`.

###### Cheatsheet
Expand All @@ -182,15 +184,15 @@ Code that uses `format=micro` should consider migrating to `format=relative` (pe

If `format` is `'datetime'` then this value will be ignored.

Tense can be used to prevent `duration` or `relative` formatted dates displaying dates in a tense other than the one specified. Setting `tense=past` will always display future `relative` dates as `now` and `duration` dates as `0 seconds`, while setting it to `future` will always display past dates `relative` as `now` and past `duration` dates as `0 seconds`.
Tense can be used to prevent `duration` or `relative` formatted dates displaying dates in a tense other than the one specified. Setting `tense=past` will always display future `relative` dates as `now` and `duration` dates as `0 seconds`, while setting it to `future` will always display past dates `relative` as `now` and past `duration` dates as `0 seconds`. For `format=micro`, `tense=past` and `tense=future` add localized compact tense phrasing.

For example when the given `datetime` is 40 seconds behind of the current date:

| `tense=` | format=duration | format=relative |
| :------: | :-------------: | :-------------: |
| future | 0s | now |
| past | 40s | 40s ago |
| auto | 40s | 40s ago |
| `tense=` | format=duration | format=relative | format=micro |
| :------: | :-------------: | :-------------: | :----------: |
| future | 0s | now | in 1m |
| past | 40s | 40s ago | 1m ago |
| auto | 40s | 40s ago | 1m |

```html
<relative-time datetime="2038-04-01T16:30:00-08:00" tense="past">
Expand Down
37 changes: 28 additions & 9 deletions src/relative-time-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,22 +236,37 @@ export class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFor
return 'datetime'
}

#getMicroDuration(duration: Duration): Duration {
duration = roundToSingleUnit(duration)
// Allow month-level durations to pass through even with mismatched tense
if (
duration.months === 0 &&
((this.tense === 'past' && duration.sign !== -1) || (this.tense === 'future' && duration.sign !== 1))
) {
Comment thread
liuliu-dev marked this conversation as resolved.
return microEmptyDuration
}
return duration
}

#getMicroRelativeFormat(duration: Duration): string {
const relativeFormat = new Intl.RelativeTimeFormat(this.#lang, {
numeric: 'always',
style: 'narrow',
})
duration = this.#getMicroDuration(duration)
const [int, unit] = getRelativeTimeUnit(duration.blank ? microEmptyDuration : duration)
return relativeFormat.format(Math.abs(int) * (this.tense === 'past' ? -1 : 1), unit)
}

#getDurationFormat(duration: Duration): string {
const locale = this.#lang
const format = this.format
const style = this.formatStyle
const tense = this.tense
let empty = emptyDuration
if (format === 'micro') {
duration = roundToSingleUnit(duration)
duration = this.#getMicroDuration(duration)
empty = microEmptyDuration
// Allow month-level durations to pass through even with mismatched tense
if (
duration.months === 0 &&
((this.tense === 'past' && duration.sign !== -1) || (this.tense === 'future' && duration.sign !== 1))
) {
duration = microEmptyDuration
}
} else if ((tense === 'past' && duration.sign !== -1) || (tense === 'future' && duration.sign !== 1)) {
duration = empty
}
Expand Down Expand Up @@ -624,7 +639,11 @@ export class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFor
newText = this.#getUserPreferredAbsoluteTimeFormat(date)
} else {
if (format === 'duration') {
newText = this.#getDurationFormat(duration)
if (this.format === 'micro' && this.tense !== 'auto' && Intl.RelativeTimeFormat) {
newText = this.#getMicroRelativeFormat(duration)
} else {
newText = this.#getDurationFormat(duration)
}
} else if (format === 'relative') {
newText = this.#getRelativeFormat(duration)
} else {
Expand Down
Loading
Loading