что вы действительно хотите вычислить?
- datetime (или время в течение 1 дня) обычно представлены как действительные числа
- координаты времени на 24-часовых часах являются комплексными числами , однако
- среднее из представлений действительных чисел времени даст вам сомнительные результаты ...
Я не знаю, что вы хотите сделать с крайними случаями, такими как [1:00
, 13:00
], но давайте рассмотрим следующий пример : [01:30
, 06:30
, 13:20
, 15:30
, 16:15
, 16:45
, 17:10
]

Я предлагаю реализовать этот алгоритм - в Python :
- преобразовать время в комплексные числа - например, вычислить их координаты по окружности радиуса = 1
- вычислить среднее значение, используя сложение векторов
- преобразование угла вектора результата в минуты + вычисление релевантности этого результата (например, релевантность среднего значения [
1:00
, 13:00
] должна быть 0 независимо от того, какой угол вычислен из-за ошибок округления)
import math
def complex_average(minutes):
# first convert the times from minutes (0:00 - 23:59) to radians
# so we get list for quasi polar coordinates (1, radians)
# (no point in rotating/flipping to get real polar coordinates)
# 180° = 1/2 day = 24*60/2 minutes
radians = [t*math.pi/(24*60/2) for t in minutes]
xs = []
ys = []
for r in radians:
# convert polar coordinates (1, r) to cartesian (x, y)
# the vectors start at (0, 0) and end in (x, y)
x, y = (math.cos(r), math.sin(r))
xs.append(x)
ys.append(y)
# result vector = vector addition
sum_x, sum_y = (sum(ys), sum(xs))
# convert result vector coordinates to radians, then to minutes
# note the cumulative ROUNDING ERRORS, however
result_radians = math.atan2(sum_x, sum_y)
result_minutes = int(result_radians / math.pi * (24*60/2))
if result_minutes < 0:
result_minutes += 24*60
# relevance = magnitude of the result vector / number of data points
# (<0.0001 means that all vectors cancel each other, e.g. [1:00, 13:00]
# => result_minutes would be random due to rounding error)
# FYI: standart_deviation = 6*60 - 6*60*relevance
relevance = round(math.sqrt(sum_x**2 + sum_y**2) / len(minutes), 4)
return result_minutes, relevance
И проверить это так:
# let's say the select returned a bunch of integers in minutes representing times
selected_times = [90, 390, 800, 930, 975, 1005, 1030]
# or create other test data:
#selected_times = [hour*60 for hour in [23,22,1]]
complex_avg_minutes, relevance = complex_average(selected_times)
print("complex_avg_minutes = {:02}:{:02}".format(complex_avg_minutes//60,
complex_avg_minutes%60),
"(relevance = {}%)".format(int(round(relevance*100))))
simple_avg = int(sum(selected_times) / len(selected_times))
print("simple_avg = {:02}:{:02}".format(simple_avg//60,
simple_avg%60))
hh_mm = ["{:02}:{:02}".format(t//60, t%60) for t in selected_times]
print("\ntimes = {}".format(hh_mm))
Вывод для моего примера:
complex_avg_minutes = 15:45 (relevance = 44%)
simple_avg = 12:25