I'm having trouble with the scheduling system I am creating in node (client and server API). My server is in UTC.
As I wanted my timezone to be consistent wherever the user was based, I suggested a timezone to the user based on their business address provided. The aim was for the user to be able to view their scheduling details from anywhere around the world, and still see the same dates. eg. User business is based in the UK, and they schedule a booking for 8pm. Then user travels to Asia for a holiday, logs into the system, and still sees the booking specified as 8pm, and can use the calendar to schedule more bookings, which can then be viewed back in the UK at the Date specified when abroad.
This had been working well up until now. I am saving the user timezone against the user on signup. I am storing the dates in the postgres database without timezone. When retrieving from the database, I am using
date = moment(fetcheddate).tz(usertimezone, true);
When I am working at server/client boundaries (and am expecting a timezone), I am using:
date = moment(receiveddate).tz(usertimezone);
This ensures that all dates are consistently in the business timezone whenever they are being used, with the express aim of all dates consistently reading as a moment object with the time always set to 00:00:00.
On the server, my business logic makes a lot of use of Moment add/subtract; isSame/isBefore/isAfter to generate new dates internal to the workings of this scheduling system.
Now the problem. Occasionally, I need to know what the current day is. eg. On the server, I alter a blockbooking by enddating the currently saved block booking, setting to "yesterday", and starting a new blockbooking from "today". .
Looking at the "alter block booking" scenario in more detail: on the server I generate "today" by calling moment, and converting into the business timezone, using moment startOf('day') to remove time info.
today = moment().tz(usertimezone).startOf('day');
I then set startdate on my new blockbooking object equal to this today value.
Now, if the user is in the same timezone as the business timezone, then this works perfectly. However, if they are working from abroad at the time in a different timezone, then I get the problem that my startday is a day out.
For instance, my current blockbooking saved info may have a start date of "2021-02-06 00:00:00". I choose to alter this blockbooking on the same day, 6th Feb, when abroad. I expect my new startdate to also equal the 6th. However, using today = moment().tz(usertimezone).startOf('day') results in me getting 5th of Feb as my new startdate, which is a day out.
I can't rely on just using moment() to get the correct date, as the server is in utc. The only solution I can think of is to pass up the browser timezone from the client using
moment.tz.guess();
But I'm not sure I can completely trust this call for such integral functionality, as it seems that there may be a number of bugs. eg. Return timezone name with Moment's guess().
I'm sure there must be a solution for this that I'm not thinking of. Perhaps my choice of using the business timezone to sync datetimes is a problem. I think that passing dates without timezones at server boundaries would work for the majority of functionality, and might simplify things, although I am not sure. But I think I still hit the same problem of generating the "today" date on the UTC server.
Does anyone have any ideas around this? What have I missed?
UPDATE: Upon request, my main question is how do I get the date value of "today" in server such that it is equal to "today" in browser. This "today" date in server must then be compared against dates that are set to the user's business timezone. Or if you have an alternative implementation that circumvents this issue then that is acceptable too