xolox / python-humanfriendly

Human friendly input/output for text interfaces using Python
https://humanfriendly.readthedocs.org
MIT License
319 stars 45 forks source link

Support months in parse_timespan / Case-sensitive suffixes #15

Open ldotlopez opened 7 years ago

ldotlopez commented 7 years ago

Sorry if this question was raise before.

Is there any reason for humanfriendly doesn't support months (with M suffix) in parse_timespan?

Looking into the code I can see that suffixes are lowercased and therefore the 'M' suffix cant' be used but this can be easily achieved removing the .lower() call or choosing another suffix like 'mo'.

Anyway, it's possible to get month suffix in parse_timespan?

xolox commented 6 years ago

Hi Luis, thanks for the feedback and sorry for the late response. There are two reasons why humanfriendly doesn't support months in parse_timespan():

  1. It seems more logical to me that the case insensitive 'm' suffix means 'minute' instead of 'month', because the primary use case that I intended for parse_timespan() is to succinctly and unambiguously express (usually short) time spans in command line arguments. You're right though that case sensitive suffixes could resolve this ambiguity.

  2. The length of a month is rather ambiguous. If I'm not mistaken the only unambiguous definition is the following: 60 * 60 * 24 * (365 / 12). But this seems a bit weird to me and so might not be what users expect :blush:.

For posterity: I do realize that leap seconds mean that the length of a year is also ambiguous, but the size of potential discrepancies is on a completely different scale (IMHO).

SkyLeach commented 6 years ago

@xolox if I may chime in on this, there are multiple use cases for 'user friendly' and/or 'human friendly' formatting of months in parse_timespan. One of them is why I'm here looking at your project.

Here are two use-cases:

Age formatting for young children (< 2 years), Puppies and Kittens (especially those up for adoption or sale):

Parents and pet owners/adoption agencies use months instead of years to communicate the ages of children, puppies and kittens. This is a social custom in western countries. I don't have experience in other countries so I can't speak to that.

The second is code and/or content updates (like shown here, on github). In this case the ability to see that code was updated 1-2 weeks ago vs. 3-6 months ago is often quite nice to have as a feature. You can see his in action on the github website for commit history.

troyhoffman commented 6 years ago

@SkyLeach How do you determine how many seconds are in a month? A puppy born February 1 will be one month old on March 1, which would be 28 days (assuming it's not a leap year) old, but a puppy born on March 1 would be a month old on April 1, which is 31 days. That's a pretty big variance.

You will need to determine the best way of representing a month in a unit other than months. If you just want a rough estimate, you could use an average per-month calculation and convert to weeks (months * 4.3). That should be close enough for most calculations, but it's something you need to decide based on your specific needs.

SkyLeach commented 6 years ago

@troyhoffman I've been busy on a number of other things, sorry it took so long for me to answer your question.

You must start with a contextual date. This can be a firm date parsed from a source or a datetime object built by NLU/NLP from the source. However you build it, you must start with your absolute datetime reference point.

Specifically, see: strftime and strptime in order to find the best way of converting whatever textual representation into something that can be used to parse your absolute datetime object.

The next thing you would use is a timedelta which can be built with months, days, years, seconds, etc.

At this point you should be in a position to provide exactly the functionality we have discussed.

note: control of the source of the calendar is also possible. You aren't forced to use gregorian or cartesian, it can be any calendar or even a make-believe one from fantasy.