Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function to represent timedeltas without losing precision (precisedelta) #137

Merged
merged 13 commits into from
Jul 20, 2020
Merged

Function to represent timedeltas without losing precision (precisedelta) #137

merged 13 commits into from
Jul 20, 2020

Conversation

eldipa
Copy link
Contributor

@eldipa eldipa commented Jun 28, 2020

Fixes #48

Changes proposed in this pull request:

Current limitations:

  • The comma , is used as separator. It could be easily changed but still we should consider the localization for this.
  • The and is used to join the last item. Translation is required.
  • If microseconds are used but seconds, milliseconds and microseconds are suppressed, the microseconds are lost.

Examples:

Return a precise representation of a timedelta

>>> import datetime as dt
>>> from humanize.time import precisedelta

>>> delta = dt.timedelta(seconds=3633, days=2, microseconds=123000)
>>> precisedelta(delta)
'2 days, 1 hour and 33.12 seconds'

A custom format can be specified to control how the fractional part
is represented:

>>> precisedelta(delta, format="%0.4f")
'2 days, 1 hour and 33.1230 seconds'

Instead, the minimum unit can be changed to have a better resolution;
the function still will readjust the unit to use the greatest of the
units that does not loose precision.

For example setting microseconds but still representing the date
with milliseconds:

>>> precisedelta(delta, minimum_unit="microseconds")
'2 days, 1 hour, 33 seconds and 123 milliseconds'

If desired, some units can be suppressed: you will not see them
represented and the time of the other units will be adjusted
to keep representing the same timedelta:

>>> precisedelta(delta, suppress=['days'])
'49 hours and 33.12 seconds'

Note that microseconds precision is lost if the seconds and all
the units below are suppressed:

>>> delta = dt.timedelta(seconds=90, microseconds=100)                                                                  
>>> precisedelta(delta, suppress=['seconds', 'milliseconds', 'microseconds'])                                           
'1.50 minutes' 

Add MINUTES, HOURS, DAYS, MONTHS and YEARS as part of the Unit Enum and
make them ordenable so MICROSECONDS < MILLISECONDS < SECONDS .. < YEARS
For backward compatibility, only allow SECONDS, MILLISECONDS and
MICROSECONDS: this was the original behavior; we can allow the rest of
the units later.
A timedelta now can be represented using a combination of days, hours
and seconds to represent the delta precisely.

>>> delta = dt.timedelta(seconds=3633, days=2, microseconds=123000)
>>> precisedelta(delta)
'2 days, 1 hour and 33.12 seconds'

Note for translators: the ' and ' needs translation.
@codecov-commenter
Copy link

codecov-commenter commented Jun 28, 2020

Codecov Report

Merging #137 into master will increase coverage by 0.14%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #137      +/-   ##
==========================================
+ Coverage   99.28%   99.42%   +0.14%     
==========================================
  Files           9        9              
  Lines         421      524     +103     
==========================================
+ Hits          418      521     +103     
  Misses          3        3              
Flag Coverage Δ
#GHA_Ubuntu 99.42% <100.00%> (+0.14%) ⬆️
#GHA_Windows 99.42% <100.00%> (+0.14%) ⬆️
#GHA_macOS 99.42% <100.00%> (+0.14%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/humanize/__init__.py 100.00% <100.00%> (ø)
src/humanize/time.py 100.00% <100.00%> (ø)
tests/test_time.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 976ad4a...dc532d6. Read the comment docs.

@eldipa eldipa changed the title WIP: function to represent timedeltas without loosing precision (precisedelta) Function to represent timedeltas without loosing precision (precisedelta) Jul 6, 2020
@hugovk hugovk added changelog: Added For new features enhancement New feature or request labels Jul 6, 2020
Copy link
Collaborator

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the tests and the docstrings, looking good!

The other docstrings (or those I've updated so far) are done following Google's style guide.

If it's not too much trouble to update following that, that'd be great. But if it doesn't really fit, you can leave them as this.

README.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved

def _quotient_and_remainer(value, divisor, unit, minimum_unit, suppress):
"""Divide ``value`` by ``divisor`` returning the quotient and
the remainer as follows:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
the remainer as follows:
the remainder as follows:

src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
@hugovk hugovk mentioned this pull request Jul 6, 2020
src/humanize/time.py Outdated Show resolved Hide resolved
@hugovk
Copy link
Collaborator

hugovk commented Jul 6, 2020

Also, would you be able to add tests to hit the error cases?

The red lines in https://codecov.io/gh/jmoiron/humanize/pull/137/diff?src=pr&el=tree#diff-c3JjL2h1bWFuaXplL3RpbWUucHk=

return NotImplemented
if tmp not in (Unit.SECONDS, Unit.MILLISECONDS, Unit.MICROSECONDS):
    raise ValueError("Minimum unit '%s' not supported" % minimum_unit)
raise ValueError(
    "Minimum unit is suppresed and not suitable replacement was found"
)
if date is None:
    return value

@hugovk hugovk changed the title Function to represent timedeltas without loosing precision (precisedelta) Function to represent timedeltas without losing precision (precisedelta) Jul 15, 2020
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@hugovk hugovk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

A few more bits and pieces :)

src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
src/humanize/time.py Outdated Show resolved Hide resolved
tests/test_time.py Outdated Show resolved Hide resolved
Comment on lines 594 to 596
assertRaises(
humanize.precisedelta, ValueError, 1, minimum_unit="years", suppress=["years"]
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assertRaises(
humanize.precisedelta, ValueError, 1, minimum_unit="years", suppress=["years"]
)
with pytest.raises(ValueError) as e:
humanize.precisedelta(1, minimum_unit="years", suppress=["years"])

tests/test_time.py Outdated Show resolved Hide resolved
tests/test_time.py Outdated Show resolved Hide resolved
README.md Show resolved Hide resolved
@hugovk hugovk merged commit 15ecb0a into jmoiron:master Jul 20, 2020
@hugovk
Copy link
Collaborator

hugovk commented Jul 20, 2020

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog: Added For new features enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

function to print timedeltas exactly
3 participants