tc39/proposal-intl-relative-time

Name: proposal-intl-relative-time

Owner: Ecma TC39

Description: `Intl.RelativeTimeFormat` specification [draft]

Created: 2015-09-20 00:08:02.0

Updated: 2018-05-20 23:44:06.0

Pushed: 2018-04-25 22:08:44.0

Homepage: http://tc39.github.io/proposal-intl-relative-time/

Size: 126

Language: HTML

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Intl.RelativeTimeFormat API Specification [draft]

Overview
Motivation

Due to common use, relative time?formatted values exist in a majority of websites and are available for the majority of frameworks (e.g., React, via react-intl and react-globalize; Ember, via ember-intl). Popular localization libraries like Moment.js, Format.js, Globalize, and others have implemented a formatting process for relative time values as well.

It is highly probable that the majority of current relative time formatting implementations require a large portion of CLDR raw or compiled data to format relative time values. Bringing this into the platform will improve performance of the web and developer productivity as they no longer have to bring extra weight to format relative time values.

Usage
reate a relative time formatter in your locale.
rtf = new Intl.RelativeTimeFormat("en", {
style: "long", // "long" (default), "short", or "narrow"


ormat relative time using the day unit.
format(
,
ay" // "year", "quarter", "month", "week", "day", "hour", "minute", or "second"

 "yesterday"
Implementation Status

Stage 3

Implementation Progress

Backpointers

Authors Reviewers

TBD

Proposal

Intl.RelativeTimeFormat is a low level API to facilitate libraries and frameworks to format relative time in a localized fashion by providing internationalized messages for date and time fields, using customary word or phrase when available.

Spec

You can view the spec text or rendered as HTML.

Technical Design

This proposal is based on the ICU Relative Date Time Formatter and on the Unicode CLDR Calendar Fields Relative values:

It is also based on the LDML spec, C.11 Language Plural Rules:

Prior Art Java Ruby
ude ActionView::Helpers::DateHelper
index
riendly_date = time_ago_in_words(Date.today - 1)

Naming

For consistency with Intl.NumberFormat and Intl.DateTimeFormat, we have chosen a similar form for this new feature. The creation of an Intl.RelativeTimeFormat instance is an expensive operation that requires resolution of locale data, and most likely, libraries will attempt to cache those instances, just like they do for Intl.NumberFormat and Intl.DateTimeFormat.

We have also chosen style as the primary form of switching between different formatting forms for consistency with Intl.NumberFormat and Intl.DateTimeFormat.

Since this new feature does format a provided value just like instances of Intl.NumberFormat, and Intl.DateTimeFormat, we have chosen the same form by providing a format(value) method of the instance, which returns a formatted string value.

Take number instead of date object for input

Relative time is used to display date distances, therefore the natural form of input should intuitively be a date object. Although, in this API we chose to take a number instead due to the following reasons:

  1. Basically, taking a number as input for the format method instead of a date object significantly simplifies the scope of this proposal while it still fully addresses the main objective which is to provide i18n building blocks to address this problem realm.
  2. Taking a date object means we should implement the comparison logic (relative time is about date distance between target and source dates). The source date is usually now, but not always. We would have to address modifying that. See #4.
  3. Taking a date object also means we should allow for different calendar calculations, which implies Date should support it. See #6 and #13.
  4. Taking a date object suggests we should be able to implement a bestFit algorithm, which has its own API challenges with respect to standardizing an approach that works for all cases. See #7, #14, and #15. We'd probably need to provide a flag for users to fill, with no default setting, to choose between options for calendar calculation.
Take number as input rather than exposing the underlying database

An idea has been floated, in the context of “the extensible web”, of just exposing the engine's copy of the CLDR database rather than a higher-level interface would be better. In the case of this specification, there is already a JS object model ready to go–the locale database is represented internally in the spec as a JavaScript object.

However, we opted not to go that route for a couple reasons:

Difference between this and UnitFormat

The fundamental difference between RelativeTimeFormat and UnitFormat is that RelativeTimeFormat displays a relative unit (e.g., 5 days ago or in 5 days) while UnitFormat displays an absolute unit (e.g., -5 meters or 5 meters). Note that RelativeTimeFormat uses different internationalized messages based on the value sign direction, while UnitFormat uses the same internationalized message for all values.

Countdowns, e.g., 15 days, 0 hours, 27 minutes, and 52 seconds

A countdown for example is a mix of UnitFormat and ListFormat, and is not a RelativeTimeFormat.

API
Intl.RelativeTimeFormat([locales[, options]])

The Intl.RelativeTimeFormat object is a constructor for objects that enable language-sensitive relative time formatting.

locales

Optional. A string with a BCP 47 language tag, or an array of such strings. For the general form and interpretation of the locales argument, see the Intl page.

options

Optional. An object with some or all of the following properties:

options.style

The length of the internationalized message. Possible values are: "long" (default, e.g., in 1 month); "short" (e.g., in 1 mo.), or "narrow" (e.g., in 1 mo.). The narrow style could be similar to the short style for some locales.

Example
reate a relative time formatter in your locale.
rtf = new Intl.RelativeTimeFormat("en", {style: "short"});
Intl.RelativeTimeFormat.prototype.format(value, unit)

The Intl.RelativeTimeFormat.prototype.format method formats a value and unit according to the locale and formatting options of this Intl.RelativeTimeFormat object.

While this method automatically provides the correct plural forms, the grammatical form is otherwise as neutral as possible. It is the caller's responsibility to handle cut-off logic such as deciding between displaying “in 7 days” or “in 1 week”. This API does not support relative dates involving compound units. e.g “in 5 days and 4 hours”.

value

Numeric value to use in the internationalized relative time message.

unit

Unit to use in the relative time internationalized message. Possible values are: "year", "quarter", "month", "week", "day", "hour", "minute", "second". Plural forms are also permitted.

Example
rtf = new Intl.RelativeTimeFormat("en");

ormat relative time using the day unit.
format(-1, "day");
 "yesterday"

format(2.15, "day");
 "in 2.15 days"

format(100, "day");
 "in 100 days"

format(0, "day");
 "today"

format(-0, "day");
 "today"

Additionally, by combining the class option style and unit, you can achieve any of the following results:

 year
 year
 year
 year
 years
ar ago
ars ago

 yr.
 yr.
 yr.
 yr.
 yr.
. ago
. ago
 quarter
 quarter
 quarter
 quarter
 quarters
arter ago
arters ago
 qtr.
 qtr.
 qtr.
 qtr.
 qtrs.
r. ago
rs. ago
 month
 month
 month
 month
 months
nth ago
nths ago
 mo.
 mo.
 mo.
 mo.
 mo.
. ago
. ago
 week
 week
 week
 week
 weeks
ek ago
eks ago
 wk.
 wk.
 wk.
 wk.
 wk.
. ago
. ago
 day
 days
y ago
ys ago
erday
y
rrow
 hour
 hours
ur ago
urs ago
 hr.
 hr.
. ago
. ago
 minute
 minutes
nute ago
nutes ago
 min.
 min.
n. ago
n. ago
 second
 seconds
cond ago
conds ago
 sec.
 sec.
c. ago
c. ago
Intl.RelativeTimeFormat.prototype.formatToParts(value, unit)

The Intl.RelativeTimeFormat.prototype.formatToParts method is a version of the format method which it returns an array of objects which represent “parts” of the object. These objects have two properties: type is the unit name or the string "literal", and value, which is the String which is the component of the output.

Example
rtf = new Intl.RelativeTimeFormat("en");

ormat relative time using the day unit.
formatToParts(-1, "day");
 [{ type: "literal", value: "yesterday"}]

formatToParts(100, "day");
 [{ type: "literal", value: "in "}, { type: "day", value: "100"}, { type: "literal", value: " days"}]
Development
Render Spec
install
run build
 index.html

This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.