Date timezone conversion socket.io - node.js

I'm writing a chat program using node.js and socket.io. When a user sends a message, I'd like the time at which they sent it to be emitted. Instead of the Date data being in the timezone of the person who sent it, however, I'd like it to be converted to the timezones of the respective recievers. Will JavaScript take care of this automatically, or is it something I need to fix?
socket.emit('chat', {
message: 'message',
date: new Date()
}

You can simply send the UTC value from the Date back to your server and up to another client. Even if they have different time zones, the local client will convert from the UTC value to that time zone when the Date is displayed.
It is important that the date is sent as UTC and not in the local time zone.
This can be an integer number (which will be milliseconds since 1/1/1970 UTC), obtained from .getTime(). All browsers support this, but it's not a very human readable format.
It can also be a string in ISO8601/RFC3339 format at UTC, such as 2013-06-26T15:40:00Z, which can be obtained by .toISOString().
What you can't do is just pass a Date object directly, as you showed in your sample. Socket.io will just call .toString() on it. That will end up sending a human readable RFC822 formatted string with the local time zone - not the UTC value that you want.

Javascript date object in different locale and timezone
This answer looks good. Store all your dates as UTC and then translate to receivers time zone.

Related

How to convert the local browser time to utc time unsing moment.js

Tried multiple methods to convert the local time to UTC. Tried Offset(420) as the time difference is UTC 7 and it worked. So here what i need is my users will be giving a request from different timezones and all of them should convert to UTC. So when giving time from different timezone the UTC time difference will also change how it can be identified and change accordingly. how can i do that?
You can use moment.utc() to get UTC time. If you wish to send it to the server, it's probably best to send as an ISO-8601 date string.
const localDate = moment();
const utcDate = moment.utc();
console.log("Local time:", localDate.format("YYYY-MM-DD HH:mm:ss"));
console.log("UTC time:", utcDate.format("YYYY-MM-DD HH:mm:ss"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

Date format in our Application

Can anyone tell me which is the right format to store date in my database.
Suppose if the client and the server are in the same region, we can use unix epoch timestamp or date string. But if the server is in US and the client is from Asia, I knew people saying UTC to auto convert date from the particular region. But I cannot store UTC in MongoDB via Node js, maybe i made it in the wrong way.
.currently I store "09-02-2021" for date and 1612837056077 timestamp. I also get the time from the front end.Also, I am not sure with the above things. Can someone explain the right way of using date and time in a real world application. If possible show me a quick demo in node js and mongoose
Thank you all :)
UTC is the way to go. I don't know what you mean by "But I cannot store UTC in MongoDB via Node js". Create your schema like so:
const client_schema = new mongoose.Schema({
...
...
date_created: {type: Date, default: Date.now},
...
...
});
And date_created will always be stored in UTC format. From UTC, you can convert it to any timezone. Here is just one example, using moment, of how to convert UTC to a Eastern Timezone:
const d = moment(utc_date).utcOffset(moment(utc_date).tz("America/New_York").format('Z'), true).toDate();
Note: moment is being phased out and is no longer recommended for new projects.

Mongoose datetime and timezone, how to get datetime based on server timezone

The first answer of this question suggests that mongoose would adapt the date according to server timezone when retrieving data.
However, I don't have this comportement.
I set the (node) server timezone with :
process.env.TZ='Europe/Paris'
For exemple if I create a simple model like :
const mongoose = require("mongoose");
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
exports.Comment = mongoose.default.model('TestSchema', testSchema);
But if I create a date with 2020-01-01 20:20:20, when doing TestSchema.find() the date will be: 2020-01-01T19:20:20.000Z so there are two things that I don't understand :
Europe/Paris is actually UTC +2, so I would expect the date to be either 2020-01-01T18:20:20.000Z in UTC or 2020-01-01T20:20:20.000Z with the server timezone
How to have mongoose automatically set the date to the correct timezone?
I know that myDate is a Date object, so I can convert it manually but I'd rather not have to do it myself for simple reasons like forgetting to convert one of the dates in the application or not having to do it every time a Date field is added
An easy solution that I can think of would be to register a global plugin for mongoose which would use schema.set('toJSON', ... and schema.set('toObject', ...) with the transform method so I can loop through schema fields and if the field is a Date, update it to my timezone.
But I see two problems with this approch :
It doesn't sound very good performance-wise if I am querying a lot of documents each with a lot of fields
As you can see here I am currently not able to register global plugins...
What would be the best method to get the date in the server timezone format? I would rather still store them in UTC but set the hour according to the server timezone.
EDIT :
I just saw that while console.log(myDate) outputs 2018-01-01T19:20:20.000Z console.log(myDate.toString() outputs Mon Jan 01 2018 20:20:20 GMT+0100 (Central European Standard Time) so it seems likes this could be used, even tho I'd rather still have a Date object and converting it to string just before sending it to the client (would need some formatting tho since this format is not very user friendly). But then again, how would I do this globally and not for every date
A few things:
Europe/Paris at 2020-01-01T20:20:20 is UTC+1. It doesn't switch to UTC+2 until Summer Time kicks in on March 29th. Reference here. Thus the conversion to 2020-01-01T19:20:20Z is correct.
The output of console.log when passed a Date object is implementation specific. Some implementations will emit the output of .toString() (which is in local time in RFC 2822 format), and some will emit the output of .toISOString() (which is in UTC in ISO 8601 extended format). That is why you see the difference.
In general, it is not good to send a local time without also sending a time zone offset. ISO 8601 format is ideal, but you should send either 2020-01-01T19:20:20Z, or 2020-01-01T20:20:20+01:00. Don't just send the date and time without an offset to the client. Otherwise, if your client could be in a different time zone then they would interpret the value incorrectly.
Keep in mind that Date objects are not time zone aware. They contain only a Unix timestamp internally, and they convert only to the system's local time zone for the functions that work in local time. They cannot work in any other time zone.
Relying on the system local time zone is bad for portability. One doesn't always have the ability to change it, and it doesn't do well when you have to work in multiple time zones. It would be better to not rely on setting a local time zone from Node's TZ variable. Instead, consider writing your code to be independent of any local time zone setting.
A time zone aware date library can help with most of your concerns. I can recommend Luxon, js-Joda, Moment + Moment-Timezone, or date-fns + date-fns-timezone.
"how would I do this globally" is something I'm not following in your question. Try the approach I described, and if you still have issues then open a new question. Try to be specific and ask a single question. You're likely to get better results that way. Please read How do I ask a good question? and How to create a Minimal, Complete, and Verifiable example. Thanks.
To solve the issue:
npm i mongoose-timezone
In your schema file:
import timeZone from "mongoose-timezone";
const testSchema = new mongoose.Schema({
myDate: { type: Date, required: true },
}, { timestamps: true });
// mongoose will save the dates based on user's timezone
testSchema.plugin(timeZone)
mongoose-timezone basically adds the current timezone offset to the
date before store and removes the offset when retrieving data. This
way dates are kept proportional in the database and in the app.

Are Alexa skill dates the same in the Service Simulator and the Echo?

My Alexa node.js skill involves getting the current date using "new Date()". In the Service Simulator the date returned is UTC. But I need the time in "America/New_York" -- my skill is local to New York. So I can convert the time zone, no problem. But I'm wondering whether this will get the same result when I deploy the skill. That is, does the Date() function on the actual Service convert to local time from UTC? If it does, then I will need some way of determining in my code whether I am in the Service Simulator or the actual Service, and converting to New York time in my accordingly.
Thank you.
From the documentation for Date
If no arguments are provided, the constructor creates a JavaScript Date object for the current date and time according to system settings.
So depending on the system settings the timezones can be different.
To overcome this you can use UTC date everywhere and then simply convert the timezone where needed.
// date with some timezone depending on system
let date = new Date();
// date in UTC
let utcDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
Note: utcDate will still be in the system timezone, but the actual value it holds will represent the correct date and time in UTC.

Mongoose converting stored UTC dates to local time?

I'm wondering if this is normal, or if I'm missing something in the schema setup or query process:
My app, and mongoose, is correctly storing a date as UTC in mongodb. This is confirmed by viewing the documents via the mongo shell. When I retrieve the documents from mongodb via mongoose the date is now local time.
Is there a way to have mongoose keep the date as UTC when queried?
Mongoose and node.js aren't doing anything to your dates, it's simply that the JavaScript Date type produces a local time string when you call toString() on it even though it actually contains the time in UTC.
Explicitly call toUTCString() on your Date object if you want a UTC time string.
The timestamps are stored timezone agnostically, as a unix timestamp. This timestamp will work across timezones, and node interprets it using your current timezone. You can retrieve the UTC value from the date object using the getUTC* methods such as get getUTCHours()

Resources