diff --git a/addons/hr_holidays/models/resource.py b/addons/hr_holidays/models/resource.py
index 9cb072b27bf2d5ee2a67e282f5d8b5a5d2e4b4d3..8c400744fc84a49464a261713b6ce5333cd0179c 100644
--- a/addons/hr_holidays/models/resource.py
+++ b/addons/hr_holidays/models/resource.py
@@ -4,6 +4,8 @@
 from odoo import fields, models, api, _
 from odoo.exceptions import ValidationError
 from odoo.osv import expression
+import pytz
+from datetime import datetime
 
 class CalendarLeaves(models.Model):
     _inherit = "resource.calendar.leaves"
@@ -80,8 +82,56 @@ class CalendarLeaves(models.Model):
 
         leaves_to_cancel._force_cancel(_("a new public holiday completely overrides this leave."), 'mail.mt_comment')
 
+    def _convert_timezone(self, utc_naive_datetime, tz_from, tz_to):
+        """
+            Convert a naive date to another timezone that initial timezone
+            used to generate the date.
+            :param utc_naive_datetime: utc date without tzinfo
+            :type utc_naive_datetime: datetime
+            :param tz_from: timezone used to obtained `utc_naive_datetime`
+            :param tz_to: timezone in which we want the date
+            :return: datetime converted into tz_to without tzinfo
+            :rtype: datetime
+        """
+        naive_datetime_from = utc_naive_datetime.astimezone(tz_from).replace(tzinfo=None)
+        aware_datetime_to = tz_to.localize(naive_datetime_from)
+        utc_naive_datetime_to = aware_datetime_to.astimezone(pytz.utc).replace(tzinfo=None)
+        return utc_naive_datetime_to
+
+    def _ensure_datetime(self, datetime_representation, date_format=None):
+        """
+            Be sure to get a datetime object if we have the necessary information.
+            :param datetime_reprentation: object which should represent a datetime
+            :rtype: datetime if a correct datetime_represtion, None otherwise
+        """
+        if isinstance(datetime_representation, datetime):
+            return datetime_representation
+        elif isinstance(datetime_representation, str) and date_format:
+            return datetime.strptime(datetime_representation, date_format)
+        else:
+            return None
+
+    def _prepare_public_holidays_values(self, vals_list):
+        for vals in vals_list:
+            # Manage the case of create a Public Time Off in another timezone
+            # The datetime created has to be in UTC for the calendar's timezone
+            if not vals.get('calendar_id') or vals.get('resource_id') or \
+                not isinstance(vals.get('date_from'), (datetime, str)) or \
+                not isinstance(vals.get('date_to'), (datetime, str)):
+                continue
+            user_tz = pytz.timezone(self.env.user.tz) if self.env.user.tz else pytz.utc
+            calendar_tz = pytz.timezone(self.env['resource.calendar'].browse(vals['calendar_id']).tz)
+            if user_tz != calendar_tz:
+                datetime_from = self._ensure_datetime(vals['date_from'], '%Y-%m-%d %H:%M:%S')
+                datetime_to = self._ensure_datetime(vals['date_to'], '%Y-%m-%d %H:%M:%S')
+                if datetime_from and datetime_to:
+                    vals['date_from'] = self._convert_timezone(datetime_from, user_tz, calendar_tz)
+                    vals['date_to'] = self._convert_timezone(datetime_to, user_tz, calendar_tz)
+        return vals_list
+
     @api.model_create_multi
     def create(self, vals_list):
+        vals_list = self._prepare_public_holidays_values(vals_list)
         res = super().create(vals_list)
         time_domain_dict = res._get_time_domain_dict()
         self._reevaluate_leaves(time_domain_dict)
diff --git a/addons/hr_holidays/tests/test_global_leaves.py b/addons/hr_holidays/tests/test_global_leaves.py
index fc57e08556037509f3ffbe2a8997010787c6afc0..ef1c8d5a4d3bf8aa95568ffa8e4355e6824d74f8 100644
--- a/addons/hr_holidays/tests/test_global_leaves.py
+++ b/addons/hr_holidays/tests/test_global_leaves.py
@@ -1,9 +1,10 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
-from datetime import date
+from datetime import date, datetime
 from odoo.addons.hr_holidays.tests.common import TestHrHolidaysCommon
 from odoo.exceptions import ValidationError
+from freezegun import freeze_time
 
 from odoo.tests import tagged
 
@@ -96,3 +97,31 @@ class TestGlobalLeaves(TestHrHolidaysCommon):
                 'date_to': date(2022, 3, 8),
                 'calendar_id': self.calendar_1.id,
             })
+
+    @freeze_time('2023-05-12')
+    def test_global_leave_timezone(self):
+        """
+            It is necessary to use the timezone of the calendar
+            for the global leaves (without resource).
+        """
+        calendar_asia = self.env['resource.calendar'].create({
+            'name': 'Asia calendar',
+            'tz': 'Asia/Calcutta', # UTC +05:30
+            'hours_per_day': 8.0,
+            'attendance_ids': []
+        })
+        self.env.user.tz = 'Europe/Brussels'
+        global_leave = self.env['resource.calendar.leaves'].with_user(self.env.user).create({
+            'name': 'Public holiday',
+            'date_from': "2023-05-15 06:00:00", # utc from 8:00:00 for Europe/Brussels (UTC +02:00)
+            'date_to': "2023-05-15 15:00:00", # utc from 17:00:00 for Europe/Brussels (UTC +02:00)
+            'calendar_id': calendar_asia.id,
+        })
+        # Expectation:
+        # 6:00:00 in UTC (data from the browser) --> 8:00:00 for Europe/Brussel (UTC +02:00)
+        # 8:00:00 for Asia/Calcutta (UTC +05:30) --> 2:30:00 in UTC
+        self.assertEqual(global_leave.date_from, datetime(2023, 5, 15, 2, 30))
+        self.assertEqual(global_leave.date_to, datetime(2023, 5, 15, 11, 30))
+        # Note:
+        # The user in Europe/Brussels timezone see 4:30 and not 2:30 because he is in UTC +02:00.
+        # The user in Asia/Calcutta timezone (determined via the browser) see 8:00 because he is in UTC +05:30