Human-readable datetime interval to datetime.timedelta in Python? - python

I find myself needing to specify a timespan in a python configuration file a lot.
Is there a way that I can specify a more human readable timeframe (similar to PostgreSQL's Interval syntax) in a python configuration file with stdlib? Or will this require a 3rd party lib?
Clarification I'm not looking for anything in the ConfigParser.ConfigParser stdlib API specifically. I guess what I really need is a way to go from human readable date/time interval to datetime.timedelta value.

I found a good answer to this in an somewhat related question. Turns out the humanfriendly library does that fairly well:
In [1]: import humanfriendly
In [2]: humanfriendly.parse_timespan('1w')
Out[2]: 604800.0
That's in seconds. To get a timedelta object, you can simply load that:
In [3]: from datetime import timedelta
In [4]: timedelta(seconds=humanfriendly.parse_timespan('1w'))
Out[4]: datetime.timedelta(7)
Since humanfriendly also supports converting the other way, you can also do full round trip, which would look like:
In [5]: humanfriendly.format_timespan(timedelta(seconds=humanfriendly.parse_timespan('1w')).total_seconds())
Out[5]: '1 week'
Note how format_timespan does not access timedelta objects, unfortunately: only an integer (seconds).

I don't think there is a standard library module for that. I wrote one that does that. You can install it, or adapt it to your needs.
The module is called pycopia.timespec
It converts strings such as "1day 3min" to seconds, as a float. It's easy to get a datetime.timedelta from that.

Related

python parse `ISO_8601` time or time interval

I need to convert
FROM
a list of strs
TO
a list of
either a datetime.datetime
or a datetime.datetime plus a datetime.timedelta.
The input list contains strings in ISO_8601 (wikipedia) format. The strings can either be a date or a time interval. The solution for this, that I came up with is the following:
import dateutil.parser
result = []
for str_ in input_list:
if not is_time_interval_str(str_):
result.append(dateutil.parser.parse(str_))
else:
result.append(parse_time_interval(str_))
What I am stuck with is the two functions is_time_interval_str and parse_time_interval. I have looked for python packages that implement parsing of the time intervals but I couldn't find any yet. I have checked
dateutil.parser
pyiso8601
isodate
arrow
ciso8601
iso8601utils (claims to support time intervals, but does only some)
maya (offers the functionality, but the implementation is flawed)
pendulum (claims to support time intervals, but does only some)
Some may be capable of parsing durations like PnYnMnDTnHnMnS but none is able to parse time intervals like for example <start>/<end>.
6.,7. and 8. work partially also with <start>/<end> but none of them works with a partial <end> description. (example '2007-01-10/27')
I considered writing my own string parser but it feels that such fundamental thing like the implementation of the ISO_8601 should be incorporated by one of the above packages.
Questions
Should I write my own string parser with something like map(dateutil.parser.parser, str_.split("/"))?
Is there any python package capable of parsing time intervals of the ISO_8601?
I've seen solutions that use database engines for conversion of str to datetime.datetime, would this be an option for time intervals?

Python Datetime Strptime Error: '-' is a bad directive in format '%-m-%-d-%y %-H:%M:%S'

I know that there have been similar questions asked, but they seemed to have to do with the way datetime deals (or doesn't deal) with timezones.
The setup is a little complicated, and probably not relevant to the problem, but I thought it was important to include the code as is, so a little background:
I've got a dictionary of arrays. Each of these arrays represents an "attempt" by the same person, but taking place at different times. Ultimately I'm going to be looking for the earliest of these dates. This may be a bit of a roundabout solution, but I'm converting all of the dates to datetime objects, finding the earliest and then just using that index to pull out the first attempt:
Here's what the code looks like to setup that array of attempt datetimes:
for key in duplicates_set.keys():
attempt_dates = [datetime.strptime(attempt['Attempt Date'], "%-m-%-d-%y %-H:%M:%S") for attempt in duplicates_set[key]]
Here's the format of what one of the original date strings looks like:
12-5-2016 3:27:58 PM
What I'm getting back is:
ValueError: '-' is a bad directive in format '%-m-%d-%y %-H:%M:%S'
I assume that's referring to the dashes placed before the 'm', 'd' and 'H' because they're non-zero-padded decimals. Why is it telling me that?
%-* -- to skip padding -- is a GNU libc extension. It's not part of POSIX strftime, and thus not guaranteed to be portable to systems where your time-formatting calls aren't eventually backed by GNU's strftime C library function.
The Python datetime module documentation explicitly specifies the format strings it supports, and this extension is not given. Thus, while this is supported in GNU date and GNU strftime(), it isn't available in Python datetime.
I had the same issue;
date: 1/9/21
according to:
https://strftime.org/ the correct format would've been "%-d/%-m/%y"
which gave the bad directive error.
"%d-/%m-/%y" didn't work either.
Weirdly enough what worked was "%d/%m/%y".

Efficient way for python date string manipulation

I want to turn '07/18/2013' to '07/2013' and there are a lot of these strings to be processed. What would be the most efficient way to do it?
I am thinking of using
''.join(['07/18/2013'[0:3],'07/18/2013'[6:]])
Look into strftime and strptime.
Assuming you start with the string s you can put it into a datetime object using strptime then take that back out into a string with only the necessary fields using strftime. I didn't actually run this code so I don't know if it is perfect, but the idea is here.
temp = datetime.strptime.(s, "%m/%D/%Y")
final = temp.strftime(%m/%Y")
You can find info on the datetime functions here https://docs.python.org/2/library/datetime.html
Use datetime module:
import datetime
print datetime.datetime.strptime("07/18/2013", '%m/%d/%Y').strftime('%m/%Y')

Write numpy datetime64 in ISO 8601 with timezone

How can the time zone be controlled when writing numpy datetime64 objects as an ISO 8601 string? Specifically, I would like the time zone to be "+0000", just like the input below. For this very simple example I just want it to print back the original string.
import numpy
print(numpy.datetime64('2014-03-07T17:52:00.000+0000'))
For me, it returns
2014-03-07T12:52:00.000-0500
I am using python 3.4, numpy 1.9.2, and windows.
This question is similar, but the first two answers don't actually answer the question and the third answer is specific to unix.
s = '2014-03-07T17:52:00.000+0000'
print(numpy.datetime64(s).item().replace(tzinfo=pytz.UTC).isoformat('T'))
Thanks to ShadowRanger for getting me going in the right direction. item gets naive datetime from datetime64, then replace time zone with UTC since I know that's what it is in this case, then get it in ISO format with the 'T' separator.
This should work:
import numpy, time, os
os.environ['TZ'] = 'GMT'
time.tzset()
print(numpy.datetime64('2014-03-07T17:52:00.000+0000'))
based on this stackoverflow answer:
https://stackoverflow.com/a/32764078/5915424

Python script: convert random date formats to fixed yyyy-mm-dd

I'm quite new to python and don't know much about it but i need to make a small script that when someone inputs a date in any format , it would then converts it in to yyyy-mm-dd format.
The script should be able to share elements of the entered date, and identify patterns.
It might be easy and obvious to some but making one by my self is over my head.
Thanks in advance!
This is a difficult task to do yourself; you might want to take a look at dateutil which has a rather robust parse() method that you can use to try and parse arbitrarily formatted date strings.
You can do something like this (not tested)
import locale
import datetime
...
parsedDate = datetime.strptime(your_string, locale.D_FMT)
print datetime.strftime(parsedDate, "%Y-%M-%d")
This assumes that the user will use its own local convention for dates.
You can use strftime for output (your format is "%Y-%M-%d").
For parsing input there's a corresponding function - strptime. But you won't be able to handle "any format". You have to know what you're getting in the first place. Otherwise you wouldn't be able to tell a difference between (for example) American and other dates. What does 01.02.03 mean for example? This could be:
yy.mm.dd
dd.mm.yy
mm.dd.yy

Categories