indrimuska / angular-moment-picker

Angular Moment Picker is an AngularJS directive for date and time picker using Moment.js.
http://indrimuska.github.io/angular-moment-picker/
MIT License
525 stars 226 forks source link

How does this directive deal with timezones? #176

Open bhaidar opened 7 years ago

bhaidar commented 7 years ago

Hi, How does this directive deal with timezones?

In my case, I need the user to select a date so that the time part of it should be based on his/her timezone.

How does this integrate? Shall I configure Moment timezone and this is enough?

Thanks

indrimuska commented 7 years ago

Hi @bhaidar, actually it does not handle timezones, since I have not heard about any specific requirements, so basically it should use your users' pc timezone.

marc-thomas commented 7 years ago

Hey @indrimuska, I am using the directive to display start/end dates for events to the user, using a date sector and a time selector, separately. I also have a timezone selector which sets the timezone.

The requirements for this is so that someone in Toronto can create an event in Vancouver, and not have any issues displaying the proper time of the event to someone in Calgary.

This example is using 0.10.1

<div class="col-sm-6">
            <span
                ng-model="event.starts_on"
                locale="en"
                change="updateStartDate(newValue, oldValue, event.timezone)"
                ng-model-options="{ updateOn: 'blur' }"
                format="LL"
                today="true"
                moment-picker>
                <span class="date-display-big">
                  <i class="icon-calendar mr5"></i> [[ event.starts_on | timezone:event.timezone:'ll' ]]
                </span>
            </span>
        </div>
        <div class="col-sm-6 moment-timepicker">
            <span
                ng-model="event.starts_on"
                locale="en"
                change="updateStartDate(newValue, oldValue, event.timezone)"
                ng-model-options="{ updateOn: 'blur' }"
                format="LT"
                show-header="false"
                moment-picker>
                <span class="date-display-big">
                  <i class="icon-time mr5"></i> [[ event.starts_on | timezone:event.timezone:'LT' ]]
                </span>
            </span>
        </div>
$scope.browserDiff = timezone => {
            var eventNow = moment.tz(timezone);
            var localNow = moment().tz(moment.tz.guess());
            return moment.duration({'milliseconds': ((localNow._offset - eventNow._offset) / 60) * 3600000});
        };

        $scope.updateDate = (newValue, timezone, time) => {
            var browserDiffs = $scope.browserDiff(timezone);
            return moment(newValue).add(browserDiffs, 'milliseconds').tz(timezone).format();
        };

        $scope.updateStartDate = (newValue, oldValue, timezone) => {
            console.log('Model changed from ' + oldValue + ' to ' + newValue);
            if (oldValue) {
                $scope.event.starts_on = $scope.updateDate(newValue, timezone);
            }
        };

The issue I am running into is that the change function gets called 3 times when selecting a new date, or time - which results in undefined values and it sets the date/time to now.

You can see the console log results here

Model changed from 1509516000000 to 1512111600000
Model changed from 1512111600000 to undefined
Model changed from 1504317600000 to undefined

I have a version working, but i'm looking to upgrade the library from 0.8.4 and clean out some code. The current working version I am using has to create new starts_on_time and starts_on_date models, and I have to run a combine date/time function depending on which moment-picker gets adjusted.

Wondering if you have any other solutions for doing something like this?

Thanks in advance.

CareerFairPlus commented 6 years ago

If you configure a moment with a timezone (using moment-timezone) like so: var date = moment('2018-06-01T12:00:00.000Z', moment.ISO_8601).tz('America/New_York'); and bind that to the ng-model value on the moment-picker, then it will have the associated time zone as a part of the date only when the directive initially loads.

However, as soon as the user changes the date, that time zone information is gone. Also, if you update the bound value programmatically (even with a moment-timezone object) after the directive has loaded that time zone information is gone. There's something fundamentally wrong about that. I’ve created a fix for this by simply checking if the model is a valid moment before attempting to create a new moment based upon the formatted value. I can’t create a PR though because the tests don’t pass after simply cloning the repo without making any changes. I’m receiving the same errors as listed here in the latest build run: https://api.travis-ci.org/v3/job/379143131/log.txt