def get_duration(self, instance): try: employment = Employment.objects.get_at(instance.user, instance.date) except Employment.DoesNotExist: # absence is invalid if no employment exists on absence date return duration_string(timedelta()) return duration_string(instance.calculate_duration(employment))
def test_user_worktime_balance(self): """Should calculate correct worktime balances.""" user = self.user employment = user.employments.get(end_date__isnull=True) # Calculate over one week start_date = date(2017, 3, 19) end_date = date(2017, 3, 26) employment.start_date = start_date employment.worktime_per_day = timedelta(hours=8) employment.save() # Overtime credit of 10 hours OvertimeCreditFactory.create(user=user, date=start_date, duration=timedelta(hours=10, minutes=30)) # One public holiday during workdays PublicHolidayFactory.create(date=start_date, location=employment.location) # One public holiday on weekend PublicHolidayFactory.create(date=start_date + timedelta(days=1), location=employment.location) url = reverse('user-detail', args=[user.id]) res = self.client.get('{0}?until={1}'.format( url, end_date.strftime('%Y-%m-%d'))) result = self.result(res) # 5 workdays minus one holiday minus 10 hours overtime credit expected_worktime = (4 * employment.worktime_per_day - timedelta(hours=10, minutes=30)) assert (result['data']['attributes']['worktime-balance'] == duration_string(timedelta() - expected_worktime)) # 2x 10 hour reported worktime ReportFactory.create(user=user, date=start_date + timedelta(days=3), duration=timedelta(hours=10)) ReportFactory.create(user=user, date=start_date + timedelta(days=4), duration=timedelta(hours=10)) AbsenceFactory.create(user=user, date=start_date + timedelta(days=5)) res2 = self.client.get('{0}?until={1}'.format( url, end_date.strftime('%Y-%m-%d'))) result2 = self.result(res2) assert (result2['data']['attributes']['worktime-balance'] == duration_string(timedelta(hours=28) - expected_worktime))
def get_mark(self, episode): mark = duration_string(datetime.timedelta(seconds=0)) request = self.context.get('request', None) if request is not None: try: if request.user.is_authenticated(): receipt = EpisodeReceipt.objects.get(episode=episode.pk, user=request.user) mark = duration_string(receipt.mark) except ObjectDoesNotExist: pass return mark
def get_root_meta(self, resource, many): if not many: queryset = Report.objects.filter(task__project=self.instance) data = queryset.aggregate(spent_time=Sum("duration")) data["spent_time"] = duration_string(data["spent_time"] or timedelta(0)) billable_data = queryset.filter( not_billable=False, review=False).aggregate(spent_billable=Sum("duration")) data["spent_billable"] = duration_string( billable_data["spent_billable"] or timedelta(0)) return data return {}
def test_worktime_balance_with_employments(auth_client, django_assert_num_queries): # Calculate over one week start_date = date(2017, 3, 19) end_date = date(2017, 3, 26) employment = EmploymentFactory.create(user=auth_client.user, start_date=start_date, worktime_per_day=timedelta( hours=8, minutes=30), end_date=date(2017, 3, 23)) EmploymentFactory.create(user=auth_client.user, start_date=date(2017, 3, 24), worktime_per_day=timedelta(hours=8), end_date=None) # Overtime credit of 10 hours OvertimeCreditFactory.create(user=auth_client.user, date=start_date, duration=timedelta(hours=10, minutes=30)) # One public holiday during workdays PublicHolidayFactory.create(date=start_date, location=employment.location) # One public holiday on weekend PublicHolidayFactory.create(date=start_date + timedelta(days=1), location=employment.location) # 2x 10 hour reported worktime ReportFactory.create(user=auth_client.user, date=start_date + timedelta(days=3), duration=timedelta(hours=10)) ReportFactory.create(user=auth_client.user, date=start_date + timedelta(days=4), duration=timedelta(hours=10)) # one absence AbsenceFactory.create(user=auth_client.user, date=start_date + timedelta(days=5)) url = reverse('worktime-balance-detail', args=[ '{0}_{1}'.format(auth_client.user.id, end_date.strftime('%Y-%m-%d')) ]) with django_assert_num_queries(12): result = auth_client.get(url) assert result.status_code == status.HTTP_200_OK # 4 workdays 8.5 hours, 1 workday 8 hours, minus one holiday 8.5 # minutes 10.5 hours overtime credit expected_worktime = timedelta(hours=23) # 2 x 10 reports hours + 1 absence of 8 hours expected_reported = timedelta(hours=28) json = result.json() assert json['data']['attributes']['balance'] == ( duration_string(expected_reported - expected_worktime))
def submit_plugin_form_data(self, form_entry, request, form, form_element_entries=None, **kwargs): """Submit plugin form data/process. :param fobi.models.FormEntry form_entry: Instance of ``fobi.models.FormEntry``. :param django.http.HttpRequest request: :param django.forms.Form form: """ # In case if we should submit value as is, we don't return anything. # In other cases, we proceed further. # Get the object value = form.cleaned_data.get(self.data.name, None) if isinstance(value, datetime.timedelta): value = duration_string(value) # Overwrite ``cleaned_data`` of the ``form`` with object # qualifier. form.cleaned_data[self.data.name] = value # It's critically important to return the ``form`` with # updated ``cleaned_data`` return form
def get_balance(self, instance): balance_date = self.get_date(instance) start = date(balance_date.year, 1, 1) # id is mapped to user instance _, _, balance = instance.id.calculate_worktime(start, balance_date) return duration_string(balance)
def get_used_duration(self, instance): """ Calculate duration of absence type. For absence types which fill worktime this will be None. """ # id is mapped to absence type absence_type = instance.id if not absence_type.fill_worktime: return None start = self._get_start(instance) absences = sum( [ absence.calculate_duration( models.Employment.objects.get_at(instance.user, absence.date)) for absence in Absence.objects.filter( user=instance.user, date__range=[start, instance.date], type_id=instance.id, ).select_related("type") ], timedelta(), ) return duration_string(absences)
def get_worktime_balance(self, instance): """Format the worktime balance. :return: The formatted worktime balance. :rtype: str """ worktime_balance = self.get_worktime_balance_raw(instance) return duration_string(worktime_balance)
def get_root_meta(self, resource, many): if not many: queryset = Report.objects.filter(task=self.instance) data = queryset.aggregate(spent_time=Sum("duration")) data["spent_time"] = duration_string(data["spent_time"] or timedelta(0)) return data return {}
def test_report_round_duration(self): """Should round the duration of a report to 15 minutes.""" report = self.reports[0] report.duration = timedelta(hours=1, minutes=7) report.save() assert duration_string(report.duration) == '01:00:00' report.duration = timedelta(hours=1, minutes=8) report.save() assert duration_string(report.duration) == '01:15:00' report.duration = timedelta(hours=1, minutes=53) report.save() assert duration_string(report.duration) == '02:00:00'
def get_purchased_time(self, obj): """ Calculate purchased time for given project. Only acknowledged hours are included. """ orders = Order.objects.filter(project=obj, acknowledged=True) data = orders.aggregate(purchased_time=Sum('duration')) return duration_string(data['purchased_time'] or timedelta(0))
def get_used(self, instance): """Format the total of used time. :return: The formatted total of used time :rtype: str """ used = self.get_used_raw(instance) return duration_string(used)
def test_report_round_duration(db): """Should round the duration of a report to 15 minutes.""" report = ReportFactory.create() report.duration = timedelta(hours=1, minutes=7) report.save() assert duration_string(report.duration) == "01:00:00" report.duration = timedelta(hours=1, minutes=8) report.save() assert duration_string(report.duration) == "01:15:00" report.duration = timedelta(hours=1, minutes=53) report.save() assert duration_string(report.duration) == "02:00:00"
def get_root_meta(self, resource, many): """Add total hours over whole result (not just page) to meta.""" if many: view = self.context['view'] queryset = view.filter_queryset(view.get_queryset()) data = queryset.aggregate(total_time=Sum(self.duration_field)) data['total_time'] = duration_string(data['total_time'] or timedelta(0)) return data return {}
def get_security_report_info(self, security_report_id): try: seurity_report = SecurityReport.objects.select_related( 'user').prefetch_related('security_report_entries').get( pk=security_report_id) except SecurityReport.DoesNotExist: return None entries = [] for entry in seurity_report.security_report_entries.all(): entries.append({ 'id': entry.id, 'name': entry.name, 'type': entry.type, 'create_age': duration_string(entry.create_age), 'write_age': duration_string(entry.write_age), 'master_password': entry.master_password, 'breached': entry.breached, 'duplicate': entry.duplicate, 'password_length': entry.password_length, 'variation_count': entry.variation_count, }) return { 'id': seurity_report.id, 'create_date': seurity_report.create_date, 'username': seurity_report.user.username, 'recovery_code_exists': seurity_report.recovery_code_exists, 'two_factor_exists': seurity_report.two_factor_exists, 'website_password_count': seurity_report.website_password_count, 'breached_password_count': seurity_report.breached_password_count, 'duplicate_password_count': seurity_report.duplicate_password_count, 'check_haveibeenpwned': seurity_report.check_haveibeenpwned, 'master_password_breached': seurity_report.master_password_breached, 'master_password_duplicate': seurity_report.master_password_duplicate, 'master_password_length': seurity_report.master_password_length, 'master_password_variation_count': seurity_report.master_password_variation_count, 'entries': entries, }
def get_time_taken(self, obj): """ TODO: add me """ try: time_diff = obj.completed_at - obj.started_at result = duration_string(time_diff) except TypeError: result = None return result
def get_spent_time(self, obj): """ Calculate spent time for given project. Reports which are not billable or are in review are excluded. """ reports = Report.objects.filter(task__project=obj, not_billable=False, review=False) data = reports.aggregate(spent_time=Sum('duration')) return duration_string(data['spent_time'] or timedelta())
def get_balance(self, instance): """Format the balance. This is None if we don't have a duration. :return: The formatted balance :rtype: str or None """ balance = self.get_balance_raw(instance) return duration_string(balance) if balance else None
def transform_dish(cls, dish: Dish): return { 'id': dish.id, 'name': dish.name, 'description': dish.description, 'price': str(dish.price), 'prepare_time': duration_string(dish.prepare_time), 'is_vegetarian': dish.is_vegetarian, 'modified': cls.transform_date(dish.modified), 'created': cls.transform_date(dish.created), 'picture': dish.picture.url if dish.picture else None }
def get_worktime_balance(self, instance): """Format the worktime balance. :return: The formatted worktime balance. :rtype: str """ request = self.context.get('request') until = request.query_params.get('until') end_date = until and datetime.strptime(until, '%Y-%m-%d').date() _, _, balance = self.get_worktime(instance, None, end_date) return duration_string(balance)
def prepare_value(self, value): # humanize had too much rounding... # also, always assuming positive for now if value is None: return None if not isinstance(value, timedelta): return value if not self.human_values: return duration_string(value) elif value == timedelta(): return "a moment" else: return human_duration_string(value)
def clean(self): """Validation.""" cleaned_data = super(DurationInputForm, self).clean() initial = cleaned_data.get('initial') if initial not in forms.Field.empty_values: if not isinstance(initial, datetime.timedelta): if parse_duration(force_text(initial)) is None: self.add_error('initial', _("Enter a valid duration.")) else: cleaned_data['initial'] = duration_string(initial) return cleaned_data
def format_course(self, course, tutor): """Format course object into the expected api response json""" course_format = { 'id': course.pk, 'name': course.name, 'credits': course.credits, # django-rest-framework uses django.utils.duration.duration_string for duration field serialization # https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/fields.py#L1289 'duration': duration_string(course.duration), 'tutors': [{ 'id': tutor.pk, 'name': tutor.name }] } return course_format
def get_price(self, obj): if obj.price_type not in (Product.PRICE_FIXED, Product.PRICE_PER_PERIOD): raise ValueError('{} has invalid price type "{}"'.format( obj, obj.price_type)) ret = { 'type': obj.price_type, 'tax_percentage': str(obj.tax_percentage), 'amount': str(obj.price) } if obj.price_type == Product.PRICE_PER_PERIOD: ret.update({'period': duration_string(obj.price_period)}) return ret
def __init__(self, param, cursor, strings_only=False): # With raw SQL queries, datetimes can reach this function # without being converted by DateTimeField.get_db_prep_value. if settings.USE_TZ and (isinstance(param, datetime.datetime) and not isinstance(param, Oracle_datetime)): if timezone.is_naive(param): warnings.warn( "Oracle received a naive datetime (%s)" " while time zone support is active." % param, RuntimeWarning) default_timezone = timezone.get_default_timezone() param = timezone.make_aware(param, default_timezone) param = Oracle_datetime.from_datetime( param.astimezone(timezone.utc)) if isinstance(param, datetime.timedelta): param = duration_string(param) if ' ' not in param: param = '0 ' + param string_size = 0 # Oracle doesn't recognize True and False correctly in Python 3. # The conversion done below works both in 2 and 3. if param is True: param = 1 elif param is False: param = 0 if hasattr(param, 'bind_parameter'): self.force_bytes = param.bind_parameter(cursor) elif isinstance(param, Database.Binary): self.force_bytes = param else: # To transmit to the database, we need Unicode if supported # To get size right, we must consider bytes. self.force_bytes = convert_unicode(param, cursor.charset, strings_only) if isinstance(self.force_bytes, six.string_types): # We could optimize by only converting up to 4000 bytes here string_size = len( force_bytes(param, cursor.charset, strings_only)) if hasattr(param, 'input_size'): # If parameter has `input_size` attribute, use that. self.input_size = param.input_size elif string_size > 4000: # Mark any string param greater than 4000 characters as a CLOB. self.input_size = Database.CLOB else: self.input_size = None
def prepare_plugin_form_data(self, cleaned_data): """Prepare plugin form data. Might be used in integration plugins. """ value = cleaned_data.get(self.data.name, None) if isinstance(value, datetime.timedelta): value = duration_string(value) # Overwrite ``cleaned_data`` of the ``form`` with object # qualifier. cleaned_data[self.data.name] = value # It's critically important to return the ``form`` with updated # ``cleaned_data`` return cleaned_data
def clean(self): """Validation.""" cleaned_data = super(DurationInputForm, self).clean() initial = cleaned_data.get('initial') if initial not in forms.Field.empty_values: if not isinstance(initial, datetime.timedelta): if parse_duration(force_text(initial)) is None: self.add_error( 'initial', _("Enter a valid duration.") ) else: cleaned_data['initial'] = duration_string(initial) return cleaned_data
def __init__(self, param, cursor, strings_only=False): # With raw SQL queries, datetimes can reach this function # without being converted by DateTimeField.get_db_prep_value. if settings.USE_TZ and (isinstance(param, datetime.datetime) and not isinstance(param, Oracle_datetime)): if timezone.is_aware(param): warnings.warn( "The Oracle database adapter received an aware datetime (%s), " "probably from cursor.execute(). Update your code to pass a " "naive datetime in the database connection's time zone (UTC by " "default).", RemovedInDjango20Warning) param = param.astimezone(timezone.utc).replace(tzinfo=None) param = Oracle_datetime.from_datetime(param) if isinstance(param, datetime.timedelta): param = duration_string(param) if ' ' not in param: param = '0 ' + param string_size = 0 # Oracle doesn't recognize True and False correctly in Code Python github 3. # The conversion done below works both in 2 and 3. if param is True: param = 1 elif param is False: param = 0 if hasattr(param, 'bind_parameter'): self.force_bytes = param.bind_parameter(cursor) elif isinstance(param, Database.Binary): self.force_bytes = param else: # To transmit to the database, we need Unicode if supported # To get size right, we must consider bytes. self.force_bytes = convert_unicode(param, cursor.charset, strings_only) if isinstance(self.force_bytes, six.string_types): # We could optimize by only converting up to 4000 bytes here string_size = len( force_bytes(param, cursor.charset, strings_only)) if hasattr(param, 'input_size'): # If parameter has `input_size` attribute, use that. self.input_size = param.input_size elif string_size > 4000: # Mark any string param greater than 4000 characters as a CLOB. self.input_size = Database.CLOB else: self.input_size = None
def __init__(self, param, cursor, strings_only=False): # With raw SQL queries, datetimes can reach this function # without being converted by DateTimeField.get_db_prep_value. if settings.USE_TZ and (isinstance(param, datetime.datetime) and not isinstance(param, Oracle_datetime)): if timezone.is_aware(param): warnings.warn( "The Oracle database adapter received an aware datetime (%s), " "probably from cursor.execute(). Update your code to pass a " "naive datetime in the database connection's time zone (UTC by " "default).", RemovedInDjango20Warning) param = param.astimezone(timezone.utc).replace(tzinfo=None) param = Oracle_datetime.from_datetime(param) if isinstance(param, datetime.timedelta): param = duration_string(param) if ' ' not in param: param = '0 ' + param string_size = 0 # Oracle doesn't recognize True and False correctly in Python 3. # The conversion done below works both in 2 and 3. if param is True: param = 1 elif param is False: param = 0 if hasattr(param, 'bind_parameter'): self.force_bytes = param.bind_parameter(cursor) elif isinstance(param, Database.Binary): self.force_bytes = param else: # To transmit to the database, we need Unicode if supported # To get size right, we must consider bytes. self.force_bytes = convert_unicode(param, cursor.charset, strings_only) if isinstance(self.force_bytes, six.string_types): # We could optimize by only converting up to 4000 bytes here string_size = len(force_bytes(param, cursor.charset, strings_only)) if hasattr(param, 'input_size'): # If parameter has `input_size` attribute, use that. self.input_size = param.input_size elif string_size > 4000: # Mark any string param greater than 4000 characters as a CLOB. self.input_size = Database.CLOB else: self.input_size = None
def test_signals_session_end_impersonatelog(self): self.assertFalse(ImpersonationLog.objects.exists()) self._impersonate_helper('user1', 'foobar', 4) session_key = self.client.session.get('_impersonate_session_id') self.client.get(reverse('impersonate-stop')) none_session_key = self.client.session.get('_impersonate_session_id') log = ImpersonationLog.objects.get() self.assertEqual(log.impersonator.id, 1) self.assertEqual(log.impersonating.id, 4) self.assertEqual(log.session_key, session_key) self.assertIsNotNone(log.session_started_at) self.assertIsNotNone(log.session_ended_at) self.assertIsNone(none_session_key) self.assertTrue(log.session_ended_at > log.session_started_at) self.assertEqual( log.duration, duration_string(log.session_ended_at - log.session_started_at), )
def prepare_value(self, value): # humanize had too much rounding... # also, always assuming positive for now if value is None: return None if not isinstance(value, timedelta): return value if not self.human_values: return duration_string(value) elif value == timedelta(): return "a moment" builder = [] # a list of tuples like ngettext (but with no subs for single) us = abs(value.microseconds) seconds = abs(value.seconds) days = abs(value.days) builder.append(('a year', '%d years', days // 365)) builder.append(('a month', '%d months', days % 365 // 30)) builder.append(('a week', '%d weeks', days % 365 % 30 // 7)) builder.append(('a day', '%d days', days % 365 % 30 % 7)) builder.append(('an hour', '%d hours', seconds // 60 // 60)) builder.append(('a minute', '%d minutes', seconds // 60 % 60)) builder.append(('a second', '%d seconds', seconds % 60)) builder.append(('a millisecond', '%d milliseconds', us // 1000)) builder.append(('a microsecond', '%d microseconds', us % 1000)) legit = [] for tup in builder: if tup[2] == 0: continue elif tup[2] == 1: legit.append(tup[0]) else: legit.append(tup[1] % tup[2]) if len(legit) == 1: return legit[0] elif len(legit) == 2: return legit[0] + " and " + legit[1] return ", ".join(legit[:-1]) + ", and " + legit[-1]
def prepare_value(self, value): if isinstance(value, datetime.timedelta): return duration_string(value) return value
def test_microseconds(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5, microseconds=12345) self.assertEqual(parse_duration(duration_string(duration)), duration)
def prepare_value(self, value): return duration_string(value)
def date_interval_sql(self, timedelta): return "'%s'" % duration_string(timedelta), []
def test_durationfield_prepare_value(self): field = DurationField() td = datetime.timedelta(minutes=15, seconds=30) self.assertEqual(field.prepare_value(td), duration_string(td)) self.assertEqual(field.prepare_value('arbitrary'), 'arbitrary') self.assertIsNone(field.prepare_value(None))
def to_representation(self, value): return duration_string(value)
"""
from __future__ import unicode_literals
def to_db(cls, value, **kwargs): if not isinstance(value, timedelta): raise cls.exception("Cannot serialize, value {0} is not a timedelta".format(value)) return duration_string(value)
def test_simple(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5) self.assertEqual(duration_string(duration), '01:03:05')
def test_microseconds(self): duration = datetime.timedelta(hours=1, minutes=3, seconds=5, microseconds=12345) self.assertEqual(duration_string(duration), '01:03:05.012345')
def test_negative(self): duration = datetime.timedelta(days=-1, hours=1, minutes=3, seconds=5) self.assertEqual(duration_string(duration), '-1 01:03:05')
def test_negative(self): duration = datetime.timedelta(days=-1, hours=1, minutes=3, seconds=5) self.assertEqual(parse_duration(duration_string(duration)), duration)