moment-timezone icon indicating copy to clipboard operation
moment-timezone copied to clipboard

Creating moment in a specific timezone with only hours supplied gives incorrect day

Open unceus opened this issue 10 years ago • 12 comments

I am in PST. In the beginning of the day, when I run Em.moment.tz('9:00 AM', 'h:mm A', 'America/Los_Angeles'), I get a moment for today at 9 AM. In the afternoon on the same day, the same command gives 9 AM tomorrow.

> Em.moment.tz('9:00 AM', 'h:mm A', 'America/Los_Angeles').toString()

"Tue Aug 19 2014 09:00:00 GMT-0700"

> Em.moment.tz('America/Los_Angeles').toString()

"Mon Aug 18 2014 19:46:43 GMT-0700"

Is this expected? I am expecting to always get a moment for 9 AM for the current day. I've done this by concatenating the time with the date that I get from Em.moment.tz('America/Los_Angeles') which has reliably given me the current day.

Moment version 2.8.1 Moment-timezone version 0.2.1

unceus avatar Aug 19 '14 02:08 unceus

Hmm, definitely not behaving as expected.

Is there a reason you need to parse a string instead of doing something like this?

moment.tz('America/Los_Angeles').hours(9).startOf('hour').toString();

timrwood avatar Aug 19 '14 04:08 timrwood

I'm saving a time of day in that format. I could create the moment the same way your example does, but that would involve me parsing the time myself.

unceus avatar Aug 19 '14 20:08 unceus

There is a weird situation going on here.

When a moment is created with moment.tz, the arguments are first passed to moment.utc. When it gets to the part in parsing that requires getting defaults for the day, month, and year, it gets the current day in UTC.

However, the current day in America/Los_Angeles is not the current day in UTC. From 12 am to 8 am, UTC is in the next day, hence your results.

It might be possible to make moment aware of the offset when choosing a default day, however, that is problematic. In order to know what offset to use, you need to know what date you are on, as you could be in DST.

So we need the offset to determine the day and we need the day to determine the offset. I'll have to do some more thinking on how to solve this one. Marking as a bug for now though.

timrwood avatar Aug 19 '14 21:08 timrwood

@timrwood @unceus Do we have any lead in this bug. This use-case(creating moment with only hours) would be pretty common. It could be a potential pain-point for many to use this great library :( Will try to see if i can provide any help in finding a fix for this. Will keep you guys posted.

kashifshamaz21 avatar Dec 10 '14 19:12 kashifshamaz21

@unceus @kashifshamaz21 How about something like

var time = moment.utc(timeString, 'h:mm A');
var dateTime = moment.tz('America/Los_Angeles').set({hours: time.hours(), minutes: time.minutes()});

Pretty much the same as timrwood's suggestion, but lets moment handle parsing the time for you. I'm not sure how well this would work for DST-switching days where the specified time falls in the missing or duplicated hour, but it should be okay as long as it functions the same as how moment-timezone handles DST issues for parsed dates.

jabjab avatar Apr 06 '15 17:04 jabjab

@jabjab - That seems like a reasonable workaround.

mattjohnsonpint avatar Apr 07 '15 05:04 mattjohnsonpint

Just got bitten by this too. How about

var now = moment.tz('America/Los_Angeles');
var dateTime = moment.tz('09:00:00', 'HH:mm:ss', 'America/Los_Angeles').date(now.date());

Do you see any problem with that?

realyze avatar Sep 15 '15 21:09 realyze

@realyze - That might fail on the first/last day of the month.

mattjohnsonpint avatar Sep 17 '15 21:09 mattjohnsonpint

I think https://github.com/moment/moment-rfcs/pull/1 could help provide a solution to this.

timrwood avatar Mar 15 '16 18:03 timrwood

Though this may be a bit late, I wanted to update this bug because I never actually wrote out the coded workaround that I alluded to in 2014. Until @timrwood is finished implementing the new moment timezone interface,

todayDate = moment.tz('America/Los_Angeles').format('YYYY-MM-DD')
todayStart = moment.tz(todayDate + ' 9:00 AM', 'YYYY-MM-DD h:mm A', 'America/Los_Angeles')

unceus avatar May 04 '16 19:05 unceus

I am trying to get 9:30 AM of America/Chicago timezone Should I be using this method? moment().tz('America/Chicago').hours(9).minutes(30).seconds(0); or moment().tz('America/Chicago').hours(16).minutes(30).seconds(0); for 4:30 PM

ahmu83 avatar Jul 01 '21 22:07 ahmu83

I'm not sure if this bug is related, I found that these two parsing way are giving different result

moment.tz('July 30, 2022 5:00 PM', 'America/Indiana/Indianapolis').toString() > 'Sat Jul 30 2022 13:00:00 GMT-0400' the function assumes that the datetime is in UTC then converted to EST, which is incorrect

moment.tz('July 30, 2022 5:00 PM', 'MMMM DD, YYYY hh:mm A', 'America/Indiana/Indianapolis').toString() > 'Sat Jul 30 2022 17:00:00 GMT-0400' this is correct

natsu90 avatar Aug 04 '22 01:08 natsu90