Uma alternativa vanilla JS para o método moment.js timeFromNow()
Tags: javascript, programming, portugues
Published: 2023-12-02 14:01:34

_**Nota:** apenas traduzi o texto abaixo e postei aqui._

## O que o método moment().timeFromNow() faz

O método `moment().timeFromNow()` retorna uma string formatada com "há quanto tempo algo aconteceu".

Você passa uma data do passado e ela retorna coisas como alguns segundos atrás ou 2 anos atrás.

```javascript
// 16 anos atrás
moment([2007, 0, 29]).fromNow();
```

Ele apenas fornece datas no passado. Existe outra function, `moment.timeToNow()`, para datas futuras.

## O que nossa helper function timeFromNow() fará

Nossa helper function funcionará de maneira um pouco diferente.

Uma das coisas que gosto no Vanilla JS é o maior controle que você tem. Em vez de obter uma string pré-formatada, prefiro ter a diferença de tempo e as unidades de tempo (anos, meses, etc.) com as quais posso trabalhar como quiser.

Eu também preferiria uma function que funcionasse tanto para eventos passados quanto futuros.

Em vez de retornar uma string, nossa helper function retornará um object a diferença de tempo, as unidades de tempo e se o tempo está no passado ou no futuro.

## Contruindo uma helper function timeFromNow()

Primeiro, vamos configurar uma helper function que aceita o `time` como argument.

```javascript
var timeFromNow = function (time) {
	// O código vai aqui...
};
```

O valor `time` pode ser uma string, um `Date() object` ou um unix timestamp em milissegundos.

```javascript
// Esses são todos válidos
timeFromNow('December 31, 1999');
timeFromNow('1999/12/31');
timeFromNow(new Date('1999-12-31T10:30:00-04:00'));
timeFromNow(946650600000);
```

## Calculando a diferença de tempo

Para encontrar a diferença entre o `time` e `now`, primeiro precisamos obter um valor de timestamp para o nosso `time`.

Iremos passá-lo para um novo `Date() object` e, em seguida, chamaremos o método `getTime()` nele. Também criaremos outro novo `Date()` object para obter o `time` de `now` e obter um timestamp para isso também.

Se não houver unixTime válido (se o usuário informou uma data incorreta, por exemplo), retornaremos `null`.

```javascript
var timeFromNow = function (time) {
	// Obtêm timestamps
	var unixTime = new Date(time).getTime();
	if (!unixTime) return null;
	var now = new Date().getTime();
};
```

A seguir, subtrairemos o time de `now` do nosso unixTime para obter a diferença entre o `time` e `now`.

Ambos timestamps estão em milissegundos, e a menor unidade com a qual queremos trabalhar são segundos, então dividiremos os dois numbers por 1000 primeiro para convertê-los em segundos.

```javascript
var timeFromNow = function (time) {
	// Obtêm timestamps
	var unixTime = new Date(time).getTime();
	if (!unixTime) return null;
	var now = new Date().getTime();

	// Calcula a diferença
	var difference = (unixTime / 1000) - (now / 1000);
};
```

## Criando nosso time a partir dos dados de now

A seguir, vamos configurar um object chamado tfn que armazenará nossos dados de time a partir de `now` (agora).

O primeiro dado que adicionaremos é quando o time acontece: no passado, agora ou no futuro. Se a diferença for maior que 0, isso aconteceu no futuro. Se for menor que -1, isso aconteceu no passado. Caso contrário, está acontecendo agora.

(Usamos -1 em vez de 0 para contabilizar pequenas frações que podem ocorrer com timestamps).

```javascript
var timeFromNow = function (time) {
	// Obtêm timestamps
	var unixTime = new Date(time).getTime();
	if (!unixTime) return null;
	var now = new Date().getTime();

	// Calcula a diferença
	var difference = (unixTime / 1000) - (now / 1000);

	// Configura o object retornado
	var tfn = {};

	// Verifique se o time está no passado, presente ou futuro
	tfn.when = 'presente';
	if (difference > 0) {
		tfn.when = 'futuro';
	} else if (difference < -1) {
		tfn.when = 'passado';
	}
};
```

## Calculando as unidades de tempo

Em seguida, precisamos descobrir se a nossa diferença tem anos, meses, dias, horas ou segundos.

Primeiro, usaremos o método `Math.abs()` para converter quaisquer números negativos em positivos. Então, podemos verificar `unitOfTime`.

Para isso, dividiremos a diferença pelo número de segundos de um ano, mês, dia e hora. Se esse valor for maior que 1, essa é a nossa unidade. Caso contrário, continuamos. Como a duração dos meses pode variar, usaremos 45 para o número de dias.

Também definiremos `tfn.time` e usaremos o método `Math.floor()` para arredondar para o integer mais próximo.

```javascript
var timeFromNow = function (time) {
	// ...

	// Converte a diferença para "absolute"
	difference = Math.abs(difference);

	// Calcula a unidade de tempo
	if (difference / (60 * 60 * 24 * 365) > 1) {
		// Anos
		tfn.unitOfTime = 'anos';
		tfn.time = Math.floor(difference / (60 * 60 * 24 * 365));
	} else if (difference / (60 * 60 * 24 * 45) > 1) {
		// Meses
		tfn.unitOfTime = 'meses';
		tfn.time = Math.floor(difference / (60 * 60 * 24 * 45));
	} else if (difference / (60 * 60 * 24) > 1) {
		// Dias
		tfn.unitOfTime = 'dias';
		tfn.time = Math.floor(difference / (60 * 60 * 24));
	} else if (difference / (60 * 60) > 1) {
		// Horas
		tfn.unitOfTime = 'horas';
		tfn.time = Math.floor(difference / (60 * 60));
	} else {
		// Segundos
		tfn.unitOfTime = 'segundos';
		tfn.time = Math.floor(difference);
	}
};
```

Se esses números são confusos, vamos detalhá-los um pouco.

Um minuto tem 60 segundos, uma hora tem 60 minutos e um dia tem 24 horas. Existem 365 dias em um ano. Para calcular o número de segundos em um ano, multiplicamos todos esses números juntos.

```javascript
// O número de segundos em um ano
var year = 60 * 60 * 24 * 365;
```

Por dias, multiplicaríamos 60 segundos por 60 minutos para obter uma hora de segundos e depois multiplicaríamos por 24 (o número de horas em um dia).

```javascript
// O número de segundos em um dia
var day = 60 * 60 * 24;
```

## Retornando nosso tfn object

Agora que fizemos todos os nossos cálculos, a última coisa a fazer é retornar nosso tfn object.

```javascript
var timeFromNow = function (time) {
	// ...

	// Retorna o time dos dados de agora
	return tfn;
};
```

Isso funcionará em todos os navegadores modernos e, pelo menos, no IE 9.

Saúde,

### Fonte

Newsletter de [Go Make Things](https://gomakethings.com/)