1

I'm trying to find the average to a list that stores my datetime times.

I've tried getting the sum of the list except that doesn't work since it is a datetime module.

finaltimes = []
for i in range(len(times)):
    try:
        a = times[i]
        b = prior_times[i]

        da = datetime.datetime.strptime(a, '%H:%M:%S')
        db = datetime.datetime.strptime(b, '%H:%M:%S')

        print(db - da)
        finaltimes.append(db - da)

I'm expecting the output to be something along the lines of 00:01:34. Any help?

martineau
  • 119,623
  • 25
  • 170
  • 301

3 Answers3

1

One way to do this would be to convert datetime objects to utc, average them out, covert the final utc back to datetime object like so -

import datetime
datetime.datetime.fromtimestamp((datetime.datetime(2012,4,1,0,0).timestamp() + datetime.datetime(2013,4,1,0,0).timestamp()) / 2 )
# OP datetime.datetime(2012, 9, 30, 11, 0)
Sushant
  • 3,499
  • 3
  • 17
  • 34
0

You can use this. I have imported just datetime from datetime for brevity in the first line. When you use datetime.strptime on only the time, it will return a date of January 1st, 1970. The datetime methods are much richer than the time methods, so the input and arithmetic is done with datetime here. You can just use strftime to output the time without the dates so they are ignored throughout. (Note: In Windows, the timestamp method will not work for January 1st, 1970, so I have added a hack to force the date to January 2nd. As long as this is done for both times, it will work fine).

from datetime import datetime
finaltimes = []
for i in range(len(times)):
    try:
        a = times[i]
        b = prior_times[i]

        da = datetime.strptime(a, '%H:%M:%S').replace(day=2)
        db = datetime.strptime(b, '%H:%M:%S').replace(day=2)

        ft = datetime.fromtimestamp((da.timestamp() + db.timestamp()) / 2)

        print(ft)
        finaltimes.append(ft)

Here's the core code using your example times, run in interactive mode, with the inputs already done.

>>> ft = datetime.fromtimestamp((da.timestamp() + db.timestamp()) / 2)
>>> print(ft)
2019-07-23 00:02:52.500000
>>> print(ft.strftime("%H:%M:%S.%f"))
00:02:52.500000
>>> print(ft.strftime("%H:%M:%S.%f")[:11])
00:02:52.50
Deepstop
  • 3,627
  • 2
  • 8
  • 21
  • Seem to be getting this error ft = datetime.fromtimestamp((da.timestamp() + db.timestamp()) / 2) AttributeError: module 'datetime' has no attribute 'fromtimestamp' – No Copywrite Spectrums Jul 23 '19 at 18:03
  • My inputs are along the lines of 00:03:34 00:02:11 – No Copywrite Spectrums Jul 23 '19 at 18:09
  • Sorry if i'm not making it clear. But I only have the times.. No dates. The times are saved in an array. I want to run the array. Get average. and print it – No Copywrite Spectrums Jul 23 '19 at 21:18
  • OK. Updated again (don't forget to use `from datetime import datetime` so as not to get the error you reported in the first comment). The `time` methods don't offer much so it is easier to do the calculation with the date attached then ignore it afterwards. You can just ignore the date and format the output with just the time part. – Deepstop Jul 23 '19 at 22:00
  • I keep getting this error: ```Error: ft = datetime.fromtimestamp((da.timestamp() + db.timestamp()) / 2) OSError: [Errno 22] Invalid argument ``` – No Copywrite Spectrums Jul 24 '19 at 14:18
  • I have discovered an issue that affect Windows only. I was testing on Linux but have reproduced the problem on my laptop. The problem, as I found in https://stackoverflow.com/questions/37494983/python-fromtimestamp-oserror, has to do with Windows failing to convert timestamps on Jan 1, 1970. I forced the date to Jan 2, 1970 and it works fine. Because both `da` and `db` are on the same day, the program still works the same way with this modification, but now works on Windows as well. – Deepstop Jul 24 '19 at 21:37
  • Sorry for the late reply, was on holiday. However this code still errors. `code ft = datetime.fromtimestamp((da.timestamp() + db.timestamp()) / 2) OSError: [Errno 22] Invalid argument ` – No Copywrite Spectrums Aug 03 '19 at 00:51
  • OK I've run it on Python 3.7.4 for Linux and the same version under windows successfully. I assume the word "code" wasn't supposed to be included in the line in your comment, so I'm not sure what's going on with your computer. You could try `replace(year=2000)` or some thing like that - maybe that would work, – Deepstop Aug 04 '19 at 01:35
0

Another method as follows. This time, if you have just HH:MM:SS format, you can just use arithmetic on the strings converted to seconds. The final times in this example are strings. You can convert them to something else, like datetime or time objects, depending on what you require. Or just leave it as the number of seconds 'ts, etc.

from operator import mul
finaltimes = []
for i in range(len(times)):
    a = times[i]
    b = prior_times[i]

    as = sum(map(operator.mul, (int(x) for x in a.split(":")), (3600, 60, 1)))
    bs = sum(map(operator.mul, (int(x) for x in b.split(":")), (3600, 60, 1)))
    ts = (as + bs) // 2

    finaltimes.append(f"{ts // 3600:02d}:{(ts % 3600) // 60:02d}:{ts % 60:02d}")
Deepstop
  • 3,627
  • 2
  • 8
  • 21
  • Sorry to come back out with more errors but I have now gotten this `code finaltimes.append(f"{ts // 3600:02d}:{(ts % 3600) // 60:02d}:{ts % 60:02d}") ValueError: Unknown format code 'd' for object of type 'float'` – No Copywrite Spectrums Aug 03 '19 at 00:46
  • Might be an odd number of seconds that you're averaging and getting a floating point #. Try `ts = (as + bs) // 2` to truncate to an integer (Answer updated). You must have caught the typo in the variable name. Otherwise if you want the fractional part then you could use a floating point format for ts as in `{ts % 60:4.1f}` – Deepstop Aug 04 '19 at 01:43
  • This just gives me a list of the times. I'm looking to get the average of all of these times. Again, sorry if it wasn't clear!! – No Copywrite Spectrums Aug 06 '19 at 01:58
  • The above provides the average of `as` and `bs` using `ts = (as + bs) // 2`, as with your sample code. Are you looking for something else? If you are looking for an average of a longer list, that is a different question, but not particularly hard. All you need to do is create a new list using the same formula to convert the time to seconds, sum it and divide by the length of the list. – Deepstop Aug 06 '19 at 10:27
  • I have an array filled with timestamps. I am looking to get the average of them all so that I can finally export it to a csv file – No Copywrite Spectrums Aug 07 '19 at 14:30