diff --git a/addons/web/static/lib/tempusdominus/tempusdominus.js b/addons/web/static/lib/tempusdominus/tempusdominus.js index bcda3437db259e8d7a7fbbc549aa45a03a5d399a..df1c51fdc9a189c6e339b0cbc0f6ffee91d511ad 100644 --- a/addons/web/static/lib/tempusdominus/tempusdominus.js +++ b/addons/web/static/lib/tempusdominus/tempusdominus.js @@ -802,17 +802,22 @@ var DateTimePicker = function ($, moment) { //public - DateTimePicker.prototype.getMoment = function getMoment(d) { + DateTimePicker.prototype.getMoment = function getMoment(d, f) { // ODOO FIX: give optional format var returnMoment = void 0; + // ODOO FIX: default to original `parseFormats` attribute + if (!f) { + f = this.parseFormats; + } + if (d === undefined || d === null) { returnMoment = moment(); //TODO should this use format? and locale? } else if (this._hasTimeZone()) { // There is a string to parse and a default time zone // parse with the tz function which takes a default time zone if it is not in the format string - returnMoment = moment.tz(d, this.parseFormats, this._options.locale, this._options.useStrict, this._options.timeZone); + returnMoment = moment.tz(d, f, this._options.locale, this._options.useStrict, this._options.timeZone); // ODOO FIX: use format argument } else { - returnMoment = moment(d, this.parseFormats, this._options.locale, this._options.useStrict); + returnMoment = moment(d, f, this._options.locale, this._options.useStrict); // ODOO FIX: use format argument } if (this._hasTimeZone()) { @@ -2434,7 +2439,7 @@ var TempusDominusBootstrap4 = function ($) { break; case 'selectHour': { - var hour = parseInt($(e.target).text(), 10); + var hour = this.getMoment($(e.target).text(), this.use24Hours ? 'HH' : 'hh').hour(); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers) if (!this.use24Hours) { if (lastPicked.hours() >= 12) { @@ -2456,7 +2461,7 @@ var TempusDominusBootstrap4 = function ($) { break; } case 'selectMinute': - this._setValue(lastPicked.clone().minutes(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex()); + this._setValue(lastPicked.clone().minutes(this.getMoment($(e.target).text(), 'mm').minute()), this._getLastPickedDateIndex()); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers) if (!this._isEnabled('a') && !this._isEnabled('s') && !this._options.keepOpen && !this._options.inline) { this.hide(); } else { @@ -2464,7 +2469,7 @@ var TempusDominusBootstrap4 = function ($) { } break; case 'selectSecond': - this._setValue(lastPicked.clone().seconds(parseInt($(e.target).text(), 10)), this._getLastPickedDateIndex()); + this._setValue(lastPicked.clone().seconds(this.getMoment($(e.target).text(), 'ss').second()), this._getLastPickedDateIndex()); // ODOO FIX: use moment format to get the proper value (not necessarily latn numbers) if (!this._isEnabled('a') && !this._options.keepOpen && !this._options.inline) { this.hide(); } else { diff --git a/addons/web/static/tests/legacy/fields/basic_fields_tests.js b/addons/web/static/tests/legacy/fields/basic_fields_tests.js index 29b81aa21eec1a3968eed3d8fcfda4ac96ded346..4334825701a6611b34c0d167420cff203daabb45 100644 --- a/addons/web/static/tests/legacy/fields/basic_fields_tests.js +++ b/addons/web/static/tests/legacy/fields/basic_fields_tests.js @@ -5362,6 +5362,75 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test("datetime field: use picker with arabic numbering system", async function (assert) { + assert.expect(2); + + const symbols = [ + ["1", "١"], + ["2", "٢"], + ["3", "٣"], + ["4", "٤"], + ["5", "٥"], + ["6", "٦"], + ["7", "٧"], + ["8", "٨"], + ["9", "٩"], + ["0", "٠"], + ]; + const symbolMap = Object.fromEntries(symbols); + const numberMap = Object.fromEntries(symbols.map(([latn, arab]) => [arab, latn])); + + const originalLocale = moment.locale(); + moment.defineLocale("TEST_ar", { + preparse: + (string) => string + .replace(/\u200f/g, "") + .replace(/[١٢٣٤٥٦٧٨٩٠]/g, (match) => numberMap[match]) + .replace(/،/g, ","), + postformat: + (string) => string + .replace(/\d/g, (match) => symbolMap[match]) + .replace(/,/g, "،"), + }); + + const form = await createView({ + View: FormView, + model: "partner", + data: this.data, + arch: /* xml */ ` + <form string="Partners"> + <field name="datetime" /> + </form> + `, + res_id: 1, + viewOptions: { + mode: "edit", + }, + }); + + const getInput = () => form.el.querySelector("[name=datetime] input") + const click = (el) => testUtils.dom.click($(el)); + + assert.strictEqual(getInput().value, "٠٢/٠٨/٢٠١٧ ١٠:٠٠:٠٠"); + + await click(getInput()); + + await click(document.querySelector("[data-action=togglePicker]")); + + await click(document.querySelector("[data-action=showMinutes]")); + await click(document.querySelectorAll("[data-action=selectMinute]")[9]); + + await click(document.querySelector("[data-action=showSeconds]")); + await click(document.querySelectorAll("[data-action=selectSecond]")[3]); + + assert.strictEqual(getInput().value, "٠٢/٠٨/٢٠١٧ ١٠:٤٥:١٥"); + + moment.locale(originalLocale); + moment.updateLocale("TEST_ar", null); + + form.destroy(); + }) + QUnit.module('RemainingDays'); QUnit.test('remaining_days widget on a date field in list view', async function (assert) {