How to filter an array with Timestamp elements?

Asked

Viewed 72 times

2

I need to create filters for a chart and I am using lib Highcharts only on the front. Data is being consumed from an API in an array of arrays like this:

[
  [
    1565308800000,
    24960
  ],[
    1565568000000,
    24960
  ]
]...

I’m taking the index values [0] of each array that are timestamp dates but I can’t compare to filter.

if (value === '1') {
   const data = list.map((item) => item[0])

it returns me only the first values.

I tried the .filter()

const FilteredValue = data.filter (function (data) {
      return data > 2019;
})

I’ve tried with the year and also with the timestamp value and not the right one.

  • Should I convert the timestamp? If yes how do I do this?

2 answers

4


Depends much what you want to do, but first you need to understand what is the timestamp.


Understanding the timestamp

Basically, a timestamp such as 1565308800000 indicates that more than 1.5 trillion milliseconds have passed, counted from the Unix Epoch (which in turn corresponds to 1 January 1970, at midnight, at UTC).

But this value is "universal", in the sense that it is the same for the whole world. It represents a specific instant, a point in the timeline. And that’s when the trouble starts...

When converting the timestamp to a date, you have to take into account the time zone, because in each one the value corresponds to a different date and time. Some examples:

Time zone Date/time
America/Sao_paulo 08/08/2019 21:00
America/Los_angeles 08/08/2019 17:00
Asia/Tokyo 09/08/2019 09:00
UTC 09/08/2019 00:00

All dates and times above correspond to the timestamp 1565308800000. That is, the point on the timeline is the same: it is the instant that occurred 1,565,308,800,000 milliseconds after the Unix Epoch. Only this same instant corresponds to a different date and/or time, depending on the time zone you consider.

So if you convert the timestamp to a date, and/or want to compare it to another date, you will have to take this into account.

To understand more about how the Date javascript, see here, here and here.


Different ways to convert can give different results

Depending on how you do it, you may get a different result in some cases. That’s because the Date Javascript, despite the name, does not keep a date (in the sense of having a single value for day, month, year, time, minute and second). In fact it only holds the value of timestamp.

Only when we use the Date for information such as the day (with getDate()) or the time (with getHours()), values are returned according to the Timezone that is configured in the environment in which the code is running (be it the browser or runtimes like Node.js and Deno, etc.).

That is, if you convert the timestamp to a date and print it out:

var data = new Date(1565308800000);
console.log(data.toString());

The output may vary according to the time zone setting. For example, if you are in Brasilia Time, the output will be Thu Aug 08 2019 21:00:00 GMT-0300 (Brasilia Standard Time), but if I switch to Japan, the exit will be Fri Aug 09 2019 09:00:00 GMT+0900 (Japan Standard Time). And the same goes for getters (getDate() and getHours() will return different values according to the spindle).

Of course, for your example, where I just wanted to compare the year, it can "work" most of the time. But there is still room for problems, such as:

var data = new Date(1577844000000);
if (data.getFullYear() > 2019) {
    console.log('ok');
}

If the above code runs in an environment in which the time zone configured is the Time of Brasilia, the "ok" will not be shown, since this timestamp corresponds to 31/12/2019 at 23:00 in the Time of Brasilia. But if the time zone is, for example, from somewhere in Europe or Asia, then it shows "ok", because in these time zones the timestamp corresponds to some time of 01/01/2020.


Same goes if you create an arbitrary date, as suggested by the other reply. Actually there’s another one there, which is the fact that you used a string in a non-standard format. In Firefox, for example, new Date('12-01-2020') returns "Invalid Date" (in Chrome and Node.js "works").

That’s because the only format defined by the specification and that it is guaranteed to work in any environment is defined by ISO 8601 standard (that in the case would be "year-month-day", ie, 2020-12-01). Any other format is dependent on implementation and varies greatly from one environment to another, and may or may not work (see more on the subject here and here).

Anyway, if you want to create a specific date, you can use this format, or numeric values:

// criando um Date equivalente a 1 de dezembro de 2020

// string no formato ISO 8601
var data = new Date('2020-12-01');

// ou, usando valores numéricos
var data = new Date(2020, 11, 1); // não é erro, o mês é 11 mesmo

One detail is that if you use numeric values, December has to be 11, because in Javascript the months are annoyingly indexed at zero (January is zero, February is 1, etc). See more here and here.

But there’s still a "catch".

When you only report the day, month and year, the time is automatically set to midnight. But there is an important difference between the two options above.

In the first case (string in ISO 8601 format), the time is set to midnight in UTC, while in the second case, the time is set to midnight in the time zone of the environment. This can give difference in timestamp value:

var d1 = new Date('2020-12-01'); // meia-noite em UTC
var d2 = new Date(2020, 11, 1); // meia-noite no timezone do browser

console.log(d1.toString());
console.log(d1.valueOf());

console.log(d2.toString());
console.log(d2.valueOf());

I ran the code above on my browser, configured with the Time of Brasilia, and the output was:

Mon Nov 30 2020 21:00:00 GMT-0300 (Brasilia Standard Time)
1606780800000
Tue Dec 01 2020 00:00:00 GMT-0300 (Brasilia Standard Time)
1606791600000

In the first case, he created a Date corresponding to 12/01/2020 at midnight on UTC (which in turn, corresponds to 30/11/2020 to 21h in Brasilia Time). Already in the second case, he created the Date corresponding to 12/01/2020, at midnight in Brasília Time. That’s why timestamps are different.

And if you run in environments with another time zone set, the results will be different (the second timestamp will not be the same as the one I got).


So how do I do?

Depending on how you choose to do the conversions (whether by converting the timestamp you have, or by creating one Date with a fixed date), may have corner cases where a "valid" date will be left out (or an "invalid" will be considered).

Just to quote a few examples of how it could be done:

var list = [
  [ 1565308800000, 24960 ],
  [ 1565568000000, 24960 ]
];

// criar uma data limite usando algum dos métodos acima, e pegar o timestamp
var limite = new Date('2019-08-10').valueOf();
var filtrados = list.filter(dados => dados[0] > limite);
console.log(filtrados); // [ [ 1565568000000, 24960 ] ]

// ou converter o timestamp para Date e verificar o critério desejado
filtrados = list.filter(function(dados) {
    var d = new Date(dados[0]);
    return d.getDate() > 10; // filtrar os dias maiores que 10
});
console.log(filtrados); // [ [ 1565568000000, 24960 ] ]

Always remembering the details already mentioned above: each approach will have some specific detail to be considered, always related to the time zone. If the code runs in the browser, for example, you have no control over the configuration of the spindle (and then you would have to resort to external libraries for this, since Javascript does not have a decent support for this - in the future will have, but for now has not).

If you are using Node.js >= 13 on Linux, you can set Timezone at the beginning of the script. For example:

process.env.TZ = 'America/Sao_Paulo'; // Horário de Brasília

In the case, America/Sao_Paulo corresponds to the Time of Brasilia. The names of the timezones are defined by IANA, and can be consulted here.

  • 1

    Thank you so much for clarifying, your explanation was excellent and at the end you ended up talking exactly what I also needed, success and thank you!!

1

You can take the date you want to compare and convert it also to timestamp using the function new Date().getTime(). For example, say I only want dates before December 1, 2020.

const FilteredValue = data.filter (function (data) {
  const primeiroDezembro = new Date('12-01-2020').getTime()
  return data < primeiroDezembro;
})

There are some libraries that facilitate such comparisons, such as the date-fns

  • It worked buddy! Thank you!!

  • 1

    @Luizfelipe and Bruno, remember that new Date('12-01-2020') it is not guaranteed to work on all browsers - I tested in Firefox 90 on an Ubuntu machine, for example, and gave "Invalid Date". This is because the only format guaranteed by the specification that works in any environment is "yyyy-mm-dd" (in which case, it would be new Date('2020-12-01')), but still has other important details that are explained in the other answer

Browser other questions tagged

You are not signed in. Login or sign up in order to post.