Releases: EtorixDev/timelength
Releases · EtorixDev/timelength
v3.0.3
- Fixed several edge cases.
ago()/hence()now evaluate “now” per call whenbaseis not provided.- Conversion rounding now respects
max_precision=0(instead of treating it like no rounding). - Power with modulo now handles zero modulo correctly (
ValueError) instead of silently skipping modulo logic. - Datetime bound checks now handle naive datetimes consistently by treating them as UTC.
- Various documentation and repr updates to
TimeLengthandGuess. - Migrated from Poetry to uv.
- Added Python 3.14 support.
v3.0.2
- Modify
GuessandTimeLengthclasses so handling ofGuess().localesoccurs only inside of theGuessclass. - Modify
Guessto makeGuess().flagsandGuess().settingsproperties to emphasize that modifying those configurations will not propagate to the internalLocales and to allow for per-locale configuration without being overwritten by theGuess's configuration. They may still be passed as arguments during initialization.- To update the flags and settings in
Guess().localespost-initialization, iterate over the list and update as necessary.
- To update the flags and settings in
- Modify
TimeLengthso that theLocalechosen during guessing is adeepcopyto prevent accidental modifications.
v3.0.1
v3.0.0
Breaking
- Python 3.8 is no longer supported.
TimeLength().strictis deprecated. Its functionality has been replaced withtimelength.FailureFlagsandtimelength.ParserSettings. Find a full list of options for each in theREADME.- The default for
FailureFlagsisFailureFlags.NONEwhich means as long as a single value is parsed, it will be considered a success. - The spiritual successor to
strict = TrueisFailureFlags.ALL, which means if any failure flag is met, the parsing will be considered a failure.
- The default for
decimal_separatorsandthousand_separatorsin the config were renamed todecimal_delimitersandthousand_delimiters.- This will only affect you if you utilized a
CustomLocale.
- This will only affect you if you utilized a
CustomLocalewas removed in favor of just usingLocale.BufferTypeandbuffer_type()renamed toStringTypeandstring_type()respectively.TimeLength().result.invalidandTimeLength().result.validare now tuples of tuples instead of lists of tuples.- The invalid tuple is of type
tuple[tuple[float | str, FailureFlags], ...]. - The valid tuple is of type
tuple[tuple[float, Scale], ...].
- The invalid tuple is of type
Features
timelength.FailureFlagsis an IntFlag enum which holds all the currently possible reasons for a parse to fail. It is not guaranteed that every flag will be used by every parser, but every flag from all parsers will be present. See theREADMEfor a full list.- Set specific failure flags by passing them to your locale.
- Example:
locale = English(flags=(FailureFlags.LONELY_VALUE | FailureFlags.UNKNOWN_TERM)). - In this scenario, parsing will only fail if
LONELY_VALUEorUNKNOWN_TERMappear in theresult.invalidtuple, or if no valid results were parsed.
- Modify parsing behavior by passing a
timelength.ParserSettings()tolocale.settings. It is not guaranteed that every setting will be used by every parser, but every setting from all parsers will be present.- Example:
locale = English(settings=ParserSettings(allow_duplicate_scales=False)) assume_seconds(Literal["LAST", "SINGLE", "NEVER"]): Defaults toSINGLE. How to handle no scale being provided. If seconds are disabled, the first loaded scale will take its place.LAST: Assume seconds only for the last value if no scale is provided for it.SINGLE: Only assume seconds when a single number is provided.NEVER: Never assume seconds when no scale is provided.
limit_allowed_terms(bool): Defaults toTrue. Prevent terms from theallowed_termslist in the config from being used in the middle of a segment/sentence, thus interrupting a value/scale pair. The affected segment will become abandoned and added to the invalid tuple. The terms may still be used at the beginning or end of a segment/sentence. IfFalse, The terms will be ignored (within other limitations) and not affect parsing.allow_duplicate_scales(bool): Defaults toTrue. Allow scales to be parsed multiple times. The values will stack. IfFalse, the first scale will be used and subsequent duplicates will be added to the invalid tuple.prevent_thousands_extra_digits(bool): Defaults toTrue. Prevent thousands from being parsed if it has more than three digits following the thousand delimiter. Ex:1,2345. The number will be added to the invalid tuple. IfFalse, the number will be interpreted as12,345. This does not allow for thousands to be parsed with less than three digits following the thousand delimiter.allow_thousands_lacking_digits(bool): Defaults toFalse. IfTrue, allow thousands to be parsed with less than three digits following the thousand delimiter. Ex:1,23will be interpreted as123, or2,455 5as24,555(depending on terms in config).
- Example:
HH:MM:SSnotation (roughly).- It is not strictly adherent to typical
HH:MM:SSstandards. Any parsable numbers work in each slot, whether they are single digits, multiple digits, or include decimals.- For example,
2.56:27/3:270:19.2231is a valid input in place of2.56 days, 9 hours, 270 minutes, and 19.2231 seconds. - It also accepts a single connector, such as a space, between deliminators. Example:
2: 6: 3.
- For example,
- Supports up to as many segments as there are scales defined, including custom scales (10 default,
MillisecondtoCentury).- The segments are parsed in reverse order, so smallest to largest (the order defined in the config and therefore the order loaded into the
Locale, may differ for custom definedScales) to ensure the correct scales are applied.- EXCEPTION: The default base from which
HH:MM:SSstarts at isSecond. Any scales (typically of lesser value) listed prior in the config, or appended to the scales list beforeSecondin the case of custom scales, will not be utilized unlessSecondis disabled or as manyHH:MM:SSsegments are parsed as there are scales defined. 12:30:15is12 hours, 30 minutes, and 15 seconds, NOT12 minutes, 30 seconds, and 15 milliseconds.1:10:100:12:52:30:24:60:60:1000will make use ofCenturytoMillisecond.
- EXCEPTION: The default base from which
- The segments are parsed in reverse order, so smallest to largest (the order defined in the config and therefore the order loaded into the
- Delimiters are modifiable in the config under the
hhmmss_delimiterskey. Values must be unique fromdecimal_delimitersandthousand_delimiters.
- It is not strictly adherent to typical
- Quickly access the parsed
TimeLengthas atimedeltawithTimeLength().result.delta. - Find the relative
datetimeof your input in the past or future withTimeLength().ago()andTimeLength().hence().- Both take an optional
baseargument which is adatetime. It defaults to the present inUTC.
- Both take an optional
- Have
TimeLengthguess theLocaleby passingGuess()for the locale.- It will attempt to parse with all locales currently available and return the best result. The best result is the one with the least invalid results.
- Add custom
Locales by appending toGuess().locales. TimeLength().localewill be set to the guessed locale.- Guess subsequent parses by using
TimeLength().parse(guess_locale=True)orTimeLength().parse(guess_locale=Guess()).
- Perform arithmetic operations on
TimeLengthobjects.- Check the README for a full list of supported operations and types.
- All operations not involving a
datetimeare absolute. For example,TimeLength("1 minute") - TimeLength("5 minutes")will returnTimeLength("4 minutes"). - Any resultant
TimeLengths will inherit thelocalefrom the first encounteredTimeLengthin the arithmetic.
- Perform comparison operations on
TimeLengthobjects.- Comparison based on their parsed seconds for all but
boolandlencomparisons. boolreturns if parsing succeeded based on theresult.successattribute.lenreturns the length of the passedcontentattribute.
- Comparison based on their parsed seconds for all but
- Other things I've likely forgotten.
Improvements
- Seconds will now only be assumed as the input if the
Secondscale is enabled (and assuming is enabled). IfSecondis disabled, the first loaded scale (typically the smallest value wise unless you have defined custom scales out of order) will be used instead. - Overhauled various
__str__and_repr__functions. - Added full type hinting.
- Commented areas where the reasoning for doing things is unclear (many places).
- A lot of things are now properties to discourage modifying them.
- Various errors added for incorrect usage.
- Tests expanded to 100% coverage.
- The
ruffformatter now uses a line-length of 120 instead of the default 88. - Other things I've likely forgotten.
v2.0.5
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v2.0.0
Rewritten to hopefully achieve a cleaner code base and better user experience.
Breaking
- Only officially supporting
Python 3.8and above. TimeLength.total_secondswas moved toTimeLength.result.seconds.TimeLength.parsed_valuewas moved toTimeLength.result.invalidandTimeLength.result.valid.TimeLength.passed_valuewas renamed toTimeLength.content.- Scales, such as
TimeLength.Second, were moved to theTimeLength.Locale.
Features
TimeLength.result.successto determine the parsing outcome based onTimeLength.strict. See theREADMEfor more information.- Numerals (
half a day), (twelve hours), etc, are supported. - The same
TimeLengthobject can be reused by accessingTimeLength.contentandTimeLength.parse(). - Parsers are now in their own files found in
timelength/parsersand are loaded dynamically by theLocalethat uses them.Locales determine which parser to use based on the config file they are passed, which are found intimelength/locales. - The 2 default supported
Locales areEnglishandSpanish. CustomLocales are possible by using theCustomLocaleobject and a custom config file. See theREADMEfor more information.
Improvements
- Errors will no longer be thrown during parsing even if
TimeLength.strictisTrue. If "invalid" (as determined by the relevant parser) inputs are found, it will be up to the user to determine how to proceed. Errors are still thrown if the config is invalid, or if a conversion method is used for a disabledScale. - Using
ruffto format code everywhere except for the test files.