sopel-irc / sopel

:robot::speech_balloon: An easy-to-use and highly extensible IRC Bot framework. Formerly Willie.
https://sopel.chat
Other
948 stars 403 forks source link

Feature: Abbreviated humanized time output #1799

Open dgw opened 4 years ago

dgw commented 4 years ago

It'd be pretty damn nice if tools.time.seconds_to_human() could output abbreviated units on demand. If I think about it for more than a few seconds, though, it seems more likely that we'll need a full-on format specification to accommodate different preferences—whether the abbreviations should contain ., whether to use e.g. sec or secs (or just s)…

Tangentially related to #1798, if only because we'll need support in this feature for both "fuzzy" and exact output modes.

half-duplex commented 4 years ago

Do we actually need more flexibility than smallest_unit = s/m/h/d/y? Months are dubious because of differing day counts, weeks are of debatable utility, and I don't want to have to build/maintain a formatter.

Exirel commented 4 years ago

Or maybe what we could split seconds_to_human in two: the first part would give a tuple of (y, m, d, h, min, s, ms), and the second part would take such a tuple and return the "human readable" version.

For instance, this is the first part:

years = secs // 31536000
months = (secs - years * 31536000) // 2635200
days = (secs - years * 31536000 - months * 2635200) // 86400
hours = (secs - years * 31536000 - months * 2635200 - days * 86400) // 3600
minutes = (secs - years * 31536000 - months * 2635200 - days * 86400 - hours * 3600) // 60
seconds = secs - years * 31536000 - months * 2635200 - days * 86400 - hours * 3600 - minutes * 60

And this is the second part:

result = ", ".join(filter(lambda x: bool(x), [
    "{0} {1}".format(years, years_text) if years else "",
    "{0} {1}".format(months, months_text) if months else "",
    "{0} {1}".format(days, days_text) if days else "",
    "{0} {1}".format(hours, hours_text) if hours else "",
    "{0} {1}".format(minutes, minutes_text) if minutes else "",
    "{0} {1}".format(seconds, seconds_text) if seconds else ""
]))

Edit: I mean that it would allow anyone to either use the built-in version, or to craft their own format.

RustyBower commented 4 years ago

I've pretty successfully used https://arrow.readthedocs.io/en/latest/#humanize to create "humanized" output from a datetime object

half-duplex commented 4 years ago

Exirel - Years and months are still not consistent lengths, so unless we know a start or end date, they cannot be correct.

Exirel commented 4 years ago

Years and months are still not consistent lengths

What do you mean?

dgw commented 4 years ago

I'm reasonably sure he means that some years have an extra day (leap years), and months have differing lengths (30 or 31 days, plus the oddball February with its 28/29 depending on leap year status).

That said, we could get close enough by assuming a 30-day month and 365.25 days per year that it wouldn't really matter in most use cases.

Exirel commented 4 years ago

Yeah, I get that. I assumed (and still do) that the function which deal with the first part gets, as its arguments, the duration, a timestamp, the current date or something alike. I took the existing code to show the separation. If the formulae to compute the right tuple has to change, so be it - but I think that's another story.

dgw commented 3 years ago

Don't wanna spend time on this for 7.1, honestly. Punted.