Skip to content

Commit

Permalink
#21. The ability to use native Intl.RelativeTimeFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
purecatamphetamine committed Oct 9, 2020
1 parent 58a879d commit ba75815
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
3 changes: 0 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
<!--
TO DO: Add the ability to use the native `Intl.RelativeTimeFormat` and `Intl.PluralRules` and not import any locale data (except for maybe doing `TimeAgo.addLabels('en', 'now', require('javascript-time-ago/locale/en/now.json')`).
https://github.com/catamphetamine/javascript-time-ago/issues/21
TO DO: Change the export of the bundle: current — `new window['javascript-time-ago'].default()`, a more appropriate one — `new TimeAgo()`. Actually, would it even work in a browser? And will also including `relative-time-format` be required. Maybe add a "CDN" secition in the README (and a note in the "Install" section).
TO DO: Maybe create a "dummy" `time-ago-js` package that would simply re-export `javascript-time-ago`.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,12 @@ const object = cache.get('key1', 'key2', ...) || cache.put('key1', 'key2', ...,
This library uses an [`Intl.RelativeTimeFormat`](https://www.npmjs.com/package/relative-time-format) polyfill under the hood.
Some people have [requested](https://github.com/catamphetamine/javascript-time-ago/issues/21) the ability to use native [`Intl.RelativeTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat) and [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) instead of the polyfills: in this case, pass `polyfill: false` option when creating a `TimeAgo` instance.
```js
new TimeAgo('en-US', { polyfill: false })
```

## React

There is also a [React component](https://www.npmjs.com/package/react-time-ago) built upon this library, that autorefreshes itself.
Expand Down
37 changes: 26 additions & 11 deletions source/TimeAgo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import RelativeTimeFormat from 'relative-time-format'
import RelativeTimeFormatPolyfill from 'relative-time-format'

import Cache from './cache'
import chooseLocale from './locale'
Expand Down Expand Up @@ -32,8 +32,9 @@ const UNITS = [
export default class TimeAgo {
/**
* @param {(string|string[])} locales=[] - Preferred locales (or locale).
* @param {boolean} [polyfill] — Pass `false` to use native `Intl.RelativeTimeFormat` and `Intl.PluralRules` instead of the polyfills.
*/
constructor(locales = []) {
constructor(locales = [], { polyfill } = {}) {
// Convert `locales` to an array.
if (typeof locales === 'string') {
locales = [locales]
Expand All @@ -43,13 +44,27 @@ export default class TimeAgo {
// from the list of `locales` added by the user.
// For example, new TimeAgo("en-US") -> "en".
this.locale = chooseLocale(
locales.concat(RelativeTimeFormat.getDefaultLocale()),
locales.concat(TimeAgo.getDefaultLocale()),
getLocaleData
)

// Use `Intl.NumberFormat` for formatting numbers (when available).
if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
this.numberFormat = new Intl.NumberFormat(this.locale)
if (typeof Intl !== 'undefined') {
// Use `Intl.NumberFormat` for formatting numbers (when available).
if (Intl.NumberFormat) {
this.numberFormat = new Intl.NumberFormat(this.locale)
}
}

// Some people have requested the ability to use native
// `Intl.RelativeTimeFormat` and `Intl.PluralRules`
// instead of the polyfills.
// https://github.com/catamphetamine/javascript-time-ago/issues/21
if (polyfill === false) {
this.IntlRelativeTimeFormat = Intl.RelativeTimeFormat
this.IntlPluralRules = Intl.PluralRules
} else {
this.IntlRelativeTimeFormat = RelativeTimeFormatPolyfill
this.IntlPluralRules = RelativeTimeFormatPolyfill.PluralRules
}

// Cache `Intl.RelativeTimeFormat` instance.
Expand Down Expand Up @@ -332,7 +347,7 @@ export default class TimeAgo {
// `Intl.RelativeTimeFormat` instance creation is (hypothetically) assumed
// a lengthy operation so the instances are cached and reused.
return this.relativeTimeFormatCache.get(this.locale, labelsType) ||
this.relativeTimeFormatCache.put(this.locale, labelsType, new RelativeTimeFormat(this.locale, { style: labelsType }))
this.relativeTimeFormatCache.put(this.locale, labelsType, new this.IntlRelativeTimeFormat(this.locale, { style: labelsType }))
}

/**
Expand All @@ -343,7 +358,7 @@ export default class TimeAgo {
// `Intl.PluralRules` instance creation is (hypothetically) assumed
// a lengthy operation so the instances are cached and reused.
return this.pluralRulesCache.get(this.locale) ||
this.pluralRulesCache.put(this.locale, new RelativeTimeFormat.PluralRules(this.locale))
this.pluralRulesCache.put(this.locale, new this.IntlPluralRules(this.locale))
}


Expand Down Expand Up @@ -383,21 +398,21 @@ export default class TimeAgo {
* Gets default locale.
* @return {string} locale
*/
TimeAgo.getDefaultLocale = RelativeTimeFormat.getDefaultLocale
TimeAgo.getDefaultLocale = RelativeTimeFormatPolyfill.getDefaultLocale

/**
* Sets default locale.
* @param {string} locale
*/
TimeAgo.setDefaultLocale = RelativeTimeFormat.setDefaultLocale
TimeAgo.setDefaultLocale = RelativeTimeFormatPolyfill.setDefaultLocale

/**
* Adds locale data for a specific locale.
* @param {Object} localeData
*/
TimeAgo.addLocale = function(localeData) {
addLocaleData(localeData)
RelativeTimeFormat.addLocale(localeData)
RelativeTimeFormatPolyfill.addLocale(localeData)
}

/**
Expand Down
15 changes: 15 additions & 0 deletions source/TimeAgo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,21 @@ describe(`javascript-time-ago`, () => {
}]
}).should.equal('in 1 second')
})

it('should support `polyfill: false` option', () => {
const timeAgo = new TimeAgo('en', { polyfill: false })
// Still uses "now" labels, even when not polyfilled.
timeAgo.format(Date.now(), 'round').should.equal('just now')
timeAgo.format(Date.now() + 1000, 'round').should.equal('in 1 second')
})

it('should not use Intl.NumberFormat if it is not available', () => {
const Intl = global.Intl
global.Intl = undefined
const timeAgo = new TimeAgo('en')
timeAgo.format(Date.now() + 1000, 'round').should.equal('in 1 second')
global.Intl = Intl
})
})

export function approximateScaleStepsTest(labels, timeAgo, style = {}) {
Expand Down

0 comments on commit ba75815

Please sign in to comment.