human_duration.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from typing import Optional
  2. from .features import FEATURES, conv_space
  3. SPEC = (
  4. (1e3, 1e3, "ns", 1),
  5. (1e3, 1e3, "µs", 1), # uses non-ASCII “µs” suffix.
  6. (1e3, 1e3, "ms", 1),
  7. (60., 1., "s", 2),
  8. # 1:01.1 (minutes in code, 1 decimal).
  9. # 1:01:01 (hours in code, 0 decimal).
  10. )
  11. def __human_duration(val: float, prec: Optional[int], space: str) -> str:
  12. val *= 1e9
  13. for size, div_next, scale, dec in SPEC:
  14. r = round(val, dec)
  15. if r >= size:
  16. val /= div_next
  17. continue
  18. if prec is not None:
  19. r = round(val, prec)
  20. elif r % 1. == 0.:
  21. prec = 0
  22. elif (r * 10.) % 1. == 0.:
  23. prec = 1
  24. else:
  25. prec = 2
  26. return '{:.{}f}{}{}'.format(r, prec, space, scale)
  27. val = round(val, 1)
  28. m = val / 60.
  29. if m < 60.:
  30. r = val % 60.
  31. if prec is not None:
  32. pass
  33. elif r % 1. == 0.:
  34. prec = 0
  35. if prec == 0:
  36. return '{:.0f}:{:02.0f}'.format(m // 1., r)
  37. return '{:.0f}:{:04.1f}'.format(m // 1., round(r, 1))
  38. return '{:.0f}:{:02.0f}:{:02.0f}'.format(m / 60. // 1., m % 60. // 1., val % 60. // 1.)
  39. def fn_human_duration(space: bool):
  40. def run(val, prec: Optional[int]):
  41. return __human_duration(val, prec, space)
  42. space = conv_space(space)
  43. return run
  44. class HumanDuration(object):
  45. def __init__(self, value):
  46. assert value >= 0.
  47. self._value = value
  48. @property
  49. def value(self):
  50. return self._value
  51. def as_human(self, prec: Optional[int] = None) -> str:
  52. """Return a beautiful representation of this duration.
  53. It dynamically calculates the best scale to use.
  54. Args:
  55. prec: an optional custom precision
  56. Returns:
  57. the human friendly representation.
  58. """
  59. return fn_human_duration(FEATURES.feature_space)(self._value, prec)
  60. def __str__(self):
  61. return self.as_human()
  62. def __repr__(self): # pragma: no cover
  63. return 'HumanDuration{{ value={} }} -> {}'.format(self._value, self)
  64. def __eq__(self, other):
  65. return self.__str__() == other