I have created a module which overwrites some functions on leaves management. This function includes getting employee working schedule from contract and calculating leave length based on the contract (In my company there can be leaves that are less than one day) the times provided by working schedule are just in format: {'time_from': 8.00, 'time_to':18:00} so they don't include any kind of timezone information however dates are transformed into utc time when they are inserted to db and when you compare those times with working schedule times you need to correct timezone to user's timezone.
My code is like this and as you see there is three places where 8 is added on dates to fix this timezone problem which is fine now when our openerp is used in utc+8 but in future we plan to enable using our system outside of our LAN and then there may be people located in different timezones using it so this fix won't help in future:
def _get_number_of_days(self, date_from, date_to, cr, uid, ids, employee_id):
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
date_from = datetime.datetime.strptime(date_from, DATETIME_FORMAT)
date_to = datetime.datetime.strptime(date_to, DATETIME_FORMAT)
timedelta = date_to - date_from
working_shift = 86400
diff_day = float();
if timedelta.days > 1:
diff_day += timedelta.days - 1
if(employee_id):
contract_pool = self.pool.get('hr.contract')
active_contract_ids= contract_pool.search(cr, uid, [
'&',
('employee_id', '=', employee_id),
'|',
'&',
('date_start', '<=', date_to),
'|',
('date_end', '>=', date_to),
('date_end', '=', False),
'&',
'|',
('trial_date_start', '=', False),
('trial_date_start', '<=', date_to),
'|',
('trial_date_end', '=', False),
('trial_date_end', '>=', date_to),
])
if active_contract_ids:
contract = contract_pool.browse(cr, uid, active_contract_ids[0])
cr.execute("select hour_from, hour_to from resource_calendar_attendance where calendar_id = %s and dayofweek = %s order by hour_from;", (contract.working_hours.id, str(date_from.isoweekday())))
start_timetable = cr.dictfetchall()
if start_timetable:
start_working_shift = self.pool.get('resource.calendar').working_hours_on_day(cr, uid, contract.working_hours, date_from)
if start_working_shift:
# add 8 hours to fix timezone
start_time = date_from.hour + 8 + float(date_from.minute)/60
if date_to.date() == date_from.date():
# add 8 hours to fix timezone
end_time = date_to.hour + 8 + float(date_to.minute)/60
if start_time < start_timetable[0]['hour_from'] and end_time > start_timetable[len(start_timetable) - 1]['hour_to']:
# leave length is one day because it starts before starting hour and ends after ending hour
return 1
else:
hours = self._calculate_hours_for_working_day(start_timetable, start_time, end_time)
return hours / start_working_shift
if start_time < start_timetable[0]['hour_from']:
# leave length is one day because it starts before starting hour and ends after ending hour
diff_day += 1
else:
end_time = float(start_timetable[len(start_timetable) - 1]['hour_to'])
hours = self._calculate_hours_for_working_day(start_timetable, start_time, end_time)
diff_day += hours / start_working_shift
cr.execute("select hour_from, hour_to from resource_calendar_attendance where calendar_id = %s and dayofweek = %s order by hour_from;", (contract.working_hours.id, str(date_to.isoweekday())))
end_timetable = cr.dictfetchall()
if end_timetable:
end_working_shift = self.pool.get('resource.calendar').working_hours_on_day(cr, uid, contract.working_hours, date_to)
if end_working_shift:
start_time = float(end_timetable[0]['hour_from'])
# add 8 hours to fix timezone
end_time = date_to.hour + 8 + float(date_to.minute)/60
if end_time > start_timetable[len(start_timetable) - 1]['hour_to']:
# leave length is one day because it starts before starting hour and ends after ending hour
diff_day += 1
else:
hours = self._calculate_hours_for_working_day(end_timetable, start_time, end_time)
diff_day += hours / end_working_shift
else:
# tell user that employee don't have contract so leaves can't be calculated
raise osv.except_osv(_('Error'), _('Employee doesn\'t have contract. Leave request can\'t be done.'))
else:
diff_day = timedelta.days + float(timedelta.seconds) / working_shift
return diff_day
Tried to fix this by adding parameter context for onchange function of the date selection and using pytz to transform these times to right timezone:
active_tz = pytz.timezone(context.get("tz","UTC")
this did not work (found this solution from another module but well as their module didn't work properly either it's not too big surprise that this did not work).