Time/Date in JavaScript is so confusing. Seriously. Confusing

Time/Date in JavaScript is so confusing. Seriously. Confusing
Read this if you're using Supabase PostgresQL + Mantine TimeInpu or another time input that uses a JavaScript Date, or if you just want to amuse yourself with my pain.

I ran into this really annoying issue and I came up with a really stupid solution (I hope someone tells me a better way!)

I'm currently building an app that requires me to ask a user for the open / closing time for a location like on Yelp. Of course, I thought this was going to be very straight forward.

  1. ask user for time open and time close : e.g. 8 am and 5 pm
  2. save the time to Postgres
  3. retrieve the saved time from Postgres and show the date or prefill the input

I pulled a little bit of hair out over this because I wanted to use Mantine UI's TimeInput with its  use-form package. TimeInput uses a JavaScript Date as its value, which is all fine and dandy at first. But then I dug in and realized that the Date varies depending on where the user's device is. So 8AM input from California or New York is a completely different time that gets saved into Supabase Postgres database... (For Postgres, all timestamps are stored in UTC, so we call JavaScript Date's built-in .toISOString() to format it correctly for the database. 8AM PST -> 4pm UTC and 8 AM EST -> 1PM UTC)

It leads to some pretty weird edge cases when the time is saved in one timezone and viewed in another timezone.

I got super confused trying to figure out how to fix this and went through a bunch of rabbit holes down stack overflow.

  1. ask the user for timezone input and then set the date to that timezone (FAIL, JavaScript Dates are tracked in UTC internally and don't store a timezone on the Date Object, even if this worked the user's would only see the correct time if their device was in PST)
  2. Postgres timestamps are stored in UTC and JavaScript Dates are tracked internally as UTC, so why don't I just store everything as UTC and call it a day? (FAIL, when you reinitialize the UTC timestamp in Postgres on the client, the same problem above occurs, device must be in PST!)

Ultimately... the solution was so simple, albeit hacky. I pulled my hair out and just said: "I just want to save the hour and the date", so.... why don't I just do that?

I realized I don't care if the user's timezone is; I just care that they're selecting 8:00 pm (PST,EST, UTC, whatever, I don't care!). Instead of storing a timestamp in Postgres, I ended up creating an hours and minutes column.

const timeClosed = new Date('November 17, 2022 20:00:00');
await supabaseClient
    .from("locations")
    .update({
    	hours: timeClosed.getHours(),
        minutes: timeClosed.getMinutes(),
    })

In the database, we store these values, and when the data is fetched again, all we need to do is create a new Date() and set the hours and minutes and feed that into the Mantine UI TimeInput

function generateTime(hours: number, minutes: number) {
    const baseDate = new Date();
    baseDate.setHours(hours);
    baseDate.setMinutes(minutes);
    return baseDate;
}

// <TimeInput value={generateTime(database.open_hours, database_close_hours) />}

Ahh, relief, it works. I'm definitely not satisfied with the solution, but this is the best solution I have for now. ☺️

Thanks for reading!

Subscribe to winnie's homebase

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe