diff --git a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts index 7b0f21534d6a..f02403eab6ae 100644 --- a/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts +++ b/packages/devextreme/js/__internal/ui/date_box/m_date_box.mask.parts.ts @@ -32,6 +32,7 @@ const PATTERN_GETTERS = { m: 'getMinutes', s: 'getSeconds', S: 'getMilliseconds', + x: 'getTimezoneOffset', }; const PATTERN_SETTERS = extend({}, getPatternSetters(), { @@ -79,6 +80,7 @@ const PATTERN_SETTERS = extend({}, getPatternSetters(), { date.setFullYear(newValue); }, + x: (date) => date, }); const getPatternGetter = (patternChar) => { @@ -134,6 +136,7 @@ const getLimits = (pattern, date, forcedPattern) => { s: { min: 0, max: 59 }, S: { min: 0, max: 999 }, a: { min: 0, max: 1 }, + x: { min: 0, max: 0 }, // NOTE: Timezone part is read only. }; // @ts-expect-error return limits[forcedPattern || pattern] || limits.getAmPm; diff --git a/packages/devextreme/js/localization/ldml/date.parser.js b/packages/devextreme/js/localization/ldml/date.parser.js index 199685d749d3..b9ad3b6f3ca7 100644 --- a/packages/devextreme/js/localization/ldml/date.parser.js +++ b/packages/devextreme/js/localization/ldml/date.parser.js @@ -62,6 +62,9 @@ const PATTERN_REGEXPS = { }, w: function(count) { return count === 2 ? '[1-5][0-9]|0?[0-9]' : '0??[0-9]|[1-5][0-9]'; + }, + x: function(count) { + return count === 3 ? '[+-](?:2[0-3]|[01][0-9]):(?:[0-5][0-9])|Z' : '[+-](?:2[0-3]|[01][0-9])(?:[0-5][0-9])|Z'; } }; diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js index a0ffea2d6a74..9b1e917aa3b1 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js @@ -1266,6 +1266,40 @@ module('Date AM/PM Handling', setupModule, () => { }); }); +module('TimeZone Handling', setupModule, () => { + test('should support \'x\' in date pattern and not generate errors (T1241387)', function(assert) { + try { + this.instance.option({ + displayFormat: 'yyyy-MM-dd\'T\'HH:mm:ssxxx', + useMaskBehavior: true, + type: 'date', + }); + assert.ok(true, 'no error shown'); + } catch(e) { + assert.ok(false, 'error exists'); + } + }); + + test('should not show error when changing timezone on runtime via up/down buttons (T1241387)', function(assert) { + try { + this.instance.option({ + displayFormat: 'yyyy-MM-dd\'T\'HH:mm:ssxxx', + useMaskBehavior: true, + type: 'date', + }); + const oldValue = this.$input.val(); + this.keyboard.caret({ start: 20, end: 24 }); + this.$input.focus().trigger('dxclick'); + this.keyboard.press('up'); + + assert.ok(true, 'no error shown'); + assert.strictEqual(this.$input.val(), oldValue, 'value has not been modified'); + } catch(e) { + assert.ok(false, 'error exists'); + } + }); +}); + module('Empty dateBox', { beforeEach: function() { setupModule.beforeEach.call(this);