Skip to content

Add a parameter to limit the amount of units returned by humanize #1013

Open

Description

@MarkKoz

Feature Request

Add a parameter to arrow.Arrow.humanize which limits the amount of units in the returned string.

>>> time1 = arrow.get(2021, 8, 7, 0, 30)
>>> time2 = arrow.get(2021, 8, 7, 2, 21, 11)
>>> time1.humanize(time2, granularity=["hour", "minute", "second"])
'an hour 51 minutes and 11 seconds ago'

>>> time1.humanize(time2, granularity=["hour", "minute", "second"], max_units=2)
'an hour and 51 minutes ago'

>>> time1.humanize(time2, granularity=["hour", "minute", "second"], max_units=1)
'an hour ago'

>>> time1.humanize(time2, granularity=["hour", "second"], max_units=3)
'an hour and 3071 seconds ago'

Just like the granularity parameter, it simply truncates the output; no rounding should be performed. It should start counting from the largest unit. In the example above it starts counting at hours; at minutes it reaches the specified limit of 2 units. Anything after (just seconds) is omitted.

The use case is to effectively limit the length of the output string. While granularity can be used to control the length of the output, the caller would already have to know what units the result will show. With the proposed parameter, the caller just specifies an amount and doesn't care which combination of units are returned.

The name is up to discussion; max_units is just used for the sake of example.

Activity

  1. krisfremen commented on Aug 7, 2021

    @krisfremen
    Member

    hmm, this is a neat thing to have!

    I think we should probably have an option to return the humanized strings as a list or dict as well?

  2. anishnya commented on Aug 7, 2021

    @anishnya
    Member

    I think we should probably give some kind of preference like highest order time frames first. This would make the feature well with the Dynamic Flag as well.

  3. MarkKoz commented on Aug 7, 2021

    @MarkKoz
    Author

    You need to be careful about this. I think adding too many customisation parameters can result in a confusing and overwhelming API. It also sets a precedent for adding even more customisation, and it can quickly get out of control. Just off the top of my head, I can also imagine someone wanting a way to customise the separator.

    I think we should probably have an option to return the humanized strings as a list or dict as well?

    This sounds promising, since it would provide a lot of flexibility to users without piling the API with many options. It would likely be better to make this a separate function, because new parameters in the future could end up being at worst incompatible or at least not making sense in conjunction with as_dict=True or whatever. In any case, returning a union of such drastically different types is kinda yucky to me anyway.

    Granted, it is still convenient for the library to directly support some customisation. There has to be a balance between that and telling users to implement customisation themselves with the dictionary.

  4. anishnya commented on Aug 7, 2021

    @anishnya
    Member

    It definitely would need to be a separate function. Humanize is already a pretty messy function to begin with, so adding even more flags and parameters to it is going to make it even more unreadable.

  5. AbhiramVSA commented on Oct 30, 2026

    @AbhiramVSA

    humanize() on current master (2224255) still passes the complete sequence of selected frames to describe_multi(). It has no max_units parameter.

    A focused PR can cap that sequence before locale formatting. A result with one frame can use the existing describe() path. This keeps truncation in the unit data and avoids cuts inside localized text. The default output and string return type can stay unchanged.

    The reported hour/minute/second example can serve as a regression case: a cap of two keeps the hour and minute without rounding the omitted seconds. Further cases can cover a cap of one, limits above the frame count, invalid limits, past/future direction, and only_distance.

    PR #997 already addresses zero-unit suppression, and #1399 addresses the conjunction in direct single-frame describe_multi() calls. Neither adds this limit.

    For this feature, must max_units count every selected frame, or only frames with a nonzero value?

  6. ub3dqy commented on Nov 3, 2026

    @ub3dqy

    I have a tested max_units option for this: it counts nonzero units, omits the rest without rounding, and leaves existing output unchanged when omitted. All 1943 tests pass locally, with one existing Windows skip; lint and docs checks pass too. Would you be open to $40 for the change, tests and docs?

    Dima Mak / ub3dqy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions