Como implementar un TimeAgo de una fecha
Tags: javascript, programming
Published: 2021-01-30 23:48:32

Al mostrar una fecha pasada solemos ver los meses, días o año en el siguiente formato **mes/día/año hora:minuto:segundo** es una manera correcta, sin embargo a veces sería mejor mostrar de una forma más entendible en un formato amigable como:
* Hace 3 minutos
* Hace 5 horas
* Hace 6 meses

Al observar páginas o aplicaciones de redes sociales es común observar esta forma de implementación.

## 😄 Ahora, Cómo lo implementamos?

Existe una API de javascript llamada Intl con el que podemos dar formato a fechas, horas, números y más de manera internacional para poder usarla en distintos idiomas. Puedes ver mas información de la [API Intl en esta documentación.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) es bastante interesante.
Lo que usaremos en esta oportunidad es el constructor **RelativeTimeFormat** del objeto **Intl** para darle formato relativo al tiempo.

## 🧭 Comenzando a usar el objeto RelativeTimeFormat

#### 1. Instanciar el objeto de la API
Lo primero que necesitamos es inicializar el objeto Intl.RleativeTimeFormat con un parámetro donde especificamos la zona regional. En este caso usamos **es**, tambíen se puede usar **en** para hacer referencia a la localización inglesa.
```javascript
const relativeTimeFormat = new Intl.RelativeTimeFormat("es");
```

### 2. Definir los formatos de tiempo
En este paso crearemos un array de objetos pasando como valores el formato y los segundos que tiene. Los formatos siguientes son **años, meses, días, horas, minutos y segundos**.

```javascript
const FORMAT_OPTIONS = [
  {
    format: "years",
    seconds: 60 * 60 * 24 * 30 * 12
  },
  {
    format: "months",
    seconds: 60 * 60 * 24 * 30
  },
  {
    format: "days",
    seconds: 60 * 60 * 24
  },
  {
    format: "hours",
    seconds: 60 * 60
  },
  {
    format: "minutes",
    seconds: 60
  },
  {
    format: "seconds",
    seconds: 1
  }
];
```

### 3. Formatear el resultado de acuerdo a la fecha ingresada
El siguiente paso es definir una función con un parámetro para obtener una fecha.

````javascript
function timeAgo(pastDatetime) {
  // siguientes pasos
}
export default timeAgo;
```

Una vez creada la función el siguiente paso es obtener la fecha actual así como la fecha pasada, para obtener la fecha actual usamos el objeto **Date** y para obtener la otra fecha asignada a una variable **pastDate** tambíen creamos un objeto con la diferencia de que le pasamos un valor recibido por constructor. Recordemos que le podemos pasar un valor al objeto **new Date** para definir una nueva fecha por ejemplo.

```javascript
const date = new Date("01/25/2021");
```

Ahora que tenemos la fecha actual y pasada, restaremos usando su método **.getTime()** para obtener el número de milisegundos.
Bien, la resta la dividiremos entre 1000 para convertir de milisegundos a segundos y se pueda manipular mucho más sencillo 😃.

```javascript
  const now = new Date();
  const pastDate = new Date(pastDatetime);
  const pastSeconds = (now.getTime() - pastDate.getTime()) / 1000;
```

Lo siguiente será recorrer el arreglo que se definió anteriormente y comparar si los segundos pasados con respecto a la fecha actual es mayor que los segundos de cada formato definido, en la primera condición que se cumpla se procederá a ejecutar las instrucciones necesarias para retornar un valor.
Como puedes observar se usa una estructura en la cuál iteramos directamente sobre los valores😅.

```javascript
  for (const { format, seconds } of FORMAT_OPTIONS) {
    if (pastSeconds > seconds) {
       // retornar valor formateado
    }
  }
```

Como último paso una vez comprobado la validación retornaremos el valor formateado usando el método del objeto **relativeTimeFormat** con dos parametros, el primero es el valor de **roundDate** cual toma como valor los segundos pasados entre los segundos del formato para obtener su valor correspondiente. El segundo viene a ser un formato como segundo, minuto, hora, etc. 
El valor **roundDate** se pasa con el signo **(-)** para poder obtener un formato con fecha pasada ya que si no usamos el signo negativo podría dar como resultado por ejemplo **Dentro de 4 días**.

```javascript
for (const { format, seconds } of FORMAT_OPTIONS) {
  if (pastSeconds > seconds) {
    const roundDate = Math.floor(pastSeconds / seconds);
    return relativeTimeFormat.format(-roundDate, format);
  }
}
```

Ahora juntando todo la función final quedaría de esta manera y es momento de probar que tal va.

```javascript
function timeAgo(pastDatetime) {
  const now = new Date();
  const pastDate = new Date(pastDatetime);
  const pastSeconds = (now.getTime() - pastDate.getTime()) / 1000;
  for (const { format, seconds } of FORMAT_OPTIONS) {
    if (pastSeconds > seconds) {
      const roundDate = Math.floor(pastSeconds / seconds);
      return relativeTimeFormat.format(-roundDate, format);
    }
  }
}
```
## ⌛😊 Realizando pruebas con la función... 

[codesanbox](https://codesandbox.io/s/implementando-timeago-gh5sq?file=/index.js)

````javascript
import timeAgo from "./timeAgo";

// mes/día/año hora:minuto:segundo

console.log(timeAgo("01/30/2021 18:44:00")); // Hace 20 segundos
console.log(timeAgo("01/30/2021 18:30")); // Hace 15 minutos
console.log(timeAgo("01/30/2021 17:00")); // Hace 5 horas
console.log(timeAgo("01/25/2021")); // Hace 5 días
console.log(timeAgo("10/01/2020")); // Hace 4 meses
console.log(timeAgo("01/12/2020")); // Hace 1 año

```