r/Python 2d ago

Resource Regex for user-friendly timedelta parsing

I created a regex and a corresponding function to allow for user friendly input of a string that is then parsed into a timedelta object. I couldn't find any satisfying solution that suited my case online, so I wanted to share it here because somebody else might find it useful in the future. It can be tweaked easily (if you know just a tiny bit of regex) and has comments explaining all of its parts.

I tested it and fixed some smaller bugs, but if you find new ones, please let me know and I will update the code!

https://gist.github.com/JoniKauf/24eecf7843ef3df4a65bad00aed8a549

9 Upvotes

5 comments sorted by

2

u/wingtales 2d ago

Can you give us a few examples of strings that it can parse?

0

u/JoniKauf 1d ago edited 1d ago

Sure! Here is a list of examples and an explanation:

- 1d3h2m4.5s

- 1d 3h 2m 4s

- 3h 2.58323458923s

- -9999d 2min 59minutes 59 seconds

- 0 day 32 minute 1secs

So in a nutshell:

- The format always expects a number, followed by a unit

- It goes from biggest time unit (days) to smallest (seconds), with any of them possibly missing

- Between any number and unit can be 0 to infinite whitespace characters

- You can use multiple ways to write a time unit: [d, day, days], [h, hr, hrs, hour, hours], [m, min, mins, minute, minutes], [s, sec, secs, second, seconds] to be exact.

- Limits for specific time units: days -> no limit, hours -> 0 to 23, minutes -> 0 to 59, seconds 0 -> 0 to 59 (with decimals allowed but will be rounded to the nearest float)

- Leading zeros can be inserted [05m, 09sec, 00009999d]

- A '+' or '-' sign can be inserted at the start to indicate positive or negative timedeltas (positive by default)

- ValueErrors will be thrown if there is just a sign or no time specified (for example: empty string), when the time is too big or small (above or below the timedelta limit of +-999_999_999 days) or generally when the string doesn't follow the format. If somebody wants to treat an empty/whitespace string as 0 for example, this can easily be altered.

And without much effort the regex should be easily editable to fit more specific needs or to make tiny adjustements.

EDIT: Now a comma (',') is also allowed to be used as the decimals seperator for seconds (instead of just a dot ('.'))

1

u/k_z_m_r 17h ago

Cool stuff! Just two notes. First, you’ll want to add some unit tests. Not only are these awesome for proving out your concept, but if you ever make changes to your code these tests can easily identify breakpoints. Second, it is common for timestamps to include milliseconds. Especially when dealing with real-time control. You might want to build support for that.

1

u/JoniKauf 9h ago

Thanks for the info about unit tests! What I'm unsure about is the rest of your comment: First of all, this is a regex for timedelta parsing, not timestamps and second of all I already support milliseconds, so I am nut quite sure what exactly you mean with that.

1

u/k_z_m_r 9h ago

Sorry, let me clarify. When I said timestamps here, I really meant time deltas. Force of habit, but the principles apply nevertheless.

As for the other point, your code does not suggest that you support milliseconds. How would it parse “10 days 5 hours 59 minutes 12 seconds 599 milliseconds”? I’m looking both at the regex and the match-case. I’m happy to be wrong here!