diff --git a/addons/web/static/src/core/datepicker/datepicker.js b/addons/web/static/src/core/datepicker/datepicker.js index 8db30ea4929..c66fefd9363 100644 --- a/addons/web/static/src/core/datepicker/datepicker.js +++ b/addons/web/static/src/core/datepicker/datepicker.js @@ -4,6 +4,7 @@ import { areDateEquals, formatDate, formatDateTime, + luxonToMomentFormat, parseDate, parseDateTime, } from "@web/core/l10n/dates"; @@ -33,14 +34,6 @@ function luxonDateToMomentDate(date) { return window.moment(String(date)); } -/** - * @param {string} format - * @returns {string} - */ -function luxonFormatToMomentFormat(format) { - return format.replace(/[dy]/g, (x) => x.toUpperCase()); -} - /** * @param {string} format * @returns {boolean} @@ -198,7 +191,7 @@ export class DatePicker extends Component { const params = { ...commandOrParams, date: this.date || null, - format: luxonFormatToMomentFormat(format), + format: luxonToMomentFormat(format), locale: commandOrParams.locale || (this.date && this.date.locale), }; for (const prop in params) { diff --git a/addons/web/static/src/core/l10n/dates.js b/addons/web/static/src/core/l10n/dates.js index d2efb6dc443..78bd7175c15 100644 --- a/addons/web/static/src/core/l10n/dates.js +++ b/addons/web/static/src/core/l10n/dates.js @@ -44,6 +44,14 @@ const normalizeFormatTable = { X: "HH:mm:ss", }; +const luxonToMomentFormatTable = { + c: "d", + d: "D", + o: "DDDD", + a: "A", + y: "Y", +}; + const smartDateUnits = { d: "days", m: "months", @@ -143,6 +151,19 @@ export const strftimeToLuxonFormat = memoize(function strftimeToLuxonFormat(valu return output.join(""); }); +/** + * Converts a Luxon format to a moment.js format. + * NB: this is not a complete conversion, only the supported tokens are converted. + * + * @param {string} value original format + * @returns {string} valid moment.js format + */ +export const luxonToMomentFormat = memoize(function luxonToMomentFormat(format) { + return format.replace(alphaRegex, (match) => { + return luxonToMomentFormatTable[match] || match; + }); +}); + // ----------------------------------------------------------------------------- // Formatting // ----------------------------------------------------------------------------- diff --git a/addons/web/static/src/views/fields/daterange/daterange_field.js b/addons/web/static/src/views/fields/daterange/daterange_field.js index 5ffe6886baa..89e70cc74f1 100644 --- a/addons/web/static/src/views/fields/daterange/daterange_field.js +++ b/addons/web/static/src/views/fields/daterange/daterange_field.js @@ -3,6 +3,7 @@ import { localization } from "@web/core/l10n/localization"; import { registry } from "@web/core/registry"; import { loadJS } from "@web/core/assets"; +import { luxonToMomentFormat } from "@web/core/l10n/dates"; import { useService } from "@web/core/utils/hooks"; import { standardFieldProps } from "../standard_field_props"; @@ -16,6 +17,9 @@ export class DateRangeField extends Component { this.root = useRef("root"); this.isPickerShown = false; this.pickerContainer; + this.momentFormat = luxonToMomentFormat( + this.isDateTime ? localization.dateTimeFormat : localization.dateFormat + ); useExternalListener(window, "scroll", this.onWindowScroll, { capture: true }); onWillStart(() => loadJS("/web/static/lib/daterangepicker/daterangepicker.js")); @@ -32,9 +36,6 @@ export class DateRangeField extends Component { locale: { applyLabel: this.env._t("Apply"), cancelLabel: this.env._t("Cancel"), - format: this.isDateTime - ? localization.dateTimeFormat - : localization.dateFormat, }, startDate: start ? window.moment(start) : window.moment(), endDate: end ? window.moment(end) : window.moment(), @@ -126,10 +127,9 @@ export class DateRangeField extends Component { async onPickerApply(ev, picker) { const start = this.isDateTime ? picker.startDate : picker.startDate.startOf("day"); const end = this.isDateTime ? picker.endDate : picker.endDate.startOf("day"); - const format = this.isDateTime ? localization.dateTimeFormat : localization.dateFormat; const parser = parsers.get(this.props.formatType); const dates = [start, end].map((date) => { - return parser(date.format(format.toUpperCase()), { + return parser(date.format(this.momentFormat), { timezone: this.isDateTime, }); }); diff --git a/addons/web/static/tests/views/fields/daterange_field_tests.js b/addons/web/static/tests/views/fields/daterange_field_tests.js index 674f2a5f2f5..b3e83d7fa2e 100644 --- a/addons/web/static/tests/views/fields/daterange_field_tests.js +++ b/addons/web/static/tests/views/fields/daterange_field_tests.js @@ -191,6 +191,27 @@ QUnit.module("Fields", (hooks) => { "30", "active end date minute should be '30' in date range picker" ); + + // Select a new range and check that inputs are updated + await triggerEvent(datepicker, ".start-date", "mousedown"); // 02/08/2017 + await triggerEvent(datepicker, ".start-date + .available", "mousedown"); // 02/09/2017 + await click(datepicker, ".applyBtn"); + assert.equal( + target.querySelector("[name=datetime] input").value, + "02/08/2017 15:30:00" + ); + assert.equal( + target.querySelector("[name=datetime_end] input").value, + "02/09/2017 05:30:00" + ); + + // Save + await click(target, ".o_form_button_save"); + fields = target.querySelectorAll(".o_field_daterange"); + + // Check date after save + assert.strictEqual(fields[0].textContent, "02/08/2017 15:30:00"); + assert.strictEqual(fields[fields.length - 1].textContent, "02/09/2017 05:30:00"); } );