-
Notifications
You must be signed in to change notification settings - Fork 187
Use today for today, and omit current year #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -217,15 +217,57 @@ export class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFor | |
| return `${this.prefix} ${formatter.format(date)}`.trim() | ||
| } | ||
|
|
||
| #getUserPreferredAbsoluteTimeFormat(date: Date): string { | ||
| return new Intl.DateTimeFormat(this.#lang, { | ||
| day: 'numeric', | ||
| month: 'short', | ||
| #isToday(date: Date): boolean { | ||
| const now = new Date() | ||
| const formatter = new Intl.DateTimeFormat(this.#lang, { | ||
| timeZone: this.timeZone, | ||
| year: 'numeric', | ||
| month: '2-digit', | ||
| day: '2-digit', | ||
| }) | ||
| return formatter.format(now) === formatter.format(date) | ||
| } | ||
|
|
||
| #isCurrentYear(date: Date): boolean { | ||
| const now = new Date() | ||
| const formatter = new Intl.DateTimeFormat(this.#lang, { | ||
| timeZone: this.timeZone, | ||
| year: 'numeric', | ||
| }) | ||
| return formatter.format(now) === formatter.format(date) | ||
| } | ||
|
|
||
| // If current day, shows "Today" + time. | ||
| // If current year, shows date without year. | ||
| // In all other scenarios, show full date. | ||
| #getUserPreferredAbsoluteTimeFormat(date: Date): string { | ||
| const timeOnlyOptions: Intl.DateTimeFormatOptions = { | ||
| hour: 'numeric', | ||
| minute: '2-digit', | ||
| timeZoneName: 'short', | ||
| timeZone: this.timeZone, | ||
| } | ||
|
|
||
| if (this.#isToday(date)) { | ||
| const relativeFormatter = new Intl.RelativeTimeFormat(this.#lang, {numeric: 'auto'}) | ||
| let todayText = relativeFormatter.format(0, 'day') | ||
| todayText = todayText.charAt(0).toLocaleUpperCase(this.#lang) + todayText.slice(1) | ||
| const timeOnly = new Intl.DateTimeFormat(this.#lang, timeOnlyOptions).format(date) | ||
|
|
||
| return `${todayText} ${timeOnly}` | ||
| } | ||
|
|
||
| const timeAndDateOptions: Intl.DateTimeFormatOptions = { | ||
| ...timeOnlyOptions, | ||
| day: 'numeric', | ||
| month: 'short', | ||
| } | ||
| if (this.#isCurrentYear(date)) { | ||
| return new Intl.DateTimeFormat(this.#lang, timeAndDateOptions).format(date) | ||
| } | ||
| return new Intl.DateTimeFormat(this.#lang, { | ||
| ...timeAndDateOptions, | ||
| year: 'numeric', | ||
| }).format(date) | ||
| } | ||
|
|
||
|
|
@@ -525,7 +567,11 @@ export class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFor | |
| this.dispatchEvent(new RelativeTimeUpdatedEvent(oldText, newText, oldTitle, newTitle)) | ||
| } | ||
|
|
||
| if ((format === 'relative' || format === 'duration') && !displayUserPreferredAbsoluteTime) { | ||
| const shouldObserve = | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for breaking out that long conditional, this is much more readable to me |
||
| format === 'relative' || | ||
| format === 'duration' || | ||
| (displayUserPreferredAbsoluteTime && (this.#isToday(date) || this.#isCurrentYear(date))) | ||
| if (shouldObserve) { | ||
| dateObserver.observe(this) | ||
| } else { | ||
| dateObserver.unobserve(this) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1886,6 +1886,10 @@ suite('relative-time', function () { | |
| }) | ||
|
|
||
| suite('experimental: [data-prefers-absolute-time]', async () => { | ||
| teardown(() => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had initially wondered if we'd need a test for the boundary condition of moving from |
||
| document.documentElement.removeAttribute('data-prefers-absolute-time') | ||
| document.body.removeAttribute('data-prefers-absolute-time') | ||
| }) | ||
| test('formats with absolute time when data-prefers-absolute-time="true"', async () => { | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
|
|
@@ -1930,6 +1934,171 @@ suite('relative-time', function () { | |
|
|
||
| assert.match(el.shadowRoot.textContent, /[A-Z][a-z]{2} \d{1,2}, \d{4}, \d{1,2}:\d{2} (AM|PM)/) | ||
| }) | ||
|
|
||
| test('formats today dates with "Today" text', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
|
|
||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'America/New_York') | ||
|
|
||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Today 12:00 PM EST') | ||
| }) | ||
|
|
||
| test('formats current year dates without year', async () => { | ||
| freezeTime(new Date('2023-06-15T12:00:00.000Z')) | ||
|
|
||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'America/New_York') | ||
| el.setAttribute('datetime', '2023-03-10T18:00:00.000Z') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Mar 10, 1:00 PM EST') | ||
| }) | ||
|
|
||
| test('formats different year dates as full date', async () => { | ||
| freezeTime(new Date('2023-06-15T12:00:00.000Z')) | ||
|
|
||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'America/New_York') | ||
| el.setAttribute('datetime', '2022-03-10T18:00:00.000Z') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Mar 10, 2022, 1:00 PM EST') | ||
| }) | ||
|
|
||
| test('respects locale formatting', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
|
|
||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'es-ES') | ||
| el.setAttribute('time-zone', 'Europe/Madrid') | ||
|
|
||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| await Promise.resolve() | ||
|
|
||
| // Spanish formatting - "hoy" = "today", 24-hour format | ||
| assert.equal(el.shadowRoot.textContent, 'Hoy 18:00 CET') | ||
| }) | ||
|
Comment on lines
+1978
to
+1991
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the future! l10n! |
||
|
|
||
| test('uses element time-zone attribute', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
|
|
||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'Europe/Paris') | ||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Today 6:00 PM GMT+1') | ||
| }) | ||
|
|
||
| suite('format exclusions', function () { | ||
| test('does not activate for format="duration"', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('datetime', '2023-01-15T16:00:00.000Z') | ||
| el.setAttribute('format', 'duration') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, '1 hour') | ||
| }) | ||
|
|
||
| test('does not activate for format="elapsed"', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('datetime', '2023-01-15T16:00:00.000Z') | ||
| el.setAttribute('format', 'elapsed') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, '1h') | ||
| }) | ||
|
|
||
| test('does not activate for format="micro"', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('datetime', '2023-01-15T16:00:00.000Z') | ||
| el.setAttribute('format', 'micro') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, '1h') | ||
| }) | ||
|
|
||
| test('activates for format="relative" (default)', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'GMT') | ||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| el.setAttribute('format', 'relative') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Today 5:00 PM UTC') | ||
| }) | ||
|
|
||
| test('activates for format="auto"', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'UTC') | ||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| el.setAttribute('format', 'auto') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Today 5:00 PM UTC') | ||
| }) | ||
|
|
||
| test('activates for format="datetime" if current day', async () => { | ||
| freezeTime(new Date('2023-01-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'America/New_York') | ||
| el.setAttribute('datetime', '2023-01-15T17:00:00.000Z') | ||
| el.setAttribute('format', 'datetime') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Today 12:00 PM EST') | ||
| }) | ||
|
|
||
| test('activates for format="datetime" if current year but not today', async () => { | ||
| freezeTime(new Date('2023-06-15T17:00:00.000Z')) | ||
| document.documentElement.setAttribute('data-prefers-absolute-time', 'true') | ||
|
|
||
| const el = document.createElement('relative-time') | ||
| el.setAttribute('lang', 'en-US') | ||
| el.setAttribute('time-zone', 'America/New_York') | ||
| el.setAttribute('datetime', '2023-03-10T18:00:00.000Z') // 18:00 UTC = 1:00 PM EST | ||
| el.setAttribute('format', 'datetime') | ||
| await Promise.resolve() | ||
|
|
||
| assert.equal(el.shadowRoot.textContent, 'Mar 10, 1:00 PM EST') | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
| suite('[aria-hidden]', async () => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, having this be sensitive to user's TZ will save us many-a bug report!