diff --git a/addons/calendar/static/tests/helpers/mock_server/models/res_users.js b/addons/calendar/static/tests/helpers/mock_server/models/res_users.js index 163f72ff321..bc35ddd3120 100644 --- a/addons/calendar/static/tests/helpers/mock_server/models/res_users.js +++ b/addons/calendar/static/tests/helpers/mock_server/models/res_users.js @@ -1,12 +1,12 @@ /** @odoo-module **/ // ensure mail override is applied first. -import '@mail/../tests/helpers/mock_server/models/res_users'; +import "@mail/../tests/helpers/mock_server/models/res_users"; import { patch } from "@web/core/utils/patch"; -import { MockServer } from '@web/../tests/helpers/mock_server'; - -import { datetime_to_str } from '@web/legacy/js/core/time'; +import { serializeDateTime } from "@web/core/l10n/dates"; +import { MockServer } from "@web/../tests/helpers/mock_server"; +const { DateTime } = luxon; patch(MockServer.prototype, { /** @@ -15,23 +15,35 @@ patch(MockServer.prototype, { * @private */ _mockResUsers_SystrayGetCalendarEventDomain() { - const startDate = new Date(); - startDate.setUTCHours(0, 0, 0, 0); - const endDate = new Date(); - endDate.setUTCHours(23, 59, 59, 999); - const currentPartnerAttendeeIds = this.pyEnv['calendar.attendee'].search([['partner_id', '=', this.pyEnv.currentPartnerId], ['state', '!=', 'declined']]); + const startDate = DateTime.fromObject({ + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0, + }); + const endDate = DateTime.fromObject({ + hours: 23, + minutes: 59, + seconds: 59, + milliseconds: 999, + }); + + const currentPartnerAttendeeIds = this.pyEnv["calendar.attendee"].search([ + ["partner_id", "=", this.pyEnv.currentPartnerId], + ["state", "!=", "declined"], + ]); return [ - '&', - '|', - '&', - '|', - ['start', '>=', datetime_to_str(startDate)], - ['stop', '>=', datetime_to_str(startDate)], - ['start', '<=', datetime_to_str(endDate)], - '&', - ['allday', '=', true], - ['start_date', '=', datetime_to_str(startDate)], - ['attendee_ids', 'in', currentPartnerAttendeeIds], + "&", + "|", + "&", + "|", + ["start", ">=", serializeDateTime(startDate)], + ["stop", ">=", serializeDateTime(startDate)], + ["start", "<=", serializeDateTime(endDate)], + "&", + ["allday", "=", true], + ["start_date", "=", serializeDateTime(startDate)], + ["attendee_ids", "in", currentPartnerAttendeeIds], ]; }, @@ -42,20 +54,20 @@ patch(MockServer.prototype, { */ _mockResUsersSystrayGetActivities() { const activities = super._mockResUsersSystrayGetActivities(...arguments); - const meetingsLines = this.pyEnv['calendar.event'].searchRead( + const meetingsLines = this.pyEnv["calendar.event"].searchRead( this._mockResUsers_SystrayGetCalendarEventDomain(), { - fields: ['id', 'start', 'name', 'allday'], - order: 'start', + fields: ["id", "start", "name", "allday"], + order: "start", } - ) + ); if (meetingsLines.length) { activities.unshift({ - id: 'calendar.event', // for simplicity + id: "calendar.event", // for simplicity meetings: meetingsLines, - model: 'calendar.event', - name: 'Today\'s Meetings', - type: 'meeting', + model: "calendar.event", + name: "Today's Meetings", + type: "meeting", }); } return activities; diff --git a/addons/mail/static/tests/activity/activity_tests.js b/addons/mail/static/tests/activity/activity_tests.js index 29a8804077f..68968dc3972 100644 --- a/addons/mail/static/tests/activity/activity_tests.js +++ b/addons/mail/static/tests/activity/activity_tests.js @@ -4,7 +4,7 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; import { start } from "@mail/../tests/helpers/test_utils"; -import { date_to_str } from "@web/legacy/js/core/time"; +import { serializeDate, today } from "@web/core/l10n/dates"; import { mockTimeout, patchDate, @@ -106,13 +106,10 @@ QUnit.test("activity with note layout", async () => { QUnit.test("activity info layout when planned after tomorrow", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const fiveDaysFromNow = new Date(); - fiveDaysFromNow.setDate(today.getDate() + 5); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(fiveDaysFromNow), + date_deadline: serializeDate(today().plus({ days: 5 })), res_id: partnerId, res_model: "res.partner", state: "planned", @@ -124,13 +121,11 @@ QUnit.test("activity info layout when planned after tomorrow", async () => { QUnit.test("activity info layout when planned tomorrow", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const tomorrow = new Date(); - tomorrow.setDate(today.getDate() + 1); + const tomorrow = today().plus({ days: 1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: partnerId, res_model: "res.partner", state: "planned", @@ -145,7 +140,7 @@ QUnit.test("activity info layout when planned today", async () => { const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(new Date()), + date_deadline: serializeDate(today()), res_id: partnerId, res_model: "res.partner", state: "today", @@ -157,13 +152,11 @@ QUnit.test("activity info layout when planned today", async () => { QUnit.test("activity info layout when planned yesterday", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const yesterday = new Date(); - yesterday.setDate(today.getDate() - 1); + const yesterday = today().plus({ days: -1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(yesterday), + date_deadline: serializeDate(yesterday), res_id: partnerId, res_model: "res.partner", state: "overdue", @@ -175,13 +168,10 @@ QUnit.test("activity info layout when planned yesterday", async () => { QUnit.test("activity info layout when planned before yesterday", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const fiveDaysBeforeNow = new Date(); - fiveDaysBeforeNow.setDate(today.getDate() - 5); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(fiveDaysBeforeNow), + date_deadline: serializeDate(today().plus({ days: -5 })), res_id: partnerId, res_model: "res.partner", state: "overdue", @@ -199,13 +189,11 @@ QUnit.test("activity info layout when planned before yesterday", async () => { QUnit.skip("activity info layout change at midnight", async () => { const mock = mockTimeout(); patchDate(2023, 11, 7, 23, 59, 59); - const today = new Date(); - const tomorrow = new Date(); - tomorrow.setDate(today.getDate() + 1); + const tomorrow = today().plus({ days: 1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: partnerId, res_model: "res.partner", state: "planned", @@ -247,16 +235,14 @@ QUnit.test("activity without summary layout", async () => { QUnit.test("activity details toggle", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const tomorrow = new Date(); - tomorrow.setDate(today.getDate() + 1); + const tomorrow = today().plus({ days: 1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); const userId = pyEnv["res.users"].create({ partner_id: partnerId }); pyEnv["mail.activity"].create({ - create_date: date_to_str(today), + create_date: serializeDate(today()), create_uid: userId, - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: partnerId, res_model: "res.partner", }); @@ -489,27 +475,24 @@ QUnit.test("activity mark done popover click on discard", async () => { QUnit.test("Activity are sorted by deadline", async () => { patchDate(2023, 0, 11, 12, 0, 0); - const today = new Date(); - const dateBefore = new Date(); - dateBefore.setDate(today.getDate() - 5); - const dateAfter = new Date(); - dateAfter.setDate(today.getDate() + 4); + const dateBefore = today().plus({ days: -5 }); + const dateAfter = today().plus({ days: 4 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(dateAfter), + date_deadline: serializeDate(dateAfter), res_id: partnerId, res_model: "res.partner", state: "planned", }); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(today), + date_deadline: serializeDate(today()), res_id: partnerId, res_model: "res.partner", state: "today", }); pyEnv["mail.activity"].create({ - date_deadline: date_to_str(dateBefore), + date_deadline: serializeDate(dateBefore), res_id: partnerId, res_model: "res.partner", state: "overdue", diff --git a/addons/mail/static/tests/helpers/mock_server/models/discuss_channel.js b/addons/mail/static/tests/helpers/mock_server/models/discuss_channel.js index 5fc1275a70f..afcff843c6a 100644 --- a/addons/mail/static/tests/helpers/mock_server/models/discuss_channel.js +++ b/addons/mail/static/tests/helpers/mock_server/models/discuss_channel.js @@ -3,9 +3,8 @@ import { patch } from "@web/core/utils/patch"; import { MockServer } from "@web/../tests/helpers/mock_server"; -import { datetime_to_str } from "@web/legacy/js/core/time"; import { assignDefined } from "@mail/utils/common/misc"; -import { formatDate } from "@web/core/l10n/dates"; +import { formatDate, serializeDateTime, today } from "@web/core/l10n/dates"; import { Command } from "@mail/../tests/helpers/command"; const { DateTime } = luxon; @@ -211,7 +210,7 @@ patch(MockServer.prototype, { ); if (memberOfCurrentUser) { this.pyEnv["discuss.channel.member"].write([memberOfCurrentUser.id], { - last_interest_dt: datetime_to_str(new Date()), + last_interest_dt: serializeDateTime(today()), is_pinned: true, }); diff --git a/addons/mail/static/tests/helpers/mock_server/models/mail_thread.js b/addons/mail/static/tests/helpers/mock_server/models/mail_thread.js index 0386c74be52..671efb90e05 100644 --- a/addons/mail/static/tests/helpers/mock_server/models/mail_thread.js +++ b/addons/mail/static/tests/helpers/mock_server/models/mail_thread.js @@ -3,7 +3,7 @@ import { patch } from "@web/core/utils/patch"; import { MockServer } from "@web/../tests/helpers/mock_server"; -import { datetime_to_str } from "@web/legacy/js/core/time"; +import { serializeDateTime, today } from "@web/core/l10n/dates"; patch(MockServer.prototype, { async _performRPC(route, args) { @@ -290,7 +290,7 @@ patch(MockServer.prototype, { const channels = this.getRecords("discuss.channel", [["id", "=", message.res_id]]); for (const channel of channels) { // notify update of last_interest_dt - const now = datetime_to_str(new Date()); + const now = serializeDateTime(today()); const members = this.getRecords("discuss.channel.member", [ ["id", "in", channel.channel_member_ids], ]); diff --git a/addons/mail/static/tests/helpers/mock_server/models/res_users.js b/addons/mail/static/tests/helpers/mock_server/models/res_users.js index b53f945f6c3..be6e0245141 100644 --- a/addons/mail/static/tests/helpers/mock_server/models/res_users.js +++ b/addons/mail/static/tests/helpers/mock_server/models/res_users.js @@ -1,7 +1,7 @@ /* @odoo-module */ import { patch } from "@web/core/utils/patch"; -import { date_to_str } from "@web/legacy/js/core/time"; +import { today, serializeDate } from "@web/core/l10n/dates"; import { MockServer } from "@web/../tests/helpers/mock_server"; patch(MockServer.prototype, { @@ -57,10 +57,10 @@ patch(MockServer.prototype, { const activities = this.pyEnv["mail.activity"].searchRead([]); const userActivitiesByModelName = {}; for (const activity of activities) { - const today = date_to_str(new Date()); - if (today === activity["date_deadline"]) { + const day = serializeDate(today()); + if (day === activity["date_deadline"]) { activity["states"] = "today"; - } else if (today > activity["date_deadline"]) { + } else if (day > activity["date_deadline"]) { activity["states"] = "overdue"; } else { activity["states"] = "planned"; diff --git a/addons/mrp_subcontracting/__manifest__.py b/addons/mrp_subcontracting/__manifest__.py index 75e2114fb97..994cb9998ff 100644 --- a/addons/mrp_subcontracting/__manifest__.py +++ b/addons/mrp_subcontracting/__manifest__.py @@ -97,7 +97,6 @@ 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', diff --git a/addons/project/__manifest__.py b/addons/project/__manifest__.py index 8aa52d9861a..911f8c5ad50 100644 --- a/addons/project/__manifest__.py +++ b/addons/project/__manifest__.py @@ -147,7 +147,6 @@ 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', ('include', 'web._assets_bootstrap_backend'), diff --git a/addons/project_todo/static/src/web/activity/activity_menu_patch.js b/addons/project_todo/static/src/web/activity/activity_menu_patch.js index 306f58040a5..23113c2f63d 100644 --- a/addons/project_todo/static/src/web/activity/activity_menu_patch.js +++ b/addons/project_todo/static/src/web/activity/activity_menu_patch.js @@ -11,6 +11,8 @@ import { useService } from "@web/core/utils/hooks"; import { patch } from "@web/core/utils/patch"; import { registry } from "@web/core/registry"; +const { DateTime } = luxon; + // Add a to-do category for the command palette registry.category("command_categories").add("to-do", {}, { sequence: 105 }); @@ -87,7 +89,6 @@ patch(ActivityMenu.prototype, { }, async saveTodo() { - const { DateTime } = luxon; const urlRegExp = /http(s)?:\/\/(www\.)?[a-zA-Z0-9@:%_+~#=~#?&/=\-;!.]{3,2000}/g; const todo = this.todoInputRef.el.value.replace(urlRegExp, '$&').trim(); if (!todo) { diff --git a/addons/project_todo/static/tests/activity_menu_tests.js b/addons/project_todo/static/tests/activity_menu_tests.js index d4d9c7f2030..3ba0469e7b6 100644 --- a/addons/project_todo/static/tests/activity_menu_tests.js +++ b/addons/project_todo/static/tests/activity_menu_tests.js @@ -5,6 +5,8 @@ import { start } from "@mail/../tests/helpers/test_utils"; import { editInput, patchDate } from "@web/../tests/helpers/utils"; import { click, contains, insertText } from "@web/../tests/utils"; +const { DateTime } = luxon; + QUnit.test("create todo from activity menu without date", async function () { await start(); await contains(".o_menu_systray i[aria-label='Activities']"); @@ -47,9 +49,7 @@ QUnit.test("create todo from activity menu without date", async function () { QUnit.test("create to-do from activity menu with date", async function () { patchDate(2023, 1, 1, 6, 0, 0); - const { DateTime } = luxon; - const today = DateTime.utc(); - const futureDay = today.plus({ days: 2 }); + const futureDay = DateTime.utc().plus({ days: 2 }); await start(); await contains(".o_menu_systray i[aria-label='Activities']"); await contains(".o-mail-ActivityMenu-counter", { count: 0 }); diff --git a/addons/project_todo/static/tests/helpers/mock_server/controller/project_todo.js b/addons/project_todo/static/tests/helpers/mock_server/controller/project_todo.js index c2ee33bd6da..e4d8fbefb55 100644 --- a/addons/project_todo/static/tests/helpers/mock_server/controller/project_todo.js +++ b/addons/project_todo/static/tests/helpers/mock_server/controller/project_todo.js @@ -1,9 +1,10 @@ /** @odoo-module **/ import { patch } from "@web/core/utils/patch"; +import { serializeDate } from "@web/core/l10n/dates"; import { MockServer } from '@web/../tests/helpers/mock_server'; -import { date_to_str } from '@web/legacy/js/core/time'; +const { DateTime } = luxon; patch(MockServer.prototype, { //-------------------------------------------------------------------------- @@ -33,7 +34,7 @@ patch(MockServer.prototype, { const taskId = this.pyEnv['project.task'].create({ description: values['todo_description'] }); if (values['date_deadline']) { this.pyEnv['mail.activity'].create({ - date_deadline: date_to_str(new Date(values['date_deadline'])), + date_deadline: serializeDate(DateTime.fromISO(values['date_deadline'])), note: values['todo_description'], res_model: 'project.task', res_id: taskId, diff --git a/addons/test_mail/static/tests/systray_activity_menu_tests.js b/addons/test_mail/static/tests/systray_activity_menu_tests.js index eff42cfd565..fa398e250af 100644 --- a/addons/test_mail/static/tests/systray_activity_menu_tests.js +++ b/addons/test_mail/static/tests/systray_activity_menu_tests.js @@ -4,7 +4,7 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; import { start } from "@mail/../tests/helpers/test_utils"; -import { date_to_str } from "@web/legacy/js/core/time"; +import { serializeDate, today } from "@web/core/l10n/dates"; import { session } from "@web/session"; import { patchWithCleanup } from "@web/../tests/helpers/utils"; import { click, contains } from "@web/../tests/utils"; @@ -26,13 +26,12 @@ QUnit.test("menu with no records", async () => { }); QUnit.test("do not show empty text when at least some future activities", async () => { - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); + const tomorrow = today().plus({ days: 1 }); const pyEnv = await startServer(); const activityId = pyEnv["mail.test.activity"].create({}); pyEnv["mail.activity"].create([ { - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: activityId, res_model: "mail.test.activity", }, @@ -46,10 +45,8 @@ QUnit.test("do not show empty text when at least some future activities", async }); QUnit.test("activity menu widget: activity menu with 2 models", async (assert) => { - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); + const tomorrow = today().plus({ days: 1 }); + const yesterday = today().plus({ days: -1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); const activityIds = pyEnv["mail.test.activity"].create([{}, {}, {}, {}]); @@ -57,17 +54,17 @@ QUnit.test("activity menu widget: activity menu with 2 models", async (assert) = { res_id: partnerId, res_model: "res.partner" }, { res_id: activityIds[0], res_model: "mail.test.activity" }, { - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: activityIds[1], res_model: "mail.test.activity", }, { - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: activityIds[2], res_model: "mail.test.activity", }, { - date_deadline: date_to_str(yesterday), + date_deadline: serializeDate(yesterday), res_id: activityIds[3], res_model: "mail.test.activity", }, @@ -116,10 +113,8 @@ QUnit.test("activity menu widget: activity menu with 2 models", async (assert) = }); QUnit.test("activity menu widget: activity view icon", async (assert) => { - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); + const tomorrow = today().plus({ days: 1 }); + const yesterday = today().plus({ days: -1 }); const pyEnv = await startServer(); const partnerId = pyEnv["res.partner"].create({}); const activityIds = pyEnv["mail.test.activity"].create([{}, {}, {}, {}]); @@ -127,17 +122,17 @@ QUnit.test("activity menu widget: activity view icon", async (assert) => { { res_id: partnerId, res_model: "res.partner" }, { res_id: activityIds[0], res_model: "mail.test.activity" }, { - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: activityIds[1], res_model: "mail.test.activity", }, { - date_deadline: date_to_str(tomorrow), + date_deadline: serializeDate(tomorrow), res_id: activityIds[2], res_model: "mail.test.activity", }, { - date_deadline: date_to_str(yesterday), + date_deadline: serializeDate(yesterday), res_id: activityIds[3], res_model: "mail.test.activity", }, diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index 8328d20a5ef..3d028b75cbe 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -99,7 +99,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', @@ -222,7 +221,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', diff --git a/addons/web/static/src/legacy/js/core/time.js b/addons/web/static/src/legacy/js/core/time.js deleted file mode 100644 index 647a70dc1e7..00000000000 --- a/addons/web/static/src/legacy/js/core/time.js +++ /dev/null @@ -1,305 +0,0 @@ -/** @odoo-module **/ - -import { localization } from "@web/core/l10n/localization"; -import { _t } from "@web/core/l10n/translation"; - -/** - * Left-pad provided arg 1 with zeroes until reaching size provided by second - * argument. - * - * @param {number|string} str value to pad - * @param {number} size size to reach on the final padded value - * @returns {string} padded string - */ -function lpad(str, size) { - str = "" + str; - return new Array(size - str.length + 1).join('0') + str; -} -/** - * @see lpad - * - * @param {string} str - * @param {number} size - * @returns {string} - */ -function rpad(str, size) { - str = "" + str; - return str + new Array(size - str.length + 1).join('0'); -} - -/** - * Replacer function for JSON.stringify, serializes Date objects to UTC - * datetime in the OpenERP Server format. - * - * However, if a serialized value has a toJSON method that method is called - * *before* the replacer is invoked. Date#toJSON exists, and thus the value - * passed to the replacer is a string, the original Date has to be fetched - * on the parent object (which is provided as the replacer's context). - * - * @param {String} k - * @param {Object} v - * @returns {Object} - */ -export function date_to_utc (k, v) { - var value = this[k]; - if (!(value instanceof Date)) { return v; } - - return datetime_to_str(value); -} - -/** - * Converts a string to a Date javascript object using OpenERP's - * datetime string format (exemple: '2011-12-01 15:12:35.832'). - * - * The time zone is assumed to be UTC (standard for OpenERP 6.1) - * and will be converted to the browser's time zone. - * - * @param {String} str A string representing a datetime. - * @returns {Date} - */ -export function str_to_datetime (str) { - if(!str) { - return str; - } - var regex = /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d(?:\.(\d+))?)$/; - var res = regex.exec(str); - if ( !res ) { - throw new Error("'" + str + "' is not a valid datetime"); - } - var tmp = new Date(2000,0,1); - tmp.setUTCMonth(1970); - tmp.setUTCMonth(0); - tmp.setUTCDate(1); - tmp.setUTCFullYear(parseFloat(res[1])); - tmp.setUTCMonth(parseFloat(res[2]) - 1); - tmp.setUTCDate(parseFloat(res[3])); - tmp.setUTCHours(parseFloat(res[4])); - tmp.setUTCMinutes(parseFloat(res[5])); - tmp.setUTCSeconds(parseFloat(res[6])); - tmp.setUTCSeconds(parseFloat(res[6])); - tmp.setUTCMilliseconds(parseFloat(rpad((res[7] || "").slice(0, 3), 3))); - return tmp; -} - -/** - * Converts a string to a Date javascript object using OpenERP's - * date string format (exemple: '2011-12-01'). - * - * As a date is not subject to time zones, we assume it should be - * represented as a Date javascript object at 00:00:00 in the - * time zone of the browser. - * - * @param {String} str A string representing a date. - * @returns {Date} - */ -export function str_to_date (str) { - if(!str) { - return str; - } - var regex = /^(\d\d\d\d)-(\d\d)-(\d\d)$/; - var res = regex.exec(str); - if ( !res ) { - throw new Error("'" + str + "' is not a valid date"); - } - var tmp = new Date(2000,0,1); - tmp.setFullYear(parseFloat(res[1])); - tmp.setMonth(parseFloat(res[2]) - 1); - tmp.setDate(parseFloat(res[3])); - tmp.setHours(0); - tmp.setMinutes(0); - tmp.setSeconds(0); - return tmp; -} - -/** - * Converts a string to a Date javascript object using OpenERP's - * time string format (exemple: '15:12:35'). - * - * The OpenERP times are supposed to always be naive times. We assume it is - * represented using a javascript Date with a date 1 of January 1970 and a - * time corresponding to the meant time in the browser's time zone. - * - * @param {String} str A string representing a time. - * @returns {Date} - */ -export function str_to_time (str) { - if(!str) { - return str; - } - var regex = /^(\d\d):(\d\d):(\d\d(?:\.(\d+))?)$/; - var res = regex.exec(str); - if ( !res ) { - throw new Error("'" + str + "' is not a valid time"); - } - var tmp = new Date(); - tmp.setFullYear(1970); - tmp.setMonth(0); - tmp.setDate(1); - tmp.setHours(parseFloat(res[1])); - tmp.setMinutes(parseFloat(res[2])); - tmp.setSeconds(parseFloat(res[3])); - tmp.setMilliseconds(parseFloat(rpad((res[4] || "").slice(0, 3), 3))); - return tmp; -} - -/** - * Converts a Date javascript object to a string using OpenERP's - * datetime string format (exemple: '2011-12-01 15:12:35'). - * - * The time zone of the Date object is assumed to be the one of the - * browser and it will be converted to UTC (standard for OpenERP 6.1). - * - * @param {Date} obj - * @returns {String} A string representing a datetime. - */ -export function datetime_to_str (obj) { - if (!obj) { - return false; - } - return lpad(obj.getUTCFullYear(),4) + "-" + lpad(obj.getUTCMonth() + 1,2) + "-" - + lpad(obj.getUTCDate(),2) + " " + lpad(obj.getUTCHours(),2) + ":" - + lpad(obj.getUTCMinutes(),2) + ":" + lpad(obj.getUTCSeconds(),2); -} - -/** - * Converts a Date javascript object to a string using OpenERP's - * date string format (exemple: '2011-12-01'). - * - * As a date is not subject to time zones, we assume it should be - * represented as a Date javascript object at 00:00:00 in the - * time zone of the browser. - * - * @param {Date} obj - * @returns {String} A string representing a date. - */ -export function date_to_str (obj) { - if (!obj) { - return false; - } - return lpad(obj.getFullYear(),4) + "-" + lpad(obj.getMonth() + 1,2) + "-" - + lpad(obj.getDate(),2); -} - -/** - * Converts a Date javascript object to a string using OpenERP's - * time string format (exemple: '15:12:35'). - * - * The OpenERP times are supposed to always be naive times. We assume it is - * represented using a javascript Date with a date 1 of January 1970 and a - * time corresponding to the meant time in the browser's time zone. - * - * @param {Date} obj - * @returns {String} A string representing a time. - */ -export function time_to_str (obj) { - if (!obj) { - return false; - } - return lpad(obj.getHours(),2) + ":" + lpad(obj.getMinutes(),2) + ":" - + lpad(obj.getSeconds(),2); -} - -export function auto_str_to_date (value) { - try { - return str_to_datetime(value); - } catch {} - try { - return str_to_date(value); - } catch {} - try { - return str_to_time(value); - } catch {} - throw new Error(_t("'%s' is not a correct date, datetime nor time", value)); -} - -export function auto_date_to_str (value, type) { - switch(type) { - case 'datetime': - return datetime_to_str(value); - case 'date': - return date_to_str(value); - case 'time': - return time_to_str(value); - default: - throw new Error(_t("'%s' is not convertible to date, datetime nor time", type)); - } -} - -const luxonToMomentFormatTable = { - c: "d", - d: "D", - o: "DDDD", - a: "A", - y: "Y", -}; - -function luxonToMomentFormat(format) { - return format.replace(/[a-zA-Z]/g, (match) => luxonToMomentFormatTable[match] || match); -} - -/** - * Get date format of the user's language - */ -export function getLangDateFormat() { - return luxonToMomentFormat(localization.dateFormat); -} - -/** - * Get time format of the user's language - */ -export function getLangTimeFormat() { - return luxonToMomentFormat(localization.timeFormat); -} - -/** - * Get date time format of the user's language - */ -export function getLangDatetimeFormat() { - return luxonToMomentFormat(localization.dateTimeFormat); -} - -const dateFormatWoZeroCache = {}; -/** - * Get date format of the user's language - allows non padded - */ -export function getLangDateFormatWoZero() { - const dateFormat = getLangDateFormat(); - if (!(dateFormat in dateFormatWoZeroCache)) { - dateFormatWoZeroCache[dateFormat] = dateFormat - .replace('MM', 'M') - .replace('DD', 'D'); - } - return dateFormatWoZeroCache[dateFormat]; -} - -const timeFormatWoZeroCache = {}; -/** - * Get time format of the user's language - allows non padded - */ -export function getLangTimeFormatWoZero() { - const timeFormat = getLangTimeFormat(); - if (!(timeFormat in timeFormatWoZeroCache)) { - timeFormatWoZeroCache[timeFormat] = timeFormat - .replace('HH', 'H') - .replace('mm', 'm') - .replace('ss', 's'); - } - return timeFormatWoZeroCache[timeFormat]; -} - -export default { - date_to_utc: date_to_utc, - str_to_datetime: str_to_datetime, - str_to_date: str_to_date, - str_to_time: str_to_time, - datetime_to_str: datetime_to_str, - date_to_str: date_to_str, - time_to_str: time_to_str, - auto_str_to_date: auto_str_to_date, - auto_date_to_str: auto_date_to_str, - getLangDateFormat: getLangDateFormat, - getLangTimeFormat: getLangTimeFormat, - getLangDateFormatWoZero: getLangDateFormatWoZero, - getLangTimeFormatWoZero: getLangTimeFormatWoZero, - getLangDatetimeFormat: getLangDatetimeFormat, -}; diff --git a/addons/web/static/tests/legacy/core/time_tests.js b/addons/web/static/tests/legacy/core/time_tests.js deleted file mode 100644 index 8e772606152..00000000000 --- a/addons/web/static/tests/legacy/core/time_tests.js +++ /dev/null @@ -1,163 +0,0 @@ -/** @odoo-module **/ - -import { strftimeToLuxonFormat } from "@web/core/l10n/dates"; -import { localization } from "@web/core/l10n/localization"; -import time from "@web/legacy/js/core/time"; - -QUnit.module('core', {}, function () { - - QUnit.module('Time utils'); - - QUnit.test('Parse server datetime', function (assert) { - assert.expect(4); - - var date = time.str_to_datetime("2009-05-04 12:34:23"); - assert.deepEqual( - [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), - date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()], - [2009, 5 - 1, 4, 12, 34, 23]); - assert.deepEqual( - [date.getFullYear(), date.getMonth(), date.getDate(), - date.getHours(), date.getMinutes(), date.getSeconds()], - [2009, 5 - 1, 4, 12 - (date.getTimezoneOffset() / 60), 34, 23]); - - var date2 = time.str_to_datetime('2011-12-10 00:00:00'); - assert.deepEqual( - [date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate(), - date2.getUTCHours(), date2.getUTCMinutes(), date2.getUTCSeconds()], - [2011, 12 - 1, 10, 0, 0, 0]); - - var date3 = time.str_to_datetime("2009-05-04 12:34:23.84565"); - assert.deepEqual( - [date3.getUTCFullYear(), date3.getUTCMonth(), date3.getUTCDate(), - date3.getUTCHours(), date3.getUTCMinutes(), date3.getUTCSeconds(), date3.getUTCMilliseconds()], - [2009, 5 - 1, 4, 12, 34, 23, 845]); - }); - - QUnit.test('Parse server datetime on 31', function (assert) { - assert.expect(1); - - var wDate = window.Date; - - try { - window.Date = function (v) { - if (typeof v === "undefined") { - v = '2013-10-31 12:34:56'; - } - return new wDate(v); - }; - var date = time.str_to_datetime('2013-11-11 02:45:21'); - - assert.deepEqual( - [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), - date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()], - [2013, 11 - 1, 11, 2, 45, 21]); - } - finally { - window.Date = wDate; - } - }); - - QUnit.test('Parse server date', function (assert) { - assert.expect(1); - - var date = time.str_to_date("2009-05-04"); - assert.deepEqual( - [date.getFullYear(), date.getMonth(), date.getDate()], - [2009, 5 - 1, 4]); - }); - - QUnit.test('Parse server date on 31', function (assert) { - assert.expect(1); - - var wDate = window.Date; - - try { - window.Date = function (v) { - if (typeof v === "undefined") { - v = '2013-10-31 12:34:56'; - } - return new wDate(v); - }; - var date = time.str_to_date('2013-11-21'); - - assert.deepEqual( - [date.getFullYear(), date.getMonth(), date.getDate()], - [2013, 11 - 1, 21]); - } - finally { - window.Date = wDate; - } - }); - - QUnit.test('Parse server time', function (assert) { - assert.expect(2); - - var date = time.str_to_time("12:34:23"); - assert.deepEqual( - [date.getHours(), date.getMinutes(), date.getSeconds()], - [12, 34, 23]); - - date = time.str_to_time("12:34:23.5467"); - assert.deepEqual( - [date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()], - [12, 34, 23, 546]); - }); - - QUnit.test('Format server datetime', function (assert) { - assert.expect(1); - - var date = new Date(); - date.setUTCFullYear(2009); - date.setUTCMonth(5 - 1); - date.setUTCDate(4); - date.setUTCHours(12); - date.setUTCMinutes(34); - date.setUTCSeconds(23); - assert.strictEqual(time.datetime_to_str(date), "2009-05-04 12:34:23"); - }); - - QUnit.test('Format server date', function (assert) { - assert.expect(1); - - var date = new Date(); - date.setUTCFullYear(2009); - date.setUTCMonth(5 - 1); - date.setUTCDate(4); - date.setUTCHours(0); - date.setUTCMinutes(0); - date.setUTCSeconds(0); - assert.strictEqual(time.date_to_str(date), "2009-05-04"); - }); - - QUnit.test('Format server time', function (assert) { - assert.expect(1); - - var date = new Date(); - date.setUTCFullYear(1970); - date.setUTCMonth(1 - 1); - date.setUTCDate(1); - date.setUTCHours(0); - date.setUTCMinutes(0); - date.setUTCSeconds(0); - date.setHours(12); - date.setMinutes(34); - date.setSeconds(23); - assert.strictEqual(time.time_to_str(date), "12:34:23"); - }); - - QUnit.test("Get lang datetime format", (assert) => { - assert.expect(4); - const originalParameters = Object.assign({}, localization); - Object.assign(localization, { - dateFormat: strftimeToLuxonFormat('%m/%d/%Y'), - timeFormat: strftimeToLuxonFormat('%H:%M:%S'), - }); - assert.strictEqual(time.getLangDateFormat(), "MM/DD/YYYY"); - assert.strictEqual(time.getLangDateFormatWoZero(), "M/D/YYYY"); - assert.strictEqual(time.getLangTimeFormat(), "HH:mm:ss"); - assert.strictEqual(time.getLangTimeFormatWoZero(), "H:m:s"); - Object.assign(localization, originalParameters); - }); - -}); diff --git a/addons/web_editor/__manifest__.py b/addons/web_editor/__manifest__.py index e0a4c581335..fb89fb3b92a 100644 --- a/addons/web_editor/__manifest__.py +++ b/addons/web_editor/__manifest__.py @@ -86,7 +86,6 @@ Odoo Web Editor widget. 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', ('include', 'web_editor.assets_wysiwyg'), diff --git a/addons/website_slides/__manifest__.py b/addons/website_slides/__manifest__.py index 84067591aa8..d7d6b72720c 100644 --- a/addons/website_slides/__manifest__.py +++ b/addons/website_slides/__manifest__.py @@ -187,7 +187,6 @@ Featuring 'web/static/src/legacy/js/core/dom.js', 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/time.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', 'web/static/src/core/**/*.js', diff --git a/addons/website_slides/static/src/js/slides.js b/addons/website_slides/static/src/js/slides.js index 1a959b2a6e2..964eebfcd10 100644 --- a/addons/website_slides/static/src/js/slides.js +++ b/addons/website_slides/static/src/js/slides.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import publicWidget from '@web/legacy/js/public/public_widget'; -import time from '@web/legacy/js/core/time'; +import { deserializeDateTime } from "@web/core/l10n/dates"; const { DateTime } = luxon; publicWidget.registry.websiteSlides = publicWidget.Widget.extend({ @@ -16,7 +16,7 @@ publicWidget.registry.websiteSlides = publicWidget.Widget.extend({ $("timeago.timeago").toArray().forEach((el) => { var datetime = $(el).attr('datetime'); - var datetimeObj = time.str_to_datetime(datetime); + var datetimeObj = deserializeDateTime(datetime); // if presentation 7 days, 24 hours, 60 min, 60 second, 1000 millis old(one week) // then return fix formate string else timeago var displayStr = '';