Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 640946c

Browse files
committed
fix(calendar, datepicker): fix issues with GMT+X timezones
- simplify `$$mdDateUtil.removeLocalTzAndReparseDate()` Fixes #12000
1 parent 7395914 commit 640946c

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

src/components/datepicker/js/calendar.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@
301301
/**
302302
* Sets up the controller's reference to ngModelController.
303303
* @param {!ngModel.NgModelController} ngModelCtrl Instance of the ngModel controller.
304-
* @param {Object} inputDirective Config for Angular's `input` directive.
304+
* @param {Object} inputDirective Config for AngularJS's `input` directive.
305305
*/
306306
CalendarCtrl.prototype.configureNgModel = function(ngModelCtrl, inputDirective) {
307307
var self = this;
@@ -326,7 +326,7 @@
326326
// In the case where a conversion is needed, the $viewValue here will be a string like
327327
// "2020-05-10" instead of a Date object.
328328
if (!self.dateUtil.isValidDate(value)) {
329-
convertedDate = self.dateUtil.removeLocalTzAndReparseDate(new Date(this.$viewValue));
329+
convertedDate = self.dateUtil.removeLocalTzAndReparseDate(new Date(value));
330330
if (self.dateUtil.isValidDate(convertedDate)) {
331331
value = convertedDate;
332332
}
@@ -360,7 +360,13 @@
360360
var value = this.dateUtil.createDateAtMidnight(date);
361361
this.focusDate(value);
362362
this.$scope.$emit('md-calendar-change', value);
363-
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd', timezone), 'default');
363+
// Using the timezone when the offset is negative (GMT+X) causes the previous day to be
364+
// selected here. This check avoids that.
365+
if (timezone == null || value.getTimezoneOffset() < 0) {
366+
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd'), 'default');
367+
} else {
368+
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd', timezone), 'default');
369+
}
364370
this.ngModelCtrl.$render();
365371
return value;
366372
};

src/components/datepicker/js/dateUtil.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -311,15 +311,10 @@
311311

312312
/**
313313
* @param {Date} value date in local timezone
314-
* @return {Date} date with local timezone removed
314+
* @return {Date} date with local timezone offset removed
315315
*/
316316
function removeLocalTzAndReparseDate(value) {
317-
var dateValue, formattedDate;
318-
// Remove the local timezone offset before calling formatDate.
319-
dateValue = new Date(value.getTime() + 60000 * value.getTimezoneOffset());
320-
formattedDate = $mdDateLocale.formatDate(dateValue);
321-
// parseDate only works with a date formatted by formatDate when using Moment validation.
322-
return $mdDateLocale.parseDate(formattedDate);
317+
return $mdDateLocale.parseDate(value.getTime() + 60000 * value.getTimezoneOffset());
323318
}
324319
});
325320
})();

src/components/datepicker/js/datepickerDirective.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,13 @@
990990
*/
991991
DatePickerCtrl.prototype.setModelValue = function(value) {
992992
var timezone = this.$mdUtil.getModelOption(this.ngModelCtrl, 'timezone');
993-
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd', timezone), 'default');
993+
// Using the timezone when the offset is negative (GMT+X) causes the previous day to be
994+
// set as the model value here. This check avoids that.
995+
if (timezone == null || value.getTimezoneOffset() < 0) {
996+
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd'), 'default');
997+
} else {
998+
this.ngModelCtrl.$setViewValue(this.ngDateFilter(value, 'yyyy-MM-dd', timezone), 'default');
999+
}
9941000
};
9951001

9961002
/**
@@ -1001,12 +1007,18 @@
10011007
var self = this;
10021008
var timezone = this.$mdUtil.getModelOption(this.ngModelCtrl, 'timezone');
10031009

1004-
if (this.dateUtil.isValidDate(value) && timezone != null) {
1010+
if (this.dateUtil.isValidDate(value) && timezone != null && value.getTimezoneOffset() >= 0) {
10051011
this.date = this.dateUtil.removeLocalTzAndReparseDate(value);
10061012
} else {
10071013
this.date = value;
10081014
}
1009-
this.inputElement.value = this.locale.formatDate(value, timezone);
1015+
// Using the timezone when the offset is negative (GMT+X) causes the previous day to be
1016+
// used here. This check avoids that.
1017+
if (timezone == null || value.getTimezoneOffset() < 0) {
1018+
this.inputElement.value = this.locale.formatDate(value);
1019+
} else {
1020+
this.inputElement.value = this.locale.formatDate(value, timezone);
1021+
}
10101022
this.mdInputContainer && this.mdInputContainer.setHasValue(!!value);
10111023
this.resizeInputElement();
10121024
// This is often called from the $formatters section of the $validators pipeline.

0 commit comments

Comments
 (0)