How to show the Date object with the Timezone it was created in Javascript?

Asked

Viewed 661 times

8

I have the following doubt, when I create an object Date with the following string:

var teste = new Date("2020-06-03T12:05:03-05:00");

So I created an object Date who says they are 12:05:03 with a offset of -5 hours of UTC time (in that case the UTC time would be 17:05:03).

That is, the object was servant using a Timezone that is -5 o'clock. However, my computer is with Timezone -3 o'clock (BRT). With this when I try to display the object teste that I created, it displays in this way:

console.log(teste.toString()); // Wed Jun 03 2020 14:05:03 GMT-0300 (-03)

That is, it formats the display to the Timezone of my browser.

I wonder if there is any way to make him display this date, with Timezone that was informed in the creation of the object (-5 hours), without needing to change the Timezone of my computer, something similar to this:

console.log(teste.algumMetodo()); // Wed Jun 03 2020 12:05:03 GMT-0500 (-05)

That is, keep the Timezone in which the object was created.

  • 1

    You might want to start storing your dates in Unixtimestamp so you can use libraries like Moment.js or even native Apis. Take a look at this answer might help you understand better: https://answall.com/questions/285238#285388 PS: always save the captured timestamp to the server

  • 1

    Welcome to the wonderful chaotic world of date handling in Javascript. The js have many good things but certainly the treatment of dates is not one of them. It is a real chaos. As someone who has spent many hours banging his head with Javascript’s Dates and Timezones I advise you: don’t waste your time, use Moment.js soon or you will be forced to use it after hitting it hard.

1 answer

10


The Date javascript nay stores Timezone information. Despite the name, the Date is not quite a date (in the sense of representing a single value of day, month, year, hour, minute and second).

How so?

In fact, the Date represents a timestamp: the quantity of milliseconds since the Unix Epoch (which in turn amounts to 1970-01-01T00:00Z - January 1, 1970 at midnight, at UTC).

When you pass a string like '2020-06-03T12:05:03-05:00', he creates a Date the timestamp of which is equivalent to this date, time and offset. But to the flaunt this date (with toString(), for example), it is converted to browser time zone.

So much so that if you create instances of Date with different strings, but corresponding at the same time, you will see that the timestamp value will be the same:

var d1 = new Date("2020-06-03T12:05:03-05:00");
var d2 = new Date("2020-06-03T13:05:03-04:00");
console.log(d1.getTime(), d2.getTime()); // 1591203903000 1591203903000 
console.log(d1);
console.log(d2);

The two above dates have the same timestamp value, and therefore correspond to the same instant. The fact that they were generated with different strings is a detail, since the strings were used to calculate the value of the timestamp, but Timezone information is not stored in the Date (only the value of timestamp).

When printing them, the timestamp is converted to the browser’s time zone, and the output is the same for both.


Another point is that actually the value -05:00 is a offset (the difference with respect to UTC), and not a Timezone in fact (see here to learn more).

Timezones have identifiers such as America/Sao_Paulo and Asia/Tokyo, and they actually have a history of offsets used throughout history, in a particular region. For example, America/Sao_Paulo corresponds to the Time of Brasilia, and generally uses the offset -03:00, but during daylight time it changes to -02:00. This whole history is part of the Timezone (when each offset is used, when transitions occur, etc), and the offset may vary according to the date you have (whether at that time it was in daylight saving or not).

So that the exit has the offset -05:00, you would need to know which Timezone owns this offset at that particular moment (and there is more than one inclusive, and this varies according to date and time, since these timezones can also have daylight savings time and use another offset depending on the season).

An alternative (still incomplete as almost does what you need) is to use toLocaleString passing a Timezone:

var data = new Date("2020-06-03T12:05:03-05:00");
console.log(data.toLocaleString('pt-BR', { timeZone: 'America/Rio_Branco' }));

The problem is that the above output does not contain the offset, since the format depends on the locale informed (in this case, I used pt-BR - português do Brasil). Unfortunately Javascript does not provide much more resources to handle the date the way you need it.


An alternative is to use the Moment js., together with the Moment Timezone. Even so we need to pass some Timezone whose offset be it -05:00 on the date in question.

let data = moment.tz("2020-06-03T12:05:03-05:00", "America/Chicago");
console.log(data.format()); // 2020-06-03T12:05:03-05:00
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data.min.js"></script>

But there is also a way to preserve the past Timezone, using parseZone:

let data = moment.parseZone("2020-06-03T12:05:03-05:00");
console.log(data.format()); // 2020-06-03T12:05:03-05:00
// outro formato
console.log(data.format('ddd, MMM DD YYYY, HH:mm:ss Z')); // Wed, Jun 03 2020, 12:05:03 -05:00

// converter para Date
let d = data.toDate();
console.log(d); // não preserva mais o -05:00, pois Date não guarda o timezone
<script src="https://momentjs.com/downloads/moment.min.js"></script>


Gambiarra that you will probably see around

Before anyone suggests gambiarra, I’ll show myself and explain why it’s not a good idea:

function converter(data, offset) {
    data.setTime(data.getTime() + offset * 3600 * 1000);
    let s = offset < 0 ? "-" : "+";
    return data.toISOString().slice(0, -1) + s + Math.abs(offset).toString().padStart(2, '0') + ":00";
}

var d1 = new Date("2020-06-03T12:05:03-05:00");
console.log(converter(d1, -5)); // 2020-06-03T12:05:03.000-05:00

Although it seems like a good idea ("worked, showed the correct date and time!"), it’s not, because when using setTime we are changing the value of timestamp, and the date will represent a different instant.

It’s as if my computer was configured with the London time zone (but I’m in Brazil). Here it is 15h, but in London it is 19h (the English are in daylight time). So the computer clock shows 19h.

I can fix it the right way (changing the time zone settings of the computer), or I can hack and delay my watch by 4 hours: it will show the value "correct" (15h), but actually I changed the value it represents (now it indicates that it is 15h in London, an instant 4 hours in the past).

This is what I do by changing the value of the date: it represents a different moment and depending on what you need to do with it, it will give wrong results (just because it shows the value "correct", it does not mean that everything is right).


See more about dates here and here.

  • 2

    I get it, now it makes sense why it’s not possible to represent the date the way I wanted it to. Actually this form of gambiarra is not interesting to me, since I just need this formatting to display on a page, and I would not like to change, in fact, the instant that the Date represents. I’ll take a look at Moment.js, since it manages to maintain the integrity of the timestamp, this may be what I’m looking for. Thank you.

Browser other questions tagged

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