2

I've lost track of how many questions & responses I've read while trying to find an answer on this. The ones that sound like they're related often aren't, or else the users are just accused of being confused. (As an example, the first answer here just tells the person asking the question that they don't really mean to be asking what they're asking. Then there's this one. The most upvoted answer here says it's just impossible. Etc., etc., etc.)

I need to be able to take a time--say 9:00 AM--and work with it as 9:00 AM regardless of which timezone my user is in. If a user pulls up this time in a US/Eastern timezone, they should see this value as 9:00 AM. If a user pulls up this time in a US/Pacific timezone, they should see this value as 9:00 AM. I recognize that this is not actually the same moment in time, and I don't need it to be.

To illustrate, let's call the timezone-immune timestamp I'm talking about timezoneImmuneTimestamp, and say that its value should always be 9:00 AM.

Say I'm executing someMomentInUsEasternTimezone.diff(timezoneImmuneTimestamp, 'minutes'), where someMomentInUsEasternTimezone is equal to 10:00AM (EST). The answer I need is 60 minutes.

Now let's add another Moment, someMomentInUsPacificTimezone and say its value is 11:00AM (PST). When I execute someMomentInUsWesternTimezone.diff(timezoneImmuneTimestamp, 'minutes'), the answer I need is 120 minutes.

Has anyone else had this particular problem, and more importantly, solved it?

79-madms
  • 596
  • 1
  • 7
  • 19

1 Answers1

2

It sounds like you want to work with only the "wall time" of each moment object. To do that, first create a clone of each moment and set their offsets to zero, as if they were UTC. When doing so, pass true to keep the wall time instead of the same point in actual universal time.

This is described in the docs for the utcOffset function:

The utcOffset function has an optional second parameter which accepts a boolean value indicating whether to keep the existing time of day.

  • Passing false (the default) will keep the same instant in Universal Time, but the local time will change.

  • Passing true will keep the same local time, but at the expense of choosing a different point in Universal Time.

Thus, to get the difference in minutes between momentA and momentB with respect only to wall time:

momentA.clone().utcOffset(0, true).diff(momentB.clone().utcOffset(0, true), 'minutes')

Though missing from the docs, the same argument can be passed to the utc function. So if you prefer, you can shorten it to:

momentA.clone().utc(true).diff(momentB.clone().utc(true), 'minutes')

(Cloning helps the rest of your code by not mutating the original moment objects.)

Also - The Moment team highly recommends only using Moment in legacy/existing code. If you are writing a new application, please try Luxon instead. In Luxon, the setZone function has a keepLocalTime option that does the same thing as I showed in Moment.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • I can't tell you how much I appreciate this *correct* response. I've spent ludicrous amounts of time on this. Just tested my application by swapping timezones, and I'm seeing exactly the behavior I was after. Thanks for all the detail and the time you spent! (And also thanks for turning me onto Luxon! I'm liking what I'm reading in the docs.) – 79-madms May 12 '20 at 23:00