# Showing Relative Time using JS Intl. API

### Basic understanding of Date object

According to MDN :

> A JavaScript date is fundamentally specified as the time in milliseconds that has elapsed since the [epoch](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range), which is defined as the midnight at the beginning of January 1, 1970, UTC (equivalent to the [UNIX epoch](https://developer.mozilla.org/en-US/docs/Glossary/Unix_time)). This timestamp is *timezone-agnostic* and uniquely defines an instant in history.

We know that we can get the current time using `Date.now()`. Which will return us the *number of* ***milliseconds*** *elapsed since midnight at the beginning of January 1, 1970, UTC.*

Usually, the date time is stored in the database in the UNIX timestamp.

> *UNIX timestamp is the number of* ***seconds*** *passed from January 1, 1970.*

### Converting timestamp to time passed (day, minutes and seconds)

Let's take an example where we have a Facebook post and we need to show the relative time string in it. If the post was made on 17-05-2023 and today is 19-05-2023. It should show `2 days ago` on the post. And yesterday if it was posted on the 18th.

First, we will calculate the time between the time of the post and the current time.

We get the UNIX timestamp of the post from the server and we can get the current time from `Date.now()`.

We will convert the UNIX timestamp (which is in seconds ) to milliseconds. `Date.now()` returns us the time in milliseconds.

we can calculate the time passed in milliseconds from the time of the post with -

```javascript
let currentTimestamp = Date.now();
let postTimestamp = getPostDateFromServer()*1000 //GET Post time from server

let timePassedInMilliseconds = currentTimestamp - postTimestamp
```

Now we have the `timePassedInMilliseconds`, We can use it to calculate if the post was made how many days, minutes or seconds ago. We will show X days ago, if days are more than 0 else we will show him X hours ago and so on.

We can show the user years and months as well but we are going till days only. If days are more than 30. We show 31 days ago and not 1 month ago.

Let's first calculate how many milliseconds are there in one (day, hour, minute and second)

```javascript
let millsecInOneSec=1000;
let millsecInOneMinute=60*millsecInOneSec;
let millsecInOneHour=60*millsecInOneMinute;
let millsecInOneDay=24*millsecInOneHour;
```

Now we take `timePassedInMilliseconds` from the time of post and calculate days, hours and minutes passed.

We can calculate the unitsOfTimePassed by timeframe / millsecInTimeframe, then we can `Math.floor` unitsOfTimePassed to show only the unit and not its fractional part.

```javascript
let unitsOfTimePassed; 
let timePassedString;
let daysPassed = timePassedInMilliseconds/millsecInOneDay;
let hoursPassed = timePassedInMilliseconds/millisecInOneHour;
let minPassed = timePassedInMilliseconds/millisecInOneMin;
let secPassed = timePassedInMilliseconds/millisecInOneSec;

let unitTypes=['day','hour','minute','second']
let displayUnitType;

if(daysPassed>1){
unitsOfTimePassed = Math.floor(daysPassed) 
displayUnitType=unitTypes[0]
//Math.floor() so that it does not show 1.x days ago , we want non-decimal value for time passed
}
else if(hoursPassed>1){
unitsOfTimePassed = Math.floor(hoursPassed) 
displayUnitType=unitTypes[1]
}
else if(minPassed>1){
unitsOfTimePassed = Math.floor(minPassed) 
displayUnitType=unitTypes[2]
}
else{
unitsOfTimePassed = Math.floor(secPassed) 
displayUnitType=unitTypes[3]
}
```

Now that we have `unitsOfTimePassed`, we can make our Relative Time String. For this, we will use Intl API. Specifically [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat).

### What is Intl API ??

Let's know what Intl (internationalization) is,

According to MDN it

> The `Intl` namespace object contains several constructors as well as functions common to the internationalization constructors and other language-sensitive functions. Collectively, they comprise the ECMAScript Internationalization API, which provides language-sensitive string comparison, number formatting, date and time formatting, and more.

In simple words, it provides proper strings for units like (date, time, number, and quantity) which are compatible with different languages and writing styles in various regions.

Eg :

We can have a news website where we show dates of news in different regions in different languages for that we can use [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).

```javascript
const date =Date.now();
const options={
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric",
}
console.log(new Intl.DateTimeFormat('en-US',options).format(date));
// "Friday, May 19, 2023"

console.log(new Intl.DateTimeFormat('hi',options).format(date))
//"शुक्रवार, 19 मई 2023"
```

Notice in the first log we have used `locale` as `'en-US'`, so it uses a US-style date. While in the second log, we have `'hi'` which is Hindi. Which makes the date in Indian Hindi format. In the Date, the day (19) comes first and then the month because that's the style that Hindi follows, while in `'en-US'` month (May) comes first.

There are many other ways we can use intl api like `Intl.Collator, Intl.ListFormat, Intl.NumberFormat, Intl.PluralRules` etc.

### Using Intl API to covert the time passed into Relative Time

We will be using `Intl.RelativeTimeFormat` to get the relative time string for the time passed since we made the post.

We already know `unitsOfTimePassed` and `displayUnitType` so we can get the string by :

```javascript
const locales='en'
const options={
  numeric: "auto", // other values: "auto"
  style: "long", // other values: "short" or "narrow"
}
const rtf = new Intl.RelativeTimeFormat(locales,options);
```

We configure the **Intl.RelativeTimeFormat** [`options`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat) and `locales` according to our needs.

```javascript
const displayString = rtf.format(-1 * unitsOfTimePassed,displayUnitType  ); // "n units of times ago
```

We put -1 to tell the `rtf` that the time has passed. To show an upcoming date we can give +1.

Now we can use the display string in the post to show the user the relative time from when the post was posted.

---

IF YOU LIKED THE POST DO SHARE IT 😄.
