Home > front end >  Combine Date and Time without UTC
Combine Date and Time without UTC

Time:11-20

I am struggling to handle dates and times within Javascript environment. We are using two input fields to obtain a date and time for an event. The event needs to display and calculate all dates within it's local timezone. E.g. if event is in Melbourne Australia, then I see the local time in Melbourne.

We are using flatpickr for date entry and time entry (2 separate fields).

Date returns: 2022-11-18T00:00:00.000Z (i.e. we only care about the date portion. time is always 00:00:00. This is stored in Mongo as "date" : ISODate("2022-11-18T00:00:00.000 0000"))

Time returns: 09:00 AM

I would like to store this into our MongoDB as 2022-11-18T09:00:00.000.

Therefore whenever this is read or used in a calculation it always uses the time local to the event.

I have tried moment and date-fns: however I cannot find consistency between servers and browsers. Everything I have tried on SO always converts UTC.

Any help is greatly appreciated.

CodePudding user response:

In MongoDB / JavaScript Date objects are UTC times - always and only!

If you need to preserve the input time zone from user, then you have to store it in a separate field. Then your application can display the time in time zone base on input data.

At almost any "date-to-string" function you can provide the time zone information for desired output.

CodePudding user response:

Date and time functionality can be confusing so best to keep things as simple as possible. It's generally recommended to keep everything in UTC and convert to local for display.

One issue is how to get UTC in the first place.

Provided a user has their device set to appropriate regional settings, construct a Date from the date and time inputs (likely it requires a manual parse, don't use the built–in parser). Then generate a timestamp using toISOString which will be the UTC equivalent.

To then get the correct offset information, you can use:

new Intl.DateTimeFormat().resolvedOptions().timeZone

which will return the IANA representative location that the system is set to, which hopefully is consistent with the date and time of the local event. If not (e.g. the user can create an event for a different timezone) you'll need library support to generate a suitable UTC timestamp (see Calculate Timezone offset only for one particular timezone).

Store the UTC timestamp (or date object) in the database along with the event timezone. That way you can generate a date and time for the location of the event and also the equivalent date and time based on the user's system settings, or any timezone you like.

E.g.

// Create a Date for New Year's Eve party starting
// at 8:00pm based on the user's current system settings
let event = new Date(2022,11,31, 20);

// Generate UTC timestamp
let ts = event.toISOString();

// Get the (assumed) event offset data
let tz = new Intl.DateTimeFormat().resolvedOptions().timeZone;

// Data to store:
console.log(
  `Store\n`  
  `UTC timestamp: ${ts}\n`  
  `IANA timezone: ${tz}`
); 

console.log(
  `Event local date and time\n`  
  new Date(ts).toLocaleString('en-ca', {
    timeZone: tz,
    timeZoneName: 'long'
  })
); 

// Equivalent for user in Somalia
console.log(
  `Mogadishu equivalent\n`  
  new Date(ts).toLocaleString('en-ca', {
    timeZone:'Africa/Mogadishu',
    timeZoneName: 'long'
  })
);

The above demonstrates that once you have the UTC timestamp and IANA timezone, you can generate a timestamp for any timezone, including the one for the event itself.

  • Related