# Formatted Duration

[react-intl](https://github.com/yahoo/react-intl) is an amazing library providing React components and API to localize your application, however it lacks a `Duration` component.

If you want to show the time it takes to do something like `1 minute` or `5 minutes` or even a simple timer `0:30` you're [out of luck](https://github.com/yahoo/react-intl/issues/77) because the ECMA committee hasn't specified the [DurationFormat](https://github.com/tc39/ecma402/issues/47) yet.

This component provides a very simple abstraction that works on React (DOM), React Native and any other target environment to format simple durations.

## Usage

`npm i --save react-intl-formatted-duration`

### Extended format

```js
// Using React DOM
import React from 'react';
import FormattedDuration from 'react-intl-formatted-duration';

export default MyComponent() {
  return <FormattedDuration seconds={60} />
  // will render `1 minute`
}
```

The default format only shows minutes and seconds. For more complex needs check the [custom format section](#Custom_format).

By default the output text is wrapped in a `span`, you can specify any component you like available on your target environment:

```js
// Using React Native
import React from 'react';
import FormattedDuration from 'react-intl-formatted-duration';

import { Text } from 'react-native';

export default MyComponent() {
  return <FormattedDuration seconds={60} textComponent={Text} />
  // will render `1 minute`
}
```

```js
// Using styled components
import React from 'react';
import FormattedDuration from 'react-intl-formatted-duration';

import styled from 'styled-components';
const Text = styled.span``;

export default MyComponent() {
  return <FormattedDuration seconds={60} textComponent={Text} />
  // will render `1 minute`
}
```

#### Styling numbers

If you want to style numbers differently from text you can pass a `valueComponent`

```js
<FormattedDuration seconds={90} textComponent={Text} valueComponent={Value} />

// renders

<Value>1</Value> <Text>minute</Text> <Value>30</Value> <Text>seconds</Text>
```

Having different components is useful not only for styling. Some languages use different [numbering systems](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat). For example Japanese has full-width numbers, so you might want to render `１０分` instead of `10分`, to do so you can use:

```js
import React from 'react';
import { FormattedNumber } from 'react-intl';
import FormattedDuration from 'react-intl-formatted-duration';

/*
You'll also need to select Japanese locale and configure the IntlProvider to use
`ja-JP-u-nu-fullwide`

Somewhere in you application
import { IntlProvider } from 'react-intl';
<IntlProvider
   locale="ja-JP-u-nu-fullwide"
/>
 */

export default MyComponent() {
  return <FormattedDuration seconds={600} textComponent={Text} valueComponent={FormattedNumber} />
  // will render `１０分`
}
```

### Custom format

#### Hours and days

By default the component only renders minutes and seconds, if you want to display hours or days you can use a custom format:

```js
<FormattedDuration seconds={180000} format="{days} {hours} {minutes} {seconds}" />
// will render `2 days 2 hours`

<FormattedDuration seconds={180000} format="{hours} {minutes} {seconds}" />
// will render `50 hours`

<FormattedDuration seconds={180000} format="{minutes} {seconds}" />
// will render `3000 minutes`
}
```

Seconds is also optional and if missing, minutes will be rounded to the closed value

```js
<FormattedDuration seconds={10} format="{minutes}" />
// will render `0 minutes`

<FormattedDuration seconds={30} format="{minutes}" />
// will render `1 minute`

<FormattedDuration seconds={70} format="{minutes}" />
// will render `1 minute`
```

The custom format can itself be localized by passing a message id instead of the actual value

```js
import React from 'react';
import FormattedDuration from 'react-intl-formatted-duration';

import messages from './messages';

export default MyComponent() {
  return (
    <FormattedDuration
      seconds={600}
      format={messages.customFormat.id}
    />
  );
}
```

#### Unit display

While `format` allows to select which units to render, `unitDisplay` allows to configure the way each unit is rendered.

```js
<FormattedDuration seconds={60} unitDisplay="long" />
// will render `1 minute`

<FormattedDuration seconds={60} unitDisplay="short" />
// will render `1 min`

<FormattedDuration seconds={60} unitDisplay="narrow" />
// will render `1m`
```

#### Timer format

```js
import FormattedDuration, { TIMER_FORMAT } from 'react-intl-formatted-duration';

export default MyComponent() {
  return <FormattedDuration seconds={60} format={TIMER_FORMAT} />
  // will render `1:00`
}
```

## Localization

`react-intl-formatted-duration` expects the following keys inside your translation file

* `react-intl-formatted-duration.longFormatting` the default format that generates something like `1 minute 30 seconds`. It uses the values `{days}`, `{hours}`, `{minutes}` and `{seconds}`. For example you can change it to `{minutes} and {seconds}`.
* `react-intl-formatted-duration.duration` the format used by the `minutes` and `seconds` variables described above. It uses the values `{value}` and `{unit}`. The default is `{value} {unit}` where `value` is a number and `{unit}` is the textual unit like `minute(s)` or `second(s)`.
* `react-intl-formatted-duration.timerFormatting` format for `TIMER_FORMAT`, defaults to `{minutes}:{seconds}` where both values are numbers padded to have a minimum length of 2 characters
* `react-intl-formatted-duration.daysUnit` string for formatting days, default `{value, plural, one {day} other {days}}`
* `react-intl-formatted-duration.hoursUnit` string for formatting hours, default `{value, plural, one {hour} other {hours}}`
* `react-intl-formatted-duration.minutesUnit` string for formatting minutes, default `{value, plural, one {minute} other {minutes}}`
* `react-intl-formatted-duration.secondsUnit` string for formatting seconds, default `{value, plural, one {second} other {seconds}}`

The messages for `daysUnit`, `hoursUnit`, `minutesUnit`, `secondsUnit` use the [format-js syntax](https://formatjs.io/guides/message-syntax/) and are only used when `unitDisplay` is not specified.

If you're using the `extract-intl` script from [react-boilerplate](https://github.com/react-boilerplate/react-boilerplate) you can import `react-intl-formatted-duration/messages` to automatically generate the keys in your translation files.


## Upgrading from version 1.0

Version `2.x` allows to use the whole power of format-js message syntax. All you need to do is remove all keys like `daysSingular`, `dayPlural` and simply use `daysUnit` with the format described above.

## Upgrading from version 2.0

Version `3.x` has exactly the same API as version `2.x` but is a complete rewrite. You don't need to change your code.

## Upgrading from version 3.0

Version `4.x` doesn't change any of the default behavior of version `3.x` and only contains new features. However internally it bumps the version of `intl-unofficial-duration-unit-format` from `1.x` to `3.x` which now requires `Intl.NumberFormat` to be available globally. If you've installed `react-intl` correctly, chances are you don't need to change your code.
