Averages/Mean time of day: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Algol 68)
 
(42 intermediate revisions by 25 users not shown)
Line 1: Line 1:
{{task|Date and time}}
{{task|Date and time}}


;Task
{{task heading}}


A particular activity of bats occurs at these times of the day:
A particular activity of bats occurs at these times of the day:
Line 18: Line 18:


<hr>
<hr>

=={{header|11l}}==
{{trans|Python}}
<syntaxhighlight lang="11l">F mean_angle(angles)
V x = sum(angles.map(a -> cos(radians(a)))) / angles.len
V y = sum(angles.map(a -> sin(radians(a)))) / angles.len
R degrees(atan2(y, x))

F mean_time(times)
V t = (times.map(time -> time.split(‘:’)))
V seconds = (t.map(hms -> (Float(hms[2]) + Int(hms[1]) * 60 + Int(hms[0]) * 3600)))
V day = 24 * 60 * 60
V to_angles = seconds.map(s -> s * 360.0 / @day)
V mean_as_angle = mean_angle(to_angles)
V mean_seconds = round(mean_as_angle * day / 360.0)
I mean_seconds < 0
mean_seconds += day
V h = mean_seconds I/ 3600
V m = mean_seconds % 3600
V s = m % 60
m = m I/ 60
R ‘#02:#02:#02’.format(h, m, s)

print(mean_time([‘23:00:17’, ‘23:40:20’, ‘00:12:45’, ‘00:17:19’]))</syntaxhighlight>
{{out}}
<pre>23:47:43</pre>

=={{header|Action!}}==
Action! does not support trigonometry, therefore a simple arithmetic solution has been proposed.
{{libheader|Action! Tool Kit}}
{{libheader|Action! Real Math}}
<syntaxhighlight lang="action!">INCLUDE "H6:REALMATH.ACT"

DEFINE PTR="CARD"
TYPE Time=[BYTE s,m,h]
REAL r60

PROC PrintB2(BYTE b)
IF b<10 THEN Put('0) FI
PrintB(b)
RETURN

PROC PrintTime(Time POINTER t)
PrintB2(t.h) Put(':)
PrintB2(t.m) Put(':)
PrintB2(t.s)
RETURN

PROC Decode(CHAR ARRAY st Time POINTER t)
CHAR ARRAY tmp

IF st(0)#8 THEN Break() FI
SCopyS(tmp,st,1,2) t.h=ValB(tmp)
SCopyS(tmp,st,4,5) t.m=ValB(tmp)
SCopyS(tmp,st,7,8) t.s=ValB(tmp)
RETURN

PROC TimeToSeconds(Time POINTER t REAL POINTER seconds)
REAL r

IntToReal(t.h,seconds)
RealMult(seconds,r60,seconds)
IntToReal(t.m,r)
RealAdd(seconds,r,seconds)
RealMult(seconds,r60,seconds)
IntToReal(t.s,r)
RealAdd(seconds,r,seconds)
RETURN

PROC SecondsToTime(REAL POINTER seconds Time POINTER t)
REAL tmp1,tmp2

RealAssign(seconds,tmp1)
RealMod(tmp1,r60,tmp2)
t.s=RealToInt(tmp2)
RealDivInt(tmp1,r60,tmp2)
RealMod(tmp2,r60,tmp1)
t.m=RealToInt(tmp1)
RealDivInt(tmp2,r60,tmp1)
t.h=RealToInt(tmp1)
RETURN

PROC AverageTime(PTR ARRAY times BYTE count Time POINTER res)
BYTE i
Time t
REAL avg,rcount,seconds,halfDay,day

IntToReal(0,avg)
IntToReal(count,rcount)
ValR("43200",halfDay) ;seconds in the half of day
ValR("86400",day) ;seconds in the whole day
FOR i=0 TO count-1
DO
Decode(times(i),t)
TimeToSeconds(t,seconds)
IF RealLess(seconds,halfDay) THEN
RealAdd(seconds,day,seconds) ;correction of time
FI
RealAdd(avg,seconds,avg)
OD
RealDivInt(avg,rcount,avg)
WHILE RealGreaterOrEqual(avg,day)
DO
RealSub(avg,day,avg) ;correction of time
OD
SecondsToTime(avg,res)
RETURN

PROC Main()
DEFINE COUNT="4"
PTR ARRAY times(COUNT)
Time t

Put(125) PutE() ;clear the screen
IntToReal(60,r60)
times(0)="23:00:17" times(1)="23:40:20"
times(2)="00:12:45" times(3)="00:17:19"

AverageTime(times,COUNT,t)
Print("Mean time is ") PrintTime(t)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Mean_time_of_day.png Screenshot from Atari 8-bit computer]
<pre>
Mean time is 23:47:40
</pre>

=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Calendar.Formatting;
with Ada.Command_Line;
with Ada.Numerics.Elementary_Functions;
with Ada.Strings.Fixed;
with Ada.Text_IO;

procedure Mean_Time_Of_Day is

subtype Time is Ada.Calendar.Time;
subtype Time_Of_Day is Ada.Calendar.Day_Duration;
subtype Time_String is String (1 .. 8); -- "HH:MM:SS"

type Time_List is array (Positive range <>) of Time_String;

function Average_Time (List : Time_List) return Time_String is

function To_Time (Time_Image : Time_String) return Time
is (Ada.Calendar.Formatting.Value ("2000-01-01 " & Time_Image));

function To_Time_Of_Day (TS : Time) return Time_Of_Day is
use Ada.Calendar.Formatting;
Hour_Part : constant Time_Of_Day := 60.0 * 60.0 * Hour (TS);
Min_Part : constant Time_Of_Day := 60.0 * Minute (TS);
Sec_Part : constant Time_Of_Day := Time_Of_Day (Second (TS));
begin
return Hour_Part + Min_Part + Sec_Part;
end To_Time_Of_Day;

function To_Time_Image (Angle : Time_Of_Day) return Time_String
is
use Ada.Calendar.Formatting;
TOD : constant Time := Time_Of
(Year => 2000, Month => 1, Day => 1, -- Not used
Seconds => Angle);
begin
return Ada.Strings.Fixed.Tail (Image (TOD), Time_String'Length);
end To_Time_Image;

function Average_Time_Of_Day (List : Time_List) return Time_Of_Day is
use Ada.Numerics.Elementary_Functions;
Cycle : constant Float := Float (Time_Of_Day'Last);
X_Sum, Y_Sum : Float := 0.0;
Angle : Float;
begin
for Time_Stamp of List loop
Angle := Float (To_Time_Of_Day (To_Time (Time_Stamp)));
X_Sum := X_Sum + Cos (Angle, Cycle => Cycle);
Y_Sum := Y_Sum + Sin (Angle, Cycle => Cycle);
end loop;
Angle := Arctan (Y_Sum, X_Sum, Cycle => Cycle);
if Angle < 0.0 then
Angle := Angle + Cycle;
elsif Angle > Cycle then
Angle := Angle - Cycle;
end if;
return Time_Of_Day (Angle);
end Average_Time_Of_Day;

begin
return To_Time_Image (Average_Time_Of_Day (List));
end Average_Time;

use Ada.Command_Line;
List : Time_List (1 .. Argument_Count);
begin
if Argument_Count = 0 then
raise Constraint_Error;
end if;

for A in 1 .. Argument_Count loop
List (A) := Argument (A);
end loop;
Ada.Text_IO.Put_Line (Average_Time (List));

exception
when others =>
Ada.Text_IO.Put_Line ("Usage: mean_time_of_day <time-1> ...");
Ada.Text_IO.Put_Line (" <time-1> ... 'HH:MM:SS' format");
end Mean_Time_Of_Day;</syntaxhighlight>
{{out}}
<pre>
% ./mean_time_of_day 23:00:17 23:40:20 00:12:45 00:17:19
23:47:43
</pre>

=={{header|ALGOL 68}}==
Uses code from the Averages/Mean angle task, included here for convenience.
<syntaxhighlight lang="algol68">
BEGIN # Mean time of day mapping time to angles #

# code from the Averages/Mean angle task - angles are in degrees #
PROC mean angle = ([]REAL angles)REAL:
(
INT size = UPB angles - LWB angles + 1;
REAL y part := 0, x part := 0;
FOR i FROM LWB angles TO UPB angles DO
x part +:= cos (angles[i] * pi / 180);
y part +:= sin (angles[i] * pi / 180)
OD;
arc tan2 (y part / size, x part / size) * 180 / pi
);
# end code from the Averages/Mean angle task #

MODE TIME = STRUCT( INT hh, mm, ss );

OP TOANGLE = ( TIME t )REAL: ( ( ( ( ( ss OF t / 60 ) + mm OF t ) / 60 ) + hh OF t ) * 360 ) / 24;
OP TOTIME = ( REAL a )TIME:
BEGIN
REAL t := ( a * 24 ) / 360;
WHILE t < 0 DO t +:= 24 OD;
WHILE t > 24 DO t -:= 24 OD;
INT hh = ENTIER t;
t -:= hh *:= 60;
INT mm = ENTIER t;
INT ss = ENTIER ( ( t - mm ) * 60 );
( hh, mm, ss )
END # TOTIME # ;

PROC mean time = ( []TIME times )TIME:
BEGIN
[ LWB times : UPB times ]REAL angles;
FOR i FROM LWB times TO UPB times DO angles[ i ] := TOANGLE times[ i ] OD;
TOTIME mean angle( angles )
END # mean time # ;

OP SHOW = ( TIME t )VOID:
BEGIN
PROC d2 = ( INT n )STRING: IF n < 10 THEN "0" ELSE "" FI + whole( n, 0 );
print( ( d2( hh OF t ), ":", d2( mm OF t ), ":", d2( ss OF t ) ) )
END # show time # ;

SHOW mean time( ( ( 23,00,17 ), ( 23,40,20 ), ( 00,12,45 ), ( 00,17,19 ) ) )
END
</syntaxhighlight>
{{out}}
<pre>
23:47:43
</pre>


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
{{works with|AutoHotkey 1.1}}
{{works with|AutoHotkey 1.1}}
<lang AutoHotkey>MsgBox, % "The mean time is: " MeanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
<syntaxhighlight lang="autohotkey">MsgBox, % "The mean time is: " MeanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])


MeanTime(t, x=0, y=0) {
MeanTime(t, x=0, y=0) {
Line 41: Line 308:
atan2(x, y) {
atan2(x, y) {
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>The mean time is: 23:47:43</pre>
<pre>The mean time is: 23:47:43</pre>


=={{header|AWK}}==
=={{header|AWK}}==
<lang AWK>#!/usr/bin/awk -f
<syntaxhighlight lang="awk">#!/usr/bin/awk -f
{
{
c = atan2(0,-1)/(12*60*60);
c = atan2(0,-1)/(12*60*60);
Line 59: Line 326:
if (p<0) p += 24*60*60;
if (p<0) p += 24*60*60;
print strftime("%T",p,1);
print strftime("%T",p,1);
}</lang>
}</syntaxhighlight>
<pre>$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk
<pre>$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk
23:47:43</pre>
23:47:43</pre>
Line 65: Line 332:
=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> nTimes% = 4
<syntaxhighlight lang="bbcbasic"> nTimes% = 4
DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19
DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19
Line 103: Line 370:
DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</lang>
IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 110: Line 377:


=={{header|C}}==
=={{header|C}}==
<syntaxhighlight lang="c">#include<stdlib.h>
<lang c>/*29th August, 2012
Abhishek Ghosh*/

#include<stdlib.h>
#include<math.h>
#include<math.h>
#include<stdio.h>
#include<stdio.h>
Line 181: Line 445:
meanTime.second);
meanTime.second);
return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 190: Line 454:




The mean time is : 23:47:43
The mean time is : 23:47:43</pre>
</pre>


----
----


=={{header|C sharp}}==
=={{header|C sharp|C#}}==
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using System.Text;
using System.Text;
using static System.Math;


namespace RosettaCode
namespace RosettaCode;

class Program
{
{
private const int SecondsPerDay = 60 * 60 * 24;
class Program

static void Main()
{
{
var digitimes = new List<TimeSpan>();
static void Main(string[] args)
{
Func<TimeSpan, double> TimeToDegrees = (time) =>
360 * time.Hours / 24.0 +
360 * time.Minutes / (24 * 60.0) +
360 * time.Seconds / (24 * 3600.0);
Func<List<double>, double> MeanAngle = (angles) =>
{
double y_part = 0.0d, x_part = 0.0d;
int numItems = angles.Count;


for (int i = 0; i < numItems; i++)
Console.WriteLine("Enter times, end with no input: ");
{
while (true) {
x_part += Math.Cos(angles[i] * Math.PI / 180);
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input)) break;
y_part += Math.Sin(angles[i] * Math.PI / 180);
}
if (TimeSpan.TryParse(input, out var digitime)) {
digitimes.Add(digitime);
} else {
Console.WriteLine("Seems this is wrong input: ignoring time");
}
}
if(digitimes.Count() > 0)
Console.WriteLine($"The mean time is : {MeanTime(digitimes)}");
}


public static TimeSpan MeanTime(IEnumerable<TimeSpan> ts) => FromDegrees(MeanAngle(ts.Select(ToDegrees)));
return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI;
public static double ToDegrees(TimeSpan ts) => ts.TotalSeconds * 360d / SecondsPerDay;
};
public static TimeSpan FromDegrees(double degrees) => TimeSpan.FromSeconds((int)(degrees * SecondsPerDay / 360));
Func<double, TimeSpan> TimeFromDegrees = (angle) =>
new TimeSpan(
(int)(24 * 60 * 60 * angle / 360) / 3600,
((int)(24 * 60 * 60 * angle / 360) % 3600 - (int)(24 * 60 * 60 * angle / 360) % 60) / 60,
(int)(24 * 60 * 60 * angle / 360) % 60);
List<double> digitimes = new List<double>();
TimeSpan digitime;
string input;


public static double MeanAngle(IEnumerable<double> angles)
Console.WriteLine("Enter times, end with no input: ");
do
{
{
var x = angles.Average(a => Cos(a * PI / 180));
input = Console.ReadLine();
var y = angles.Average(a => Sin(a * PI / 180));
if (!(string.IsNullOrWhiteSpace(input)))
return (Atan2(y, x) * 180 / PI + 360) % 360;
{
if (TimeSpan.TryParse(input, out digitime))
digitimes.Add(TimeToDegrees(digitime));
else
Console.WriteLine("Seems this is wrong input: ignoring time");
}
} while (!string.IsNullOrWhiteSpace(input));

if(digitimes.Count() > 0)
Console.WriteLine("The mean time is : {0}", TimeFromDegrees(360 + MeanAngle(digitimes)));
}
}
}
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 263: Line 510:
The mean time is : 23:47:43
The mean time is : 23:47:43
</pre>
</pre>

=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <iomanip>
#include <iostream>
#include <vector>

#define _USE_MATH_DEFINES
#include <math.h>

struct Time {
int hour, minute, second;

friend std::ostream &operator<<(std::ostream &, const Time &);
};

std::ostream &operator<<(std::ostream &os, const Time &t) {
return os << std::setfill('0')
<< std::setw(2) << t.hour << ':'
<< std::setw(2) << t.minute << ':'
<< std::setw(2) << t.second;
}

double timeToDegrees(Time &&t) {
return 360.0 * t.hour / 24.0
+ 360.0 * t.minute / (24 * 60.0)
+ 360.0 * t.second / (24 * 3600.0);
}

Time degreesToTime(double angle) {
while (angle < 0.0) {
angle += 360.0;
}
while (angle > 360.0) {
angle -= 360.0;
}

double totalSeconds = 24.0 * 60 * 60 * angle / 360;
Time t;

t.second = (int)totalSeconds % 60;
t.minute = ((int)totalSeconds % 3600 - t.second) / 60;
t.hour = (int)totalSeconds / 3600;

return t;
}

double meanAngle(const std::vector<double> &angles) {
double yPart = 0.0, xPart = 0.0;
for (auto a : angles) {
xPart += cos(a * M_PI / 180);
yPart += sin(a * M_PI / 180);
}
return atan2(yPart / angles.size(), xPart / angles.size()) * 180 / M_PI;
}

int main() {
std::vector<double> tv;
tv.push_back(timeToDegrees({ 23, 0, 17 }));
tv.push_back(timeToDegrees({ 23, 40, 20 }));
tv.push_back(timeToDegrees({ 0, 12, 45 }));
tv.push_back(timeToDegrees({ 0, 17, 19 }));

double ma = meanAngle(tv);
auto mt = degreesToTime(ma);
std::cout << mt << '\n';

return 0;
}</syntaxhighlight>
{{out}}
<pre>23:47:43</pre>

=={{header|Common Lisp}}==
{{trans|Echo Lisp}}
<syntaxhighlight lang="lisp">;; * Loading the split-sequence library
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '("split-sequence")))

;; * The package definition
(defpackage :mean-time-of-day
(:use :common-lisp :iterate :split-sequence))
(in-package :mean-time-of-day)

;; * The data
(defparameter *time-values*
'("23:00:17" "23:40:20" "00:12:45" "00:17:19"))

(defun time->radian (time)
"Returns the radian value for TIME given as a STRING like HH:MM:SS. Assuming a
valid input value."
(destructuring-bind (h m s)
(mapcar #'parse-integer (split-sequence #\: time))
(+ (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600)))))

(defun radian->time (radian)
"Returns the corresponding time as a string like HH:MM:SS for RADIAN."
(let* ((time (if (plusp radian)
(round (/ (* 12 3600 radian) PI))
(round (/ (* 12 3600 (+ radian (* 2 PI))) PI))))
(h (floor time 3600))
(m (floor (- time (* h 3600)) 60))
(s (- time (* h 3600) (* m 60))))
(format nil "~2,'0D:~2,'0D:~2,'0D" h m s)))

(defun make-polar (rho theta)
"Returns a complex representing the polar coordinates."
(complex (* rho (cos theta)) (* rho (sin theta))))

(defun mean-time (times)
"Returns the mean time value within 24h of the list of TIMES given as strings
HH:MM:SS."
(radian->time (phase
(reduce #'+ (mapcar (lambda (time)
(make-polar 1 (time->radian time))) times)))))
</syntaxhighlight>

{{out}}
<pre>MEAN-TIME-OF-DAY> (mean-time *time-values*)
"23:47:43"</pre>


=={{header|D}}==
=={{header|D}}==
{{trans|Python}}
{{trans|Python}}
<lang d>import std.stdio, std.range, std.algorithm, std.complex, std.math,
<syntaxhighlight lang="d">import std.stdio, std.range, std.algorithm, std.complex, std.math,
std.format, std.conv;
std.format, std.conv;


Line 304: Line 669:
void main() @safe {
void main() @safe {
["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln;
["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.Math}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Averages_Mean_time_of_day;


{$APPTYPE CONSOLE}

uses
System.SysUtils,
System.Math;

const
Inputs: TArray<string> = ['23:00:17', '23:40:20', '00:12:45', '00:17:19'];

function ToTimes(ts: TArray<string>): TArray<TTime>;
begin
SetLength(result, length(ts));
for var i := 0 to High(ts) do
Result[i] := StrToTime(ts[i]);
end;

function MeanTime(times: TArray<TTime>): TTime;
var
ssum, csum: TTime;
h, m, s, ms: word;
dayFrac, fsec, ssin, ccos: double;
begin
if Length(times) = 0 then
exit(0);

ssum := 0;
csum := 0;
for var t in times do
begin
DecodeTime(t, h, m, s, ms);
fsec := (h * 60 + m) * 60 + s + ms / 1000;
ssin := sin(fsec * Pi / (12 * 60 * 60));
ccos := cos(fsec * Pi / (12 * 60 * 60));
ssum := ssum + ssin;
csum := csum + ccos;
end;
if (ssum = 0) and (csum = 0) then
raise Exception.Create('Error MeanTime: Mean undefined');

dayFrac := frac(1 + ArcTan2(ssum, csum) / (2 * Pi));
fsec := dayFrac * 24 * 3600;

ms := Trunc(frac(fsec) * 1000);
s := trunc(fsec) mod 60;
m := trunc(fsec) div 60 mod 60;
h := trunc(fsec) div 3600;

Result := EncodeTime(h, m, s, ms);
end;

begin
writeln(TimeToStr(MeanTime(ToTimes(Inputs))));
readln;
end.</syntaxhighlight>
=={{header|EasyLang}}==
{{trans|C}}
<syntaxhighlight lang=easylang>
func tm2deg t$ .
t[] = number strsplit t$ ":"
return 360 * t[1] / 24.0 + 360 * t[2] / (24 * 60.0) + 360 * t[3] / (24 * 3600.0)
.
func$ deg2tm deg .
len t[] 3
h = floor (24 * 60 * 60 * deg / 360)
t[3] = h mod 60
h = h div 60
t[2] = h mod 60
t[1] = h div 60
for h in t[]
if h < 10
s$ &= 0
.
s$ &= h
s$ &= ":"
.
return substr s$ 1 8
.
func mean ang[] .
for ang in ang[]
x += cos ang
y += sin ang
.
return atan2 (y / len ang[]) (x / len ang[])
.
in$ = "23:00:17 23:40:20 00:12:45 00:17:19"
for s$ in strsplit in$ " "
ar[] &= tm2deg s$
.
print deg2tm (360 + mean ar[])
</syntaxhighlight>


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
<lang scheme>
<syntaxhighlight lang="scheme">
;; string hh:mm:ss to radians
;; string hh:mm:ss to radians
(define (time->radian time)
(define (time->radian time)
Line 332: Line 793:
(mean-time '{"23:00:17" "23:40:20" "00:12:45" "00:17:19"})
(mean-time '{"23:00:17" "23:40:20" "00:12:45" "00:17:19"})
→ "23:47:43"
→ "23:47:43"
</syntaxhighlight>
</lang>


=={{header|Erlang}}==
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( mean_time_of_day ).
-module( mean_time_of_day ).
-export( [from_times/1, task/0] ).
-export( [from_times/1, task/0] ).
Line 366: Line 827:
Secs = Seconds - (Hours * 3600) - (Minutes * 60),
Secs = Seconds - (Hours * 3600) - (Minutes * 60),
lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ).
lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ).
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 372: Line 833:
The mean time of ["23:00:17","23:40:20","00:12:45","00:17:19"] is: "23:47:43"
The mean time of ["23:00:17","23:40:20","00:12:45","00:17:19"] is: "23:47:43"
</pre>
</pre>




=={{header|Euphoria}}==
=={{header|Euphoria}}==
{{works with|OpenEuphoria}}
{{works with|OpenEuphoria}}
<syntaxhighlight lang="euphoria">
<lang Euphoria>
include std/console.e
include std/console.e
include std/math.e
include std/math.e
Line 441: Line 900:
if getc(0) then end if
if getc(0) then end if
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 454: Line 913:


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
<lang fsharp>open System
<syntaxhighlight lang="fsharp">open System
open System.Numerics
open System.Numerics


Line 474: Line 933:
|> deg2time |> fun t -> t.ToString(@"hh\:mm\:ss")
|> deg2time |> fun t -> t.ToString(@"hh\:mm\:ss")
|> printfn "%s: %s" msg
|> printfn "%s: %s" msg
0</lang>
0</syntaxhighlight>
{{out}}
{{out}}
<pre>>RosettaCode 23:00:17 23:40:20 00:12:45 00:17:19
<pre>>RosettaCode 23:00:17 23:40:20 00:12:45 00:17:19
Average time for [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43</pre>
Average time for [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43</pre>

=={{header|Factor}}==
<syntaxhighlight lang="factor">USING: arrays formatting kernel math math.combinators
math.functions math.libm math.parser math.trig qw sequences
splitting ;
IN: rosetta-code.mean-time

CONSTANT: input qw{ 23:00:17 23:40:20 00:12:45 00:17:19 }

: time>deg ( hh:mm:ss -- x )
":" split [ string>number ] map first3
[ 15 * ] [ 1/4 * ] [ 1/240 * ] tri* + + ;

: mean-angle ( seq -- x )
[ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ]
[ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ;

: cutf ( x -- str y )
[ >integer number>string ] [ dup floor - ] bi ;

: mean-time ( seq -- str )
[ time>deg ] map mean-angle [ 360 + ] when-negative 24 *
360 / cutf 60 * cutf 60 * round cutf drop 3array ":" join ;

: mean-time-demo ( -- )
input dup mean-time "Mean time for %u is %s.\n" printf ;

MAIN: mean-time-demo</syntaxhighlight>
{{out}}
<pre>
Mean time for { "23:00:17" "23:40:20" "00:12:45" "00:17:19" } is 23:47:43.
</pre>


=={{header|Fortran}}==
=={{header|Fortran}}==
{{works with|gfortran 5.1.0}}
{{works with|gfortran 5.1.0}}
<lang fortran>
<syntaxhighlight lang="fortran">
program mean_time_of_day
program mean_time_of_day
implicit none
implicit none
Line 552: Line 1,043:
end function
end function
end program
end program
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 559: Line 1,050:


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64


Const pi As Double = 3.1415926535897932
Const pi As Double = 3.1415926535897932
Line 612: Line 1,103:
Print
Print
Print "Press any key to quit"
Print "Press any key to quit"
Sleep</lang>
Sleep</syntaxhighlight>


{{out}}
{{out}}
Line 620: Line 1,111:


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 669: Line 1,160:
_, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi))
_, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi))
return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil
return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 677: Line 1,168:
=={{header|Groovy}}==
=={{header|Groovy}}==
Solution:
Solution:
<lang groovy>import static java.lang.Math.*
<syntaxhighlight lang="groovy">import static java.lang.Math.*


final format = 'HH:mm:ss', clock = PI / 12, millisPerHr = 3600*1000
final format = 'HH:mm:ss', clock = PI / 12, millisPerHr = 3600*1000
Line 687: Line 1,178:
def times = timeStrings.collect(parseTime)
def times = timeStrings.collect(parseTime)
formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock)
formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock)
}</lang>
}</syntaxhighlight>


Test:
Test:
<lang groovy>println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))</lang>
<syntaxhighlight lang="groovy">println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))</syntaxhighlight>


{{out}}
{{out}}
Line 696: Line 1,187:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang haskell>import Data.Complex (cis, phase)
<syntaxhighlight lang="haskell">import Data.Complex (cis, phase)
import Data.List.Split (splitOn)
import Data.List.Split (splitOn)
import Text.Printf (printf)
import Text.Printf (printf)
Line 723: Line 1,214:
main :: IO ()
main :: IO ()
main = putStrLn $ radiansToTime $ meanAngle $ map timeToRadians ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
main = putStrLn $ radiansToTime $ meanAngle $ map timeToRadians ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>
Line 729: Line 1,220:
=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==


<lang>procedure main(A)
<syntaxhighlight lang="text">procedure main(A)
every put(B := [], ct2a(!A))
every put(B := [], ct2a(!A))
write(ca2t(meanAngle(B)))
write(ca2t(meanAngle(B)))
Line 752: Line 1,243:
every (sumCosines := 0.0) +:= cos(dtor(!A))
every (sumCosines := 0.0) +:= cos(dtor(!A))
return rtod(atan(sumSines/*A,sumCosines/*A))
return rtod(atan(sumSines/*A,sumCosines/*A))
end</lang>
end</syntaxhighlight>


Sample run:
Sample run:
Line 764: Line 1,255:
=={{header|J}}==
=={{header|J}}==
use <code>avgAngleR</code> from [[Averages/Mean angle#J]]
use <code>avgAngleR</code> from [[Averages/Mean angle#J]]
<lang J>require 'types/datetime'
<syntaxhighlight lang="j">require 'types/datetime'
parseTimes=: ([: _&".;._2 ,&':');._2
parseTimes=: ([: _&".;._2 ,&':');._2
secsFromTime=: 24 60 60 #. ] NB. convert from time to seconds
secsFromTime=: 24 60 60 #. ] NB. convert from time to seconds
rft=: 2r86400p1 * secsFromTime NB. convert from time to radians
rft=: 2r86400p1 * secsFromTime NB. convert from time to radians
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes</lang>
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes</syntaxhighlight>
{{out|Example Use}}
{{out|Example Use}}
<lang J> meanTime '23:00:17 23:40:20 00:12:45 00:17:19 '
<syntaxhighlight lang="j"> meanTime '23:00:17 23:40:20 00:12:45 00:17:19 '
23:47:43</lang>
23:47:43</syntaxhighlight>

=={{header|Java}}==
{{trans|Kotlin}}
<syntaxhighlight lang="java">public class MeanTimeOfDay {
static double meanAngle(double[] angles) {
int len = angles.length;
double sinSum = 0.0;
for (int i = 0; i < len; i++) {
sinSum += Math.sin(angles[i] * Math.PI / 180.0);
}
double cosSum = 0.0;
for (int i = 0; i < len; i++) {
cosSum += Math.cos(angles[i] * Math.PI / 180.0);
}

return Math.atan2(sinSum / len, cosSum / len) * 180.0 / Math.PI;
}

/* time string assumed to be in format "hh:mm:ss" */
static int timeToSecs(String t) {
int hours = Integer.parseInt(t.substring(0, 2));
int mins = Integer.parseInt(t.substring(3, 5));
int secs = Integer.parseInt(t.substring(6, 8));
return 3600 * hours + 60 * mins + secs;
}

/* 1 second of time = 360/(24 * 3600) = 1/240th degree */
static double timeToDegrees(String t) {
return timeToSecs(t) / 240.0;
}

static String degreesToTime(double d) {
if (d < 0.0) d += 360.0;
int secs = (int)(d * 240.0);
int hours = secs / 3600;
int mins = secs % 3600;
secs = mins % 60;
mins /= 60;
return String.format("%2d:%2d:%2d", hours, mins, secs);
}

public static void main(String[] args) {
String[] tm = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"};
double[] angles = new double[4];
for (int i = 0; i < 4; i++) angles[i] = timeToDegrees(tm[i]);
double mean = meanAngle(angles);
System.out.println("Average time is : " + degreesToTime(mean));
}
}</syntaxhighlight>

{{out}}
<pre>
Average time is : 23:47:43
</pre>


=={{header|Javascript}}==
=={{header|Javascript}}==
{{works with|Node.js}}
{{works with|Node.js}}
<lang Javascript>var args = process.argv.slice(2);
<syntaxhighlight lang="javascript">var args = process.argv.slice(2);


function time_to_seconds( hms ) {
function time_to_seconds( hms ) {
var parts = hms.split(':');
var parts = hms.split(':');
if ( parts[0] < 12 ) {
var h = parseInt(parts[0]);
parts[0] = 24;
var m = parseInt(parts[1]);
var s = parseInt(parts[2]);
if ( h < 12 ) {
h += 24;
}
}
var seconds = parseInt(parts[0]) * 60 * 60 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
var seconds = parseInt(parts[0]) * 60 * 60 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
Line 812: Line 1,362:
var seconds = Math.floor( sum / count )
var seconds = Math.floor( sum / count )
console.log( 'Mean time is ', seconds_to_time(seconds));
console.log( 'Mean time is ', seconds_to_time(seconds));
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 822: Line 1,372:


The "mean time" of two times that differ by 12 hours (e.g. ["00:00:00", "12:00:00"]) is not very well-defined, and is accordingly computed as null here.
The "mean time" of two times that differ by 12 hours (e.g. ["00:00:00", "12:00:00"]) is not very well-defined, and is accordingly computed as null here.
<lang jq># input: array of "h:m:s"
<syntaxhighlight lang="jq"># input: array of "h:m:s"
def mean_time_of_day:
def mean_time_of_day:
def pi: 4 * (1|atan);
def pi: 4 * (1|atan);
Line 852: Line 1,402:
| round
| round
| secs2time
| secs2time
end ;</lang>
end ;</syntaxhighlight>
'''Examples'''
'''Examples'''
<lang jq>["0:0:0", "12:0:0" ],
<syntaxhighlight lang="jq">["0:0:0", "12:0:0" ],
["0:0:0", "24:0:0" ],
["0:0:0", "24:0:0" ],
["1:0:0", "1:0:0" ],
["1:0:0", "1:0:0" ],
Line 861: Line 1,411:
["23:0:0", "23:0:0" ],
["23:0:0", "23:0:0" ],
["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
| mean_time_of_day</lang>
| mean_time_of_day</syntaxhighlight>
{{out}}
{{out}}
<lang sh>$ jq -r -n -f Mean_time_of_day.jq
<syntaxhighlight lang="sh">$ jq -r -n -f Mean_time_of_day.jq
null
null
00:00:00
00:00:00
Line 870: Line 1,420:
00:00:01
00:00:01
23:00:00
23:00:00
23:47:43</lang>
23:47:43</syntaxhighlight>

=={{header|Julia}}==
{{works with|Julia|0.6}}
{{trans|MATLAB}}
<syntaxhighlight lang="julia">using Statistics

function meantime(times::Array, dlm::String=":")
c = π / (12 * 60 * 60)
a = map(x -> parse.(Int, x), split.(times, dlm))
ϕ = collect(3600t[1] + 60t[2] + t[3] for t in a)
d = angle(mean(exp.(c * im * ϕ))) / 2π # days
if d < 0 d += 1 end
# Convert to h:m:s
h = trunc(Int, d * 24)
m = trunc(Int, d * 24 * 60) - h * 60
s = trunc(Int, d * 24 * 60 * 60) - h * 60 * 60 - m * 60
return "$h:$m:$s"
end

times = String["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
mtime = meantime(times)
println("Times:")
println.(times)
println("Mean: $mtime")</syntaxhighlight>

{{out}}
<pre>Times:
23:00:17
23:40:20
00:12:45
00:17:19
Mean: 23:47:43</pre>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
<lang scala>// version 1.0.6
<syntaxhighlight lang="scala">// version 1.0.6


fun meanAngle(angles: DoubleArray): Double {
fun meanAngle(angles: DoubleArray): Double {
Line 909: Line 1,491:
val mean = meanAngle(angles)
val mean = meanAngle(angles)
println("Average time is : ${degreesToTime(mean)}")
println("Average time is : ${degreesToTime(mean)}")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 917: Line 1,499:


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
global pi
global pi
pi = acs(-1)
pi = acs(-1)
Line 963: Line 1,545:
atan2 = (y=0)*(x<0)*pi
atan2 = (y=0)*(x<0)*pi
End Function
End Function
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 973: Line 1,555:
00:17:19
00:17:19
is 23:47:43
is 23:47:43
</pre>

=={{header|Lua}}==
<syntaxhighlight lang="lua">
local times = {"23:00:17","23:40:20","00:12:45","00:17:19"}

-- returns time converted to a radian format
local function timeToAngle(str)
local h,m,s = str:match("(..):(..):(..)")
return (h + m / 60 + s / 3600)/12 * math.pi
end

-- computes the mean of the angles inside a list
local function meanAngle(angles)
local sumSin,sumCos = 0,0
for k,v in pairs(angles) do
sumSin = sumSin + math.sin(v)
sumCos = sumCos + math.cos(v)
end
return math.atan2(sumSin,sumCos)
end

-- converts and angle back to a time string
local function angleToTime(angle)
local abs = angle % (math.pi * 2)
local time = abs / math.pi * 12
local h = math.floor(time)
local m = math.floor(time * 60) % 60
local s = math.floor(time * 3600) % 60
return string.format("%02d:%02d:%02d", h, m, s)
end

-- convert times to angles
for k,v in pairs(times) do
times[k] = timeToAngle(v)
end

print(angleToTime(meanAngle(times)))
</syntaxhighlight>

{{out}}
<pre>
23:47:43
</pre>
</pre>


=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<lang mathematica>meanTime[list_] :=
<syntaxhighlight lang="mathematica">meanTime[list_] :=
StringJoin@
StringJoin@
Riffle[ToString /@
Riffle[ToString /@
Line 983: Line 1,608:
Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@
Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@
list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"];
list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"];
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]</lang>
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]</syntaxhighlight>
{{Out}}
{{Out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>


=={{header|MATLAB}} / {{header|Octave}}==
=={{header|MATLAB}} / {{header|Octave}}==
<lang MATLAB>function t = mean_time_of_day(t)
<syntaxhighlight lang="matlab">function t = mean_time_of_day(t)
c = pi/(12*60*60);
c = pi/(12*60*60);
for k=1:length(t)
for k=1:length(t)
Line 997: Line 1,622:
if (d<0) d += 1;
if (d<0) d += 1;
t = datestr(d,"HH:MM:SS");
t = datestr(d,"HH:MM:SS");
end; </lang>
end; </syntaxhighlight>
<pre>mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'})
<pre>mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'})
ans = 23:47:43
ans = 23:47:43
Line 1,003: Line 1,628:


=={{header|Nim}}==
=={{header|Nim}}==
{{works with|Nim|0.20.0+}}
<lang nim>import math, complex, strutils, sequtils
<syntaxhighlight lang="nim">import math, complex, strutils, sequtils
proc rect(r, phi: float): Complex = (r * cos(phi), sin(phi))
proc phase(c: Complex): float = arctan2(c.im, c.re)
proc radians(x: float): float = (x * Pi) / 180.0
proc degrees(x: float): float = (x * 180.0) / Pi
proc meanAngle(deg: openArray[float]): float =
proc meanAngle(deg: openArray[float]): float =
var c: Complex
var c: Complex[float]
for d in deg:
for d in deg:
c += rect(1.0, radians(d))
c += rect(1.0, degToRad(d))
degrees(phase(c / float(deg.len)))
radToDeg(phase(c / float(deg.len)))
proc meanTime(times: openArray[string]): string =
proc meanTime(times: openArray[string]): string =
Line 1,028: Line 1,648:
align($h, 2, '0') & ":" & align($m, 2, '0') & ":" & align($s, 2, '0')
align($h, 2, '0') & ":" & align($m, 2, '0') & ":" & align($s, 2, '0')
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</lang>
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>
Line 1,034: Line 1,654:
=={{header|Oberon-2}}==
=={{header|Oberon-2}}==
{{works with|oo2c}}
{{works with|oo2c}}
<lang oberon2>
<syntaxhighlight lang="oberon2">
MODULE AvgTimeOfDay;
MODULE AvgTimeOfDay;
IMPORT
IMPORT
Line 1,105: Line 1,725:


END AvgTimeOfDay.
END AvgTimeOfDay.
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,112: Line 1,732:


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml>let pi_twice = 2.0 *. 3.14159_26535_89793_23846_2643
<syntaxhighlight lang="ocaml">let pi_twice = 2.0 *. 3.14159_26535_89793_23846_2643
let day = float (24 * 60 * 60)
let day = float (24 * 60 * 60)


Line 1,148: Line 1,768:
Printf.printf "The mean time of [%s] is: %s\n"
Printf.printf "The mean time of [%s] is: %s\n"
(String.concat "; " times)
(String.concat "; " times)
(string_of_time (mean_time (List.map parse_time times)))</lang>
(string_of_time (mean_time (List.map parse_time times)))</syntaxhighlight>
{{out}}
{{out}}
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43


=={{header|ooRexx}}==
=={{header|ooRexx}}==
<lang oorexx>/* REXX ---------------------------------------------------------------
<syntaxhighlight lang="oorexx">/* REXX ---------------------------------------------------------------
* 25.06.2014 Walter Pachl
* 25.06.2014 Walter Pachl
*--------------------------------------------------------------------*/
*--------------------------------------------------------------------*/
Line 1,188: Line 1,808:
f2: return right(format(arg(1),2,0),2,0)
f2: return right(format(arg(1),2,0),2,0)


::requires rxmath library</lang>
::requires rxmath library</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>


=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
<lang parigp>meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
<syntaxhighlight lang="parigp">meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
meanTime(v)=my(x=meanAngle(2*Pi*apply(u->u[1]/24+u[2]/1440+u[3]/86400, v))*12/Pi); [x\1, 60*(x-=x\1)\1, round(60*(60*x-60*x\1))]
meanTime(v)=my(x=meanAngle(2*Pi*apply(u->u[1]/24+u[2]/1440+u[3]/86400, v))*12/Pi); [x\1, 60*(x-=x\1)\1, round(60*(60*x-60*x\1))]
meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</lang>
meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</syntaxhighlight>
{{out}}
{{out}}
<pre>[23, 47, 43]</pre>
<pre>[23, 47, 43]</pre>


=={{header|Perl}}==
=={{header|Perl}}==
===Traditional===
<lang Perl>use Const::Fast;
Using the core module <code>Math::Complex</code> to enable use of complex numbers. The <code>POSIX</code> CPAN module provides the <code>fmod</code> routine for non-integer modulus calculations.
const my $SECONDS_IN_HOUR => 60 * 60;
{{trans|Raku}}
const my $SECONDS_IN_MINUTE => 60;
<syntaxhighlight lang="perl">use strict;
use warnings;
use POSIX 'fmod';
use Math::Complex;
use List::Util qw(sum);
use utf8;


use constant τ => 2 * 3.1415926535;
sub hms_2_seconds {
my ( $hms ) = @_;
my ( $h, $m, $s ) = split /:/, $hms;
$h += 24 if $h < 12;
return $s + $m * $SECONDS_IN_MINUTE + $h * $SECONDS_IN_HOUR;
}
sub seconds_2_hms {
my ( $seconds ) = @_;


# time-of-day to radians
my ( $h, $m );
sub tod2rad {
($h,$m,$s) = split /:/, @_[0];
(3600*$h + 60*$m + $s) * τ / 86400;
}


# radians to time-of-day
$h = int( $seconds / $SECONDS_IN_HOUR );
sub rad2tod {
$seconds = $seconds % $SECONDS_IN_HOUR;
my $x = $_[0] * 86400 / τ;
sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60);
}


# float modulus, normalized to positive values
$m = int( $seconds / $SECONDS_IN_MINUTE );
sub fm {
$seconds = $seconds % $SECONDS_IN_MINUTE;
my($n,$b) = @_;

$x = fmod($n,$b);
return sprintf "%02s:%02s:%02s", $h, $m, $seconds;
$x += $b if $x < 0;
}
}


sub phase { arg($_[0]) } # aka theta
my @hms = split /,\s+/, scalar <STDIN>;
sub cis { cos($_[0]) + i*sin($_[0]) }

sub mean_time { rad2tod phase sum map { cis tod2rad $_ } @_ }
my ($sum, $count);
for my $time ( @hms) {
$sum += hms_2_seconds $time;
$count++;
}
say seconds_2_hms int( $sum / $count );</lang>


@times = ("23:00:17", "23:40:20", "00:12:45", "00:17:19");
print mean_time(@times) . " is the mean time of " . join(' ', @times) . "\n";</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19</pre>
<pre>
===v5.36===
$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | mean_time.pl
As previous, but using features from an up-to-date release of Perl, e.g. strict/warn/subroutine signatures without the <code>use</code> boilerplate.
23:47:40
<syntaxhighlight lang="perl">use v5.36;
</pre>
use POSIX 'fmod';
use Math::Complex;
use List::Util 'sum';
use utf8;


use constant τ => 2 * 2 * atan2(1, 0);
=={{header|Perl 6}}==
{{works with|Rakudo|2015.12}}


sub R_to_ToD ($radians) { my $x = $radians * 86400 / τ; sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60) }
<lang perl6>sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * tau / 86400 }
sub ToD_to_R ($h,$m,$s) { (3600*$h + 60*$m + $s) * τ / 86400 }
sub fm ($n,$b) { my $x = fmod($n,$b); $x += $b if $x < 0 }
sub rad2tod ($r) {
sub cis ($radians) { cos($radians) + i*sin($radians) }
my $x = $r * 86400 / tau;
(($x xx 3 Z/ 3600,60,1) Z% 24,60,60).fmt('%02d',':');
sub phase ($Θ) { arg() }
sub mean_time(@t) { R_to_ToD phase sum map { cis ToD_to_R split ':', $_ } @t }
}
sub phase ($c) { $c.polar[1] }
sub mean-time (@t) { rad2tod phase [+] map { cis tod2rad $_ }, @t }

my @times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"];
say "{ mean-time(@times) } is the mean time of @times[]";</lang>


my @times = <23:00:17 23:40:20 00:12:45 00:17:19>;
say my $result = mean_time(@times) . ' is the mean time of ' . join ' ', @times;</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19</pre>
<pre>
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
</pre>


=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function atan2(atom y, atom x)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
return 2*arctan((sqrt(power(x,2)+power(y,2))-x)/y)
<span style="color: #008080;">function</span> <span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #004080;">atom</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">angles</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
function MeanAngle(sequence angles)
<span style="color: #004080;">atom</span> <span style="color: #000000;">ai_rad</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">angles</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]*</span><span style="color: #004600;">PI</span><span style="color: #0000FF;">/</span><span style="color: #000000;">180</span>
atom x=0, y=0, ai_rad
<span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">cos</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span>
integer l=length(angles)
<span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">sin</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ai_rad</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to l do
<span style="color: #008080;">if</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">1e-16</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"not meaningful"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ai_rad = angles[i]*PI/180
<span style="color: #008080;">return</span> <span style="color: #7060A8;">atan2</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">180</span><span style="color: #0000FF;">/</span><span style="color: #004600;">PI</span>
x += cos(ai_rad)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
y += sin(ai_rad)
end for
<span style="color: #008080;">function</span> <span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hours</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">minutes</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">seconds</span><span style="color: #0000FF;">)</span>
if abs(x)<1e-16 then return "not meaningful" end if
<span style="color: #008080;">return</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">hours</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">+</span><span style="color: #000000;">minutes</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">+</span><span style="color: #000000;">seconds</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">24</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">360</span>
return atan2(y,x)*180/PI
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function
<span style="color: #008080;">constant</span> <span style="color: #000000;">Times</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">),</span>
function toSecAngle(integer hours, integer minutes, integer seconds)
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">40</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">),</span>
return ((hours*60+minutes)*60+seconds)/(24*60*60)*360
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">45</span><span style="color: #0000FF;">),</span>
end function
<span style="color: #000000;">toSecAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">00</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">)}</span>

constant Times = {toSecAngle(23,00,17),
<span style="color: #008080;">function</span> <span style="color: #000000;">toHMS</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
toSecAngle(23,40,20),
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
toSecAngle(00,12,45),
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">+=</span><span style="color: #000000;">360</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
toSecAngle(00,17,19)}
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">24</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">60</span><span style="color: #0000FF;">*</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">360</span>

<span style="color: #004080;">atom</span> <span style="color: #000000;">hours</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3600</span><span style="color: #0000FF;">),</span>
function toHMS(object s)
<span style="color: #000000;">mins</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3600</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">60</span><span style="color: #0000FF;">),</span>
if not string(s) then
<span style="color: #000000;">secs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">60</span><span style="color: #0000FF;">)</span>
if s<0 then s+=360 end if
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%02d:%02d:%02d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">hours</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mins</span><span style="color: #0000FF;">,</span><span style="color: #000000;">secs</span><span style="color: #0000FF;">})</span>
s = 24*60*60*s/360
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
s = sprintf("%02d:%02d:%02d",{floor(s/3600),floor(remainder(s,3600)/60),remainder(s,60)})
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
return s
end function
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Mean Time is %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">toHMS</span><span style="color: #0000FF;">(</span><span style="color: #000000;">MeanAngle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Times</span><span style="color: #0000FF;">))})</span>

<!--</syntaxhighlight>-->
printf(1,"Mean Time is %s\n",{toHMS(MeanAngle(Times))})
{} = wait_key()</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,306: Line 1,924:


=={{header|PHP}}==
=={{header|PHP}}==
<syntaxhighlight lang="php">
<lang PHP>
<?php
<?php
function time2ang($tim) {
function time2ang($tim) {
Line 1,344: Line 1,962:
print "The mean time of day is $result (angle $ma).\n";
print "The mean time of day is $result (angle $ma).\n";
?>
?>
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,352: Line 1,970:


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(load "@lib/math.l")
<syntaxhighlight lang="picolisp">(load "@lib/math.l")


(de meanTime (Lst)
(de meanTime (Lst)
Line 1,361: Line 1,979:
(sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) )
(sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) )
43200 pi )
43200 pi )
(tim$ (% (+ Tim 86400) 86400) T) ) )</lang>
(tim$ (% (+ Tim 86400) 86400) T) ) )</syntaxhighlight>
{{out|Test}}
{{out|Test}}
<lang PicoLisp>: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
<syntaxhighlight lang="picolisp">: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
-> "23:47:43"</lang>
-> "23:47:43"</syntaxhighlight>


=={{header|PL/I}}==
=={{header|PL/I}}==
<lang pli>*process source attributes xref;
<syntaxhighlight lang="pli">*process source attributes xref;
avt: Proc options(main);
avt: Proc options(main);
/*--------------------------------------------------------------------
/*--------------------------------------------------------------------
Line 1,412: Line 2,030:
End;
End;


End;</lang>
End;</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-MeanTimeOfDay
function Get-MeanTimeOfDay
{
{
Line 1,484: Line 2,102:
}
}
}
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
[timespan]$meanTimeOfDay = "23:00:17","23:40:20","00:12:45","00:17:19" | Get-MeanTimeOfDay
[timespan]$meanTimeOfDay = "23:00:17","23:40:20","00:12:45","00:17:19" | Get-MeanTimeOfDay
"Mean time is {0}" -f (Get-Date $meanTimeOfDay.ToString()).ToString("hh:mm:ss tt")
"Mean time is {0}" -f (Get-Date $meanTimeOfDay.ToString()).ToString("hh:mm:ss tt")
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,495: Line 2,113:


=={{header|Python}}==
=={{header|Python}}==
<lang python>from cmath import rect, phase
<syntaxhighlight lang="python">from cmath import rect, phase
from math import radians, degrees
from math import radians, degrees


Line 1,518: Line 2,136:


if __name__ == '__main__':
if __name__ == '__main__':
print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )</lang>
print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>


=={{header|Racket}}==
=={{header|Racket}}==
<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket
(define (mean-angle/radians as)
(define (mean-angle/radians as)
Line 1,544: Line 2,162:
(loop q (cons (~r r #:min-width 2 #:pad-string "0") ts))))))
(loop q (cons (~r r #:min-width 2 #:pad-string "0") ts))))))
(mean-time '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
(mean-time '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>"23:47:43"</pre>
<pre>"23:47:43"</pre>


=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2015.12}}

<syntaxhighlight lang="raku" line>sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * tau / 86400 }
sub rad2tod ($r) {
my $x = $r * 86400 / tau;
(($x xx 3 Z/ 3600,60,1) Z% 24,60,60).fmt('%02d',':');
}
sub phase ($c) { $c.polar[1] }
sub mean-time (@t) { rad2tod phase [+] map { cis tod2rad $_ }, @t }

my @times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"];
say "{ mean-time(@times) } is the mean time of @times[]";</syntaxhighlight>

{{out}}
<pre>
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19
</pre>


=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/* REXX ---------------------------------------------------------------
<syntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 25.06.2014 Walter Pachl
* 25.06.2014 Walter Pachl
* taken from ooRexx using my very aged sin/cos/artan functions
* taken from ooRexx using my very aged sin/cos/artan functions
Line 1,649: Line 2,290:
End
End
Numeric Digits (prec)
Numeric Digits (prec)
Return r+0</lang>
Return r+0</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>

=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
≪ → angles
≪ 0 1 angles SIZE '''FOR''' j
1 angles j GET R→C P→R + '''NEXT'''
angles SIZE / ARG
≫ ≫ ''''MEANG'''' STO

≪ → times
≪ { } 1 times SIZE '''FOR''' j
1 times j GET HMS→ 15 * + '''NEXT'''
'''MEANG''' 15 / 24 MOD →HMS 4 FIX RND STD
≫ ≫ ''''MTIME'''' STO

{23.0017 23.4020 0.1245 0.1719 } '''MTIME'''
{{out}}
<pre>
1: 23.4743
</pre>


=={{header|Ruby}}==
=={{header|Ruby}}==
Using the methods at [[http://rosettacode.org/wiki/Averages/Mean_angle#Ruby|Averages/Mean angle]]
Using the methods at [[http://rosettacode.org/wiki/Averages/Mean_angle#Ruby|Averages/Mean angle]]


<lang ruby>def time2deg(t)
<syntaxhighlight lang="ruby">def time2deg(t)
raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/)
raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/)
hh,mm,ss = m[1..3].map {|e| e.to_i}
hh,mm,ss = m[1..3].map {|e| e.to_i}
Line 1,674: Line 2,335:
end
end


puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]</lang>
puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]</syntaxhighlight>
{{out}}
{{out}}
23:47:43
23:47:43


=={{header|Run BASIC}}==
=={{header|Run BASIC}}==
<lang runbasic>global pi
<syntaxhighlight lang="runbasic">global pi
pi = acs(-1)
pi = acs(-1)
Line 1,722: Line 2,383:
atan2 = (y=0)*(x<0)*pi
atan2 = (y=0)*(x<0)*pi
end if
end if
End Function</lang>
End Function</syntaxhighlight>
=={{header|Rust}}==
<syntaxhighlight lang="rust">
use std::f64::consts::PI;

#[derive(Debug, PartialEq, Eq)]
struct Time {
h: u8,
m: u8,
s: u8,
}

impl Time {
/// Create a Time from equivalent radian measure
fn from_radians(mut rads: f64) -> Time {
rads %= 2.0 * PI;
if rads < 0.0 {
rads += 2.0 * PI
}
Time {
h: (rads * 12.0 / PI) as u8,
m: ((rads * 720.0 / PI) % 60.0) as u8,
s: ((rads * 43200.0 / PI) % 60.0).round() as u8,
}
}

/// Create a Time from H/M/S
fn from_parts(h: u8, m: u8, s: u8) -> Result<Time, ()> {
if h > 23 || m > 59 || s > 59 {
return Err(());
}
Ok(Time { h, m, s })
}

/// Return time as measure in radians
fn as_radians(&self) -> f64 {
((self.h as f64 / 12.0) + (self.m as f64 / 720.0) + (self.s as f64 / 43200.0)) * PI
}
}

/// Compute the mean time from a slice of times
fn mean_time(times: &[Time]) -> Time {
// compute sum of sines and cosines
let (ss, sc) = times
.iter()
.map(Time::as_radians)
.map(|a| (a.sin(), a.cos()))
.fold((0.0, 0.0), |(ss, sc), (s, c)| (ss + s, sc + c));
// scaling does not matter for atan2, meaning we do not have to divide sums by len
Time::from_radians(ss.atan2(sc))
}

fn main() {
let times = [
Time::from_parts(23, 00, 17).unwrap(),
Time::from_parts(23, 40, 20).unwrap(),
Time::from_parts(00, 12, 45).unwrap(),
Time::from_parts(00, 17, 19).unwrap(),
];

let mean = mean_time(&times);

println!("{:02}:{:02}:{:02}", mean.h, mean.m, mean.s);
}

</syntaxhighlight>
{{out}}
<pre>
23:47:43
</pre>


=={{header|Scala}}==
=={{header|Scala}}==
{{libheader|java.time.LocalTime}}<lang Scala>import java.time.LocalTime
{{libheader|java.time.LocalTime}}<syntaxhighlight lang="scala">import java.time.LocalTime
import scala.compat.Platform
import scala.compat.Platform


Line 1,754: Line 2,484:
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40")
assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40")
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")
println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")
}</lang>
}</syntaxhighlight>


=={{header|Scheme}}==
=={{header|Scheme}}==
Line 1,761: Line 2,491:
To be self-contained, this starts with the functions from [[Averages/Mean angle]]
To be self-contained, this starts with the functions from [[Averages/Mean angle]]


<lang scheme>
<syntaxhighlight lang="scheme">
(import (scheme base)
(import (scheme base)
(scheme inexact)
(scheme inexact)
Line 1,814: Line 2,544:
(write (mean-time-of-day '("23:00:17" "23:40:20" "00:12:45" "00:17:19")))
(write (mean-time-of-day '("23:00:17" "23:40:20" "00:12:45" "00:17:19")))
(newline)
(newline)
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,824: Line 2,554:
{{trans|Ruby}}
{{trans|Ruby}}
Using the '''mean_angle()''' function from: [http://rosettacode.org/wiki/Averages/Mean_angle#Sidef "Averages/Mean angle"]
Using the '''mean_angle()''' function from: [http://rosettacode.org/wiki/Averages/Mean_angle#Sidef "Averages/Mean angle"]
<lang ruby>func time2deg(t) {
<syntaxhighlight lang="ruby">func time2deg(t) {
(var m = t.match(/^(\d\d):(\d\d):(\d\d)$/)) || die "invalid time"
(var m = t.match(/^(\d\d):(\d\d):(\d\d)$/)) || die "invalid time"
var (hh,mm,ss) = m.cap.map{.to_i}...
var (hh,mm,ss) = m.cap.map{.to_i}...
Line 1,840: Line 2,570:
}
}
 
 
say mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</lang>
say mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])</syntaxhighlight>
{{out}}
{{out}}
<pre>23:47:43</pre>
<pre>23:47:43</pre>
Line 1,846: Line 2,576:
=={{header|SQL}}/{{header|PostgreSQL}}==
=={{header|SQL}}/{{header|PostgreSQL}}==
{{trans|Python}}
{{trans|Python}}
<syntaxhighlight lang="sql">
<lang SQL>
--Setup table for testing
--Setup table for testing
CREATE TABLE time_table(times time);
CREATE TABLE time_table(times time);
Line 1,859: Line 2,589:
(SELECT EXTRACT(epoch from times) t
(SELECT EXTRACT(epoch from times) t
FROM time_table) T1
FROM time_table) T1
)T2</lang>
)T2</syntaxhighlight>


Output:
Output:
Line 1,865: Line 2,595:
23:47:43.361529
23:47:43.361529
</pre>
</pre>

=={{header|Swift}}==

<syntaxhighlight lang="swift">import Foundation

@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 }
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi }

public func meanOfAngles(_ angles: [Double]) -> Double {
let cInv = 1 / Double(angles.count)
let (y, x) =
angles.lazy
.map(d2r)
.map({ (sin($0), cos($0)) })
.reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 })

return r2d(atan2(cInv * y, cInv * x))
}

struct DigitTime {
var hour: Int
var minute: Int
var second: Int

init?(fromString str: String) {
let split = str.components(separatedBy: ":").compactMap(Int.init)

guard split.count == 3 else {
return nil
}

(hour, minute, second) = (split[0], split[1], split[2])
}

init(fromDegrees angle: Double) {
let totalSeconds = 24 * 60 * 60 * angle / 360

second = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
minute = Int((totalSeconds.truncatingRemainder(dividingBy: 3600) - Double(second)) / 60)
hour = Int(totalSeconds / 3600)
}

func toDegrees() -> Double {
return 360 * Double(hour) / 24.0 + 360 * Double(minute) / (24 * 60.0) + 360 * Double(second) / (24 * 3600.0)
}
}

extension DigitTime: CustomStringConvertible {
var description: String { String(format: "%02i:%02i:%02i", hour, minute, second) }
}

let times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"].compactMap(DigitTime.init(fromString:))

guard times.count == 4 else {
fatalError()
}

let meanTime = DigitTime(fromDegrees: 360 + meanOfAngles(times.map({ $0.toDegrees() })))

print("Given times \(times), the mean time is \(meanTime)")</syntaxhighlight>

{{out}}

<pre>Given times [23:00:17, 23:40:20, 00:12:45, 00:17:19], the mean time is 23:47:43</pre>


=={{header|Tcl}}==
=={{header|Tcl}}==
<lang tcl>proc meanTime {times} {
<syntaxhighlight lang="tcl">proc meanTime {times} {
set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}]
set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}]
set sumSin [set sumCos 0.0]
set sumSin [set sumCos 0.0]
Line 1,884: Line 2,678:
}
}


puts [meanTime {23:00:17 23:40:20 00:12:45 00:17:19}]</lang>
puts [meanTime {23:00:17 23:40:20 00:12:45 00:17:19}]</syntaxhighlight>
{{out}}
{{out}}
23:47:43
23:47:43

=={{header|VBA}}==
Uses Excel and [[Averages/Mean_angle#VBA|mean angle]].
<syntaxhighlight lang="vb">Public Sub mean_time()
Dim angles() As Double
s = [{"23:00:17","23:40:20","00:12:45","00:17:19"}]
For i = 1 To UBound(s)
s(i) = 360 * TimeValue(s(i))
Next i
Debug.Print Format(mean_angle(s) / 360 + 1, "hh:mm:ss")
End Sub</syntaxhighlight>{{out}}
<pre>23:47:43</pre>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Module Module1

Function TimeToDegrees(time As TimeSpan) As Double
Return 360 * time.Hours / 24.0 + 360 * time.Minutes / (24 * 60.0) + 360 * time.Seconds / (24 * 3600.0)
End Function

Function DegreesToTime(angle As Double) As TimeSpan
Return New TimeSpan((24 * 60 * 60 * angle \ 360) \ 3600, ((24 * 60 * 60 * angle \ 360) Mod 3600 - (24 * 60 * 60 * angle \ 360) Mod 60) \ 60, (24 * 60 * 60 * angle \ 360) Mod 60)
End Function

Function MeanAngle(angles As List(Of Double)) As Double
Dim y_part = 0.0
Dim x_part = 0.0
Dim numItems = angles.Count

For Each angle In angles
x_part += Math.Cos(angle * Math.PI / 180)
y_part += Math.Sin(angle * Math.PI / 180)
Next

Return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI
End Function

Sub Main()
Dim digitimes As New List(Of Double)
Dim digitime As TimeSpan
Dim input As String

Console.WriteLine("Enter times, end with no input: ")
Do
input = Console.ReadLine
If Not String.IsNullOrWhiteSpace(input) Then
If TimeSpan.TryParse(input, digitime) Then
digitimes.Add(TimeToDegrees(digitime))
Else
Console.WriteLine("Seems this is wrong input: ingnoring time")
End If
End If
Loop Until String.IsNullOrWhiteSpace(input)

If digitimes.Count > 0 Then
Console.WriteLine("The mean time is : {0}", DegreesToTime(360 + MeanAngle(digitimes)))
End If
End Sub

End Module</syntaxhighlight>
{{out}}
<pre>Enter times, end with no input:
23:00:17
23:40:20
00:12:45
00:17:19

The mean time is : 23:47:43</pre>

=={{header|V (Vlang)}}==
{{trans|Wren}}
<syntaxhighlight lang="v (vlang)">import math

const inputs = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
fn main() {
angles := inputs.map(time_to_degs(it))
println('Mean time of day is: ${degs_to_time(mean_angle(angles))}')
}
fn mean_angle(angles []f64) f64 {
n := angles.len
mut sin_sum := f64(0)
mut cos_sum := f64(0)
for angle in angles {
sin_sum += math.sin(angle * math.pi / 180)
cos_sum += math.cos(angle * math.pi / 180)
}
return math.atan2(sin_sum/n, cos_sum/n) * 180 / math.pi
}

fn degs_to_time(dd f64) string{
mut d := dd
for d < 0 {
d += 360
}
mut s := math.round(d * 240)
h := math.floor(s/3600)
mut m := math.fmod(s, 3600)
s = math.fmod(m, 60)
m = math.floor(m / 60)
return "${h:02}:${m:02}:${s:02}"
}
fn time_to_degs(time string) f64 {
t := time.split(":")
h := t[0].f64() * 3600
m := t[1].f64() * 60
s := t[2].f64()
return (h + m + s) / 240
}</syntaxhighlight>

{{out}}
<pre>
Mean time of day is: 23:47:43
</pre>

=={{header|Wren}}==
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt

var timeToDegs = Fn.new { |time|
var t = time.split(":")
var h = Num.fromString(t[0]) * 3600
var m = Num.fromString(t[1]) * 60
var s = Num.fromString(t[2])
return (h + m + s) / 240
}

var degsToTime = Fn.new { |d|
while (d < 0) d = d + 360
var s = (d * 240).round
var h = (s/3600).floor
var m = s % 3600
s = m % 60
m = (m / 60).floor
return Fmt.swrite("$2d:$2d:$2d", h, m, s)
}

var meanAngle = Fn.new { |angles|
var n = angles.count
var sinSum = 0
var cosSum = 0
for (angle in angles) {
sinSum = sinSum + (angle * Num.pi / 180).sin
cosSum = cosSum + (angle * Num.pi / 180).cos
}
return (sinSum/n).atan(cosSum/n) * 180 / Num.pi
}

var times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
var angles = times.map { |t| timeToDegs.call(t) }.toList
System.print("Mean time of day is : %(degsToTime.call(meanAngle.call(angles)))")</syntaxhighlight>

{{out}}
<pre>
Mean time of day is : 23:47:43
</pre>


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>include c:\cxpl\codes;
<syntaxhighlight lang="xpl0">include c:\cxpl\codes;


proc NumOut(N); \Display 2-digit N with leading zero
proc NumOut(N); \Display 2-digit N with leading zero
Line 1,925: Line 2,877:
];
];


TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))</lang>
TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
23:47:43
23:47:43
</pre>
</pre>

=={{header|Yabasic}}==
{{trans|Phix}}
<syntaxhighlight lang="yabasic">sub atan2(y, x)
return 2 * atan((sqrt(x **2 + y ** 2) - x) / y)
end sub
sub MeanAngle(angles())
local x, y, ai_rad, l, i
l = arraysize(angles(), 1)
for i = 1 to l
ai_rad = angles(i) * PI / 180
x = x + cos(ai_rad)
y = y + sin(ai_rad)
next i
if abs(x) < 1e-16 return false
return atan2(y, x) * 180 / PI
end sub
sub toSecAngle(hours, minutes, seconds)
return ((hours * 60 + minutes) * 60 + seconds) / (24 * 60 * 60) * 360
end sub

dim Times(4)

Times(1) = toSecAngle(23,00,17)
Times(2) = toSecAngle(23,40,20)
Times(3) = toSecAngle(00,12,45)
Times(4) = toSecAngle(00,17,19)

sub toHMS$(t)
local s$
if t then
if t < 0 t = t + 360
t = 24 * 60 * 60 * t / 360
s$ = str$(int(t / 3600), "%02g") + ":" + str$(int(mod(t, 3600) / 60), "%02g") + ":" + str$(int(mod(t, 60)), "%02g")
else
s$ = "not meaningful"
end if
return s$
end sub

print "Mean Time is ", toHMS$(MeanAngle(Times()))

// Output: Mean Time is 23:47:43
</syntaxhighlight>


=={{header|zkl}}==
=={{header|zkl}}==
Line 1,935: Line 2,936:
to task "Averages/Mean angle" and some on-the-fly
to task "Averages/Mean angle" and some on-the-fly
time-to-angle and back conversions.
time-to-angle and back conversions.
<lang zkl>var D=Time.Date;
<syntaxhighlight lang="zkl">var D=Time.Date;
fcn meanT(t1,t2,etc){
fcn meanT(t1,t2,etc){
ts:=vm.arglist.apply(fcn(hms){
ts:=vm.arglist.apply(fcn(hms){
Line 1,946: Line 2,947:
if(mt<0) mt+=24; //-0.204622-->23.7954
if(mt<0) mt+=24; //-0.204622-->23.7954
D.toHour(mt).concat(":")
D.toHour(mt).concat(":")
}</lang>
}</syntaxhighlight>
Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle.
Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle.
{{out}}
{{out}}

Latest revision as of 16:20, 27 December 2023

Task
Averages/Mean time of day
You are encouraged to solve this task according to the task description, using any language you may know.
Task

A particular activity of bats occurs at these times of the day:

23:00:17, 23:40:20, 00:12:45, 00:17:19

Using the idea that there are twenty-four hours in a day, which is analogous to there being 360 degrees in a circle, map times of day to and from angles; and using the ideas of Averages/Mean angle compute and show the average time of the nocturnal activity to an accuracy of one second of time.

See also

11l

Translation of: Python
F mean_angle(angles)
   V x = sum(angles.map(a -> cos(radians(a)))) / angles.len
   V y = sum(angles.map(a -> sin(radians(a)))) / angles.len
   R degrees(atan2(y, x))

F mean_time(times)
   V t = (times.map(time -> time.split(‘:’)))
   V seconds = (t.map(hms -> (Float(hms[2]) + Int(hms[1]) * 60 + Int(hms[0]) * 3600)))
   V day = 24 * 60 * 60
   V to_angles = seconds.map(s -> s * 360.0 / @day)
   V mean_as_angle = mean_angle(to_angles)
   V mean_seconds = round(mean_as_angle * day / 360.0)
   I mean_seconds < 0
      mean_seconds += day
   V h = mean_seconds I/ 3600
   V m = mean_seconds % 3600
   V s = m % 60
   m = m I/ 60
   R ‘#02:#02:#02’.format(h, m, s)

print(mean_time([‘23:00:17’, ‘23:40:20’, ‘00:12:45’, ‘00:17:19’]))
Output:
23:47:43

Action!

Action! does not support trigonometry, therefore a simple arithmetic solution has been proposed.

INCLUDE "H6:REALMATH.ACT"

DEFINE PTR="CARD"
TYPE Time=[BYTE s,m,h]
REAL r60

PROC PrintB2(BYTE b)
  IF b<10 THEN Put('0) FI
  PrintB(b)
RETURN

PROC PrintTime(Time POINTER t)
  PrintB2(t.h) Put(':)
  PrintB2(t.m) Put(':)
  PrintB2(t.s)
RETURN

PROC Decode(CHAR ARRAY st Time POINTER t)
  CHAR ARRAY tmp

  IF st(0)#8 THEN Break() FI
  SCopyS(tmp,st,1,2) t.h=ValB(tmp)
  SCopyS(tmp,st,4,5) t.m=ValB(tmp)
  SCopyS(tmp,st,7,8) t.s=ValB(tmp)
RETURN

PROC TimeToSeconds(Time POINTER t REAL POINTER seconds)
  REAL r

  IntToReal(t.h,seconds)
  RealMult(seconds,r60,seconds)
  IntToReal(t.m,r)
  RealAdd(seconds,r,seconds)
  RealMult(seconds,r60,seconds)
  IntToReal(t.s,r)
  RealAdd(seconds,r,seconds)
RETURN

PROC SecondsToTime(REAL POINTER seconds Time POINTER t)
  REAL tmp1,tmp2

  RealAssign(seconds,tmp1)
  RealMod(tmp1,r60,tmp2)
  t.s=RealToInt(tmp2)
  RealDivInt(tmp1,r60,tmp2)
  RealMod(tmp2,r60,tmp1)
  t.m=RealToInt(tmp1)
  RealDivInt(tmp2,r60,tmp1)
  t.h=RealToInt(tmp1)
RETURN

PROC AverageTime(PTR ARRAY times BYTE count Time POINTER res)
  BYTE i
  Time t
  REAL avg,rcount,seconds,halfDay,day

  IntToReal(0,avg)
  IntToReal(count,rcount)
  ValR("43200",halfDay) ;seconds in the half of day
  ValR("86400",day)     ;seconds in the whole day
  FOR i=0 TO count-1
  DO
    Decode(times(i),t)
    TimeToSeconds(t,seconds)
    IF RealLess(seconds,halfDay) THEN
      RealAdd(seconds,day,seconds) ;correction of time
    FI
    RealAdd(avg,seconds,avg)
  OD
  RealDivInt(avg,rcount,avg)
  WHILE RealGreaterOrEqual(avg,day)
  DO
    RealSub(avg,day,avg) ;correction of time
  OD
  SecondsToTime(avg,res)
RETURN

PROC Main()
  DEFINE COUNT="4"
  PTR ARRAY times(COUNT)
  Time t

  Put(125) PutE() ;clear the screen
  IntToReal(60,r60)
  times(0)="23:00:17" times(1)="23:40:20"
  times(2)="00:12:45" times(3)="00:17:19"

  AverageTime(times,COUNT,t)
  Print("Mean time is ") PrintTime(t)
RETURN
Output:

Screenshot from Atari 8-bit computer

Mean time is 23:47:40

Ada

with Ada.Calendar.Formatting;
with Ada.Command_Line;
with Ada.Numerics.Elementary_Functions;
with Ada.Strings.Fixed;
with Ada.Text_IO;

procedure Mean_Time_Of_Day is

   subtype Time        is Ada.Calendar.Time;
   subtype Time_Of_Day is Ada.Calendar.Day_Duration;
   subtype Time_String is String (1 .. 8);  --  "HH:MM:SS"

   type Time_List is array (Positive range <>) of Time_String;

   function Average_Time (List : Time_List) return Time_String is

      function To_Time (Time_Image : Time_String) return Time
      is (Ada.Calendar.Formatting.Value ("2000-01-01 " & Time_Image));

      function To_Time_Of_Day (TS : Time) return Time_Of_Day is
         use Ada.Calendar.Formatting;
         Hour_Part : constant Time_Of_Day := 60.0 * 60.0 * Hour (TS);
         Min_Part  : constant Time_Of_Day := 60.0 * Minute (TS);
         Sec_Part  : constant Time_Of_Day := Time_Of_Day (Second (TS));
      begin
         return Hour_Part + Min_Part + Sec_Part;
      end To_Time_Of_Day;

      function To_Time_Image (Angle : Time_Of_Day) return Time_String
      is
         use Ada.Calendar.Formatting;
         TOD : constant Time := Time_Of
           (Year => 2000, Month => 1, Day => 1,  --  Not used
            Seconds => Angle);
      begin
         return Ada.Strings.Fixed.Tail (Image (TOD), Time_String'Length);
      end To_Time_Image;

      function Average_Time_Of_Day (List : Time_List) return Time_Of_Day is
         use Ada.Numerics.Elementary_Functions;
         Cycle : constant Float := Float (Time_Of_Day'Last);
         X_Sum, Y_Sum : Float := 0.0;
         Angle        : Float;
      begin
         for Time_Stamp of List loop
            Angle := Float (To_Time_Of_Day (To_Time (Time_Stamp)));
            X_Sum := X_Sum + Cos (Angle, Cycle => Cycle);
            Y_Sum := Y_Sum + Sin (Angle, Cycle => Cycle);
         end loop;
         Angle := Arctan (Y_Sum, X_Sum, Cycle => Cycle);
         if Angle < 0.0 then
            Angle := Angle + Cycle;
         elsif Angle > Cycle then
            Angle := Angle - Cycle;
         end if;
         return Time_Of_Day (Angle);
      end Average_Time_Of_Day;

   begin
      return To_Time_Image (Average_Time_Of_Day (List));
   end Average_Time;

   use Ada.Command_Line;
   List : Time_List (1 .. Argument_Count);
begin
   if Argument_Count = 0 then
      raise Constraint_Error;
   end if;

   for A in 1 .. Argument_Count loop
      List (A) := Argument (A);
   end loop;
   Ada.Text_IO.Put_Line (Average_Time (List));

exception
   when others =>
      Ada.Text_IO.Put_Line ("Usage: mean_time_of_day <time-1> ...");
      Ada.Text_IO.Put_Line ("       <time-1> ...   'HH:MM:SS' format");
end Mean_Time_Of_Day;
Output:
% ./mean_time_of_day 23:00:17 23:40:20 00:12:45 00:17:19
23:47:43

ALGOL 68

Uses code from the Averages/Mean angle task, included here for convenience.

BEGIN # Mean time of day mapping time to angles                      #

    # code from the Averages/Mean angle task - angles are in degrees #
    PROC mean angle = ([]REAL angles)REAL:
    (
      INT size = UPB angles - LWB angles + 1;
      REAL y part := 0, x part := 0;
      FOR i FROM LWB angles TO UPB angles DO
          x part +:= cos (angles[i] * pi / 180);
          y part +:= sin (angles[i] * pi / 180)
      OD;
 
      arc tan2 (y part / size, x part / size) * 180 / pi
    );
    # end code from the Averages/Mean angle task                     #

    MODE TIME = STRUCT( INT hh, mm, ss );

    OP   TOANGLE = ( TIME t )REAL: ( ( ( ( ( ss OF t / 60 ) + mm OF t ) / 60 ) + hh OF t ) * 360 ) / 24;
    OP   TOTIME  = ( REAL a )TIME:
         BEGIN
            REAL t  := ( a * 24 ) / 360;
            WHILE t <  0 DO t +:= 24 OD;
            WHILE t > 24 DO t -:= 24 OD;
            INT  hh  = ENTIER t;
            t      -:= hh *:= 60;
            INT  mm  = ENTIER t;
            INT  ss  = ENTIER ( ( t - mm ) * 60 );
            ( hh, mm, ss )
         END # TOTIME # ;

    PROC mean time = ( []TIME times )TIME:
         BEGIN
            [ LWB times : UPB times ]REAL angles;
            FOR i FROM LWB times TO UPB times DO angles[ i ] := TOANGLE times[ i ] OD;
            TOTIME mean angle( angles )
         END # mean time # ;

    OP   SHOW = ( TIME t )VOID:
         BEGIN
            PROC d2 = ( INT n )STRING: IF n < 10 THEN "0" ELSE "" FI + whole( n, 0 );
            print( ( d2( hh OF t ), ":", d2( mm OF t ), ":", d2( ss OF t ) ) )
         END # show time # ;

    SHOW mean time( ( ( 23,00,17 ), ( 23,40,20 ), ( 00,12,45 ), ( 00,17,19 ) ) )
END
Output:
23:47:43

AutoHotkey

Works with: AutoHotkey 1.1
MsgBox, % "The mean time is: " MeanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])

MeanTime(t, x=0, y=0) {
	static c := ATan(1) / 45
	for k, v in t {
		n := StrSplit(v, ":")
		r := c * (n[1] * 3600 + n[2] * 60 + n[3]) / 240
		x += Cos(r)
		y += Sin(r)
	}
	r := atan2(x, y) / c
	r := (r < 0 ? r + 360 : r) / 15
	h := SubStr("00" Round(r // 1, 0), -1)
	s := SubStr("00" Round(Mod(m := Mod(r, 1) * 60, 1) * 60, 0), -1)
	m := SubStr("00" Round(m // 1, 0), -1)
	return, h ":" m ":" s
}

atan2(x, y) {
   return dllcall("msvcrt\atan2", "Double",y, "Double",x, "CDECL Double")
}
Output:
The mean time is: 23:47:43

AWK

#!/usr/bin/awk -f
{
    c = atan2(0,-1)/(12*60*60);
    x=0.0; y=0.0;
    for (i=1; i<=NF; i++) {	
        split($i,a,":");
	p = (a[1]*3600+a[2]*60+a[3])*c;
	x += sin(p);
	y += cos(p);
    }
    p = atan2(x,y)/c;	
    if (p<0) p += 24*60*60;
    print strftime("%T",p,1);
}
$ echo 23:00:17, 23:40:20, 00:12:45, 00:17:19 | awk -f mean_time_of_day.awk
23:47:43

BBC BASIC

      nTimes% = 4
      DATA 23:00:17, 23:40:20, 00:12:45, 00:17:19
      
      DIM angles(nTimes%-1)
      FOR N% = 0 TO nTimes%-1
        READ tim$
        angles(N%) = FNtimetoangle(tim$)
      NEXT
      PRINT "Mean time is " FNangletotime(FNmeanangle(angles(), nTimes%))
      END
      
      DEF FNtimetoangle(t$)
      LOCAL A%, I%
      REPEAT
        A% = A% * 60 + VAL(t$)
        I% = INSTR(t$, ":")
        t$ = MID$(t$, I%+1)
      UNTIL I% = 0
      = A% / 240 - 180
      
      DEF FNangletotime(a)
      LOCAL A%, I%, t$
      A% = INT((a + 180) * 240 + 0.5)
      FOR I% = 1 TO 3
        t$ = RIGHT$("0" + STR$(A% MOD 60), 2) + ":" + t$
        A% DIV= 60
      NEXT
      = LEFT$(t$)
      
      DEF FNmeanangle(angles(), N%)
      LOCAL I%, addsin, addcos
      FOR I% = 0 TO N%-1
        addsin += SINRADangles(I%)
        addcos += COSRADangles(I%)
      NEXT
      = DEGFNatan2(addsin, addcos)
      
      DEF FNatan2(y,x) : ON ERROR LOCAL = SGN(y)*PI/2
      IF x>0 THEN = ATN(y/x) ELSE IF y>0 THEN = ATN(y/x)+PI ELSE = ATN(y/x)-PI
Output:
Mean time is 23:47:43

C

#include<stdlib.h>
#include<math.h>
#include<stdio.h>

typedef struct
{
  int hour, minute, second;
} digitime;

double
timeToDegrees (digitime time)
{
  return (360 * time.hour / 24.0 + 360 * time.minute / (24 * 60.0) +
          360 * time.second / (24 * 3600.0));
}

digitime
timeFromDegrees (double angle)
{
  digitime d;
  double totalSeconds = 24 * 60 * 60 * angle / 360;

  d.second = (int) totalSeconds % 60;
  d.minute = ((int) totalSeconds % 3600 - d.second) / 60;
  d.hour = (int) totalSeconds / 3600;

  return d;
}

double
meanAngle (double *angles, int size)
{
  double y_part = 0, x_part = 0;
  int i;

  for (i = 0; i < size; i++)
    {
      x_part += cos (angles[i] * M_PI / 180);
      y_part += sin (angles[i] * M_PI / 180);
    }

  return atan2 (y_part / size, x_part / size) * 180 / M_PI;
}

int
main ()
{
  digitime *set, meanTime;
  int inputs, i;
  double *angleSet, angleMean;

  printf ("Enter number of inputs : ");
  scanf ("%d", &inputs);
  set = malloc (inputs * sizeof (digitime));
  angleSet = malloc (inputs * sizeof (double));
  printf ("\n\nEnter the data separated by a space between each unit : ");

  for (i = 0; i < inputs; i++)
    {
      scanf ("%d:%d:%d", &set[i].hour, &set[i].minute, &set[i].second);
      angleSet[i] = timeToDegrees (set[i]);
    }

  meanTime = timeFromDegrees (360 + meanAngle (angleSet, inputs));

  printf ("\n\nThe mean time is : %d:%d:%d", meanTime.hour, meanTime.minute,
          meanTime.second);
  return 0;
}
Output:
Enter number of inputs : 4


Enter the data separated by a space between each unit : 23:00:17 23:40:20 00:12:45 00:17:19


The mean time is : 23:47:43

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static System.Math;

namespace RosettaCode;

class Program
{
    private const int SecondsPerDay = 60 * 60 * 24;

    static void Main()
    {
        var digitimes = new List<TimeSpan>();

        Console.WriteLine("Enter times, end with no input: ");
        while (true) {
            string input = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(input)) break;
            if (TimeSpan.TryParse(input, out var digitime)) {
                digitimes.Add(digitime);
            } else {
                Console.WriteLine("Seems this is wrong input: ignoring time");
            }
        }
        if(digitimes.Count() > 0)
            Console.WriteLine($"The mean time is : {MeanTime(digitimes)}");
    }

    public static TimeSpan MeanTime(IEnumerable<TimeSpan> ts) => FromDegrees(MeanAngle(ts.Select(ToDegrees)));
    public static double ToDegrees(TimeSpan ts) => ts.TotalSeconds * 360d / SecondsPerDay;
    public static TimeSpan FromDegrees(double degrees) => TimeSpan.FromSeconds((int)(degrees * SecondsPerDay / 360));

    public static double MeanAngle(IEnumerable<double> angles)
    {
        var x = angles.Average(a => Cos(a * PI / 180));
        var y = angles.Average(a => Sin(a * PI / 180));
        return (Atan2(y, x) * 180 / PI + 360) % 360;
    }
}
Output:
Enter times, end with no input:
23:00:17
23:40:20
00:12:45
00:17:19

The mean time is : 23:47:43

C++

#include <iomanip>
#include <iostream>
#include <vector>

#define _USE_MATH_DEFINES
#include <math.h>

struct Time {
    int hour, minute, second;

    friend std::ostream &operator<<(std::ostream &, const Time &);
};

std::ostream &operator<<(std::ostream &os, const Time &t) {
    return os << std::setfill('0')
        << std::setw(2) << t.hour << ':'
        << std::setw(2) << t.minute << ':'
        << std::setw(2) << t.second;
}

double timeToDegrees(Time &&t) {
    return 360.0 * t.hour / 24.0
        + 360.0 * t.minute / (24 * 60.0)
        + 360.0 * t.second / (24 * 3600.0);
}

Time degreesToTime(double angle) {
    while (angle < 0.0) {
        angle += 360.0;
    }
    while (angle > 360.0) {
        angle -= 360.0;
    }

    double totalSeconds = 24.0 * 60 * 60 * angle / 360;
    Time t;

    t.second = (int)totalSeconds % 60;
    t.minute = ((int)totalSeconds % 3600 - t.second) / 60;
    t.hour = (int)totalSeconds / 3600;

    return t;
}

double meanAngle(const std::vector<double> &angles) {
    double yPart = 0.0, xPart = 0.0;
    for (auto a : angles) {
        xPart += cos(a * M_PI / 180);
        yPart += sin(a * M_PI / 180);
    }
    return atan2(yPart / angles.size(), xPart / angles.size()) * 180 / M_PI;
}

int main() {
    std::vector<double> tv;
    tv.push_back(timeToDegrees({ 23, 0, 17 }));
    tv.push_back(timeToDegrees({ 23, 40, 20 }));
    tv.push_back(timeToDegrees({ 0, 12, 45 }));
    tv.push_back(timeToDegrees({ 0, 17, 19 }));

    double ma = meanAngle(tv);
    auto mt = degreesToTime(ma);
    std::cout << mt << '\n';

    return 0;
}
Output:
23:47:43

Common Lisp

Translation of: Echo Lisp
;; * Loading the split-sequence library
(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload '("split-sequence")))

;; * The package definition
(defpackage :mean-time-of-day
  (:use :common-lisp :iterate :split-sequence))
(in-package :mean-time-of-day)

;; * The data
(defparameter *time-values*
  '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))

(defun time->radian (time)
  "Returns the radian value for TIME given as a STRING like HH:MM:SS. Assuming a
valid input value."
  (destructuring-bind (h m s)
      (mapcar #'parse-integer (split-sequence #\: time))
    (+  (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600)))))

(defun radian->time (radian)
  "Returns the corresponding time as a string like HH:MM:SS for RADIAN."
  (let* ((time (if (plusp radian)
                   (round (/ (* 12 3600 radian) PI))
                   (round (/ (* 12 3600 (+ radian (* 2 PI))) PI))))
         (h (floor time 3600))
         (m (floor (- time (* h 3600)) 60))
         (s (- time (* h 3600) (* m 60))))
    (format nil "~2,'0D:~2,'0D:~2,'0D" h m s)))

(defun make-polar (rho theta)
  "Returns a complex representing the polar coordinates."
  (complex (* rho (cos theta)) (* rho (sin theta))))

(defun mean-time (times)
  "Returns the mean time value within 24h of the list of TIMES given as strings
  HH:MM:SS."
  (radian->time (phase
                 (reduce #'+ (mapcar (lambda (time)
                                       (make-polar 1 (time->radian time))) times)))))
Output:
MEAN-TIME-OF-DAY> (mean-time *time-values*)
"23:47:43"

D

Translation of: Python
import std.stdio, std.range, std.algorithm, std.complex, std.math,
       std.format, std.conv;

double radians(in double d) pure nothrow @safe @nogc {
    return d * PI / 180;
}

double degrees(in double r) pure nothrow @safe @nogc {
    return r * 180 / PI;
}

double meanAngle(in double[] deg) pure nothrow @safe @nogc {
    return (deg.map!(d => fromPolar(1, d.radians)).sum / deg.length).arg.degrees;
}

string meanTime(in string[] times) pure @safe {
    auto t = times.map!(times => times.split(':').to!(int[3]));
    assert(t.all!(hms => 24.iota.canFind(hms[0]) &&
                         60.iota.canFind(hms[1]) &&
                         60.iota.canFind(hms[2])),
           "Invalid time");

    auto seconds = t.map!(hms => hms[2] + hms[1] * 60 + hms[0] * 3600);
    enum day = 24 * 60 * 60;
    const to_angles = seconds.map!(s => s * 360.0 / day).array;

    immutable mean_as_angle = to_angles.meanAngle;
    auto mean_seconds_fp = mean_as_angle * day / 360.0;
    if (mean_seconds_fp < 0)
        mean_seconds_fp += day;
    immutable mean_seconds = mean_seconds_fp.to!uint;
    immutable h = mean_seconds / 3600;
    immutable m = mean_seconds % 3600;
    return "%02d:%02d:%02d".format(h, m / 60, m % 60);
}

void main() @safe {
    ["23:00:17", "23:40:20", "00:12:45", "00:17:19"].meanTime.writeln;
}
Output:
23:47:43

Delphi

Library: System.Math
Translation of: Go
program Averages_Mean_time_of_day;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math;

const
  Inputs: TArray<string> = ['23:00:17', '23:40:20', '00:12:45', '00:17:19'];

function ToTimes(ts: TArray<string>): TArray<TTime>;
begin
  SetLength(result, length(ts));
  for var i := 0 to High(ts) do
    Result[i] := StrToTime(ts[i]);
end;

function MeanTime(times: TArray<TTime>): TTime;
var
  ssum, csum: TTime;
  h, m, s, ms: word;
  dayFrac, fsec, ssin, ccos: double;
begin
  if Length(times) = 0 then
    exit(0);

  ssum := 0;
  csum := 0;
  for var t in times do
  begin
    DecodeTime(t, h, m, s, ms);
    fsec := (h * 60 + m) * 60 + s + ms / 1000;
    ssin := sin(fsec * Pi / (12 * 60 * 60));
    ccos := cos(fsec * Pi / (12 * 60 * 60));
    ssum := ssum + ssin;
    csum := csum + ccos;
  end;
  if (ssum = 0) and (csum = 0) then
    raise Exception.Create('Error MeanTime: Mean undefined');

  dayFrac := frac(1 + ArcTan2(ssum, csum) / (2 * Pi));
  fsec := dayFrac * 24 * 3600;

  ms := Trunc(frac(fsec) * 1000);
  s := trunc(fsec) mod 60;
  m := trunc(fsec) div 60 mod 60;
  h := trunc(fsec) div 3600;

  Result := EncodeTime(h, m, s, ms);
end;

begin
  writeln(TimeToStr(MeanTime(ToTimes(Inputs))));
  readln;
end.

EasyLang

Translation of: C
func tm2deg t$ .
   t[] = number strsplit t$ ":"
   return 360 * t[1] / 24.0 + 360 * t[2] / (24 * 60.0) + 360 * t[3] / (24 * 3600.0)
.
func$ deg2tm deg .
   len t[] 3
   h = floor (24 * 60 * 60 * deg / 360)
   t[3] = h mod 60
   h = h div 60
   t[2] = h mod 60
   t[1] = h div 60
   for h in t[]
      if h < 10
         s$ &= 0
      .
      s$ &= h
      s$ &= ":"
   .
   return substr s$ 1 8
.
func mean ang[] .
   for ang in ang[]
      x += cos ang
      y += sin ang
   .
   return atan2 (y / len ang[]) (x / len ang[])
.
in$ = "23:00:17 23:40:20 00:12:45 00:17:19"
for s$ in strsplit in$ " "
   ar[] &= tm2deg s$
.
print deg2tm (360 + mean ar[])

EchoLisp

;; string hh:mm:ss to radians
(define (time->radian time) 
    (define-values (h m s) (map string->number (string-split time ":")))
    (+  (* h (/ PI 12)) (* m (/ PI 12 60)) (* s (/ PI 12 3600))))
			
;; radians to string hh:mm;ss
(define (radian->time rad)
	(when (< rad 0) (+= rad (* 2 PI)))
	(define t (round (/ (* 12 3600 rad) PI)))
	(define h (quotient t 3600))
	(define m (quotient (- t (* h 3600)) 60))
	(define s (- t (* 3600 h) (* 60 m)))
	(string-join (map number->string (list h m s)) ":"))
	
(define (mean-time times)
	(radian->time 
	 (angle 
	  (for/sum ((t times)) (make-polar 1 (time->radian t))))))
	
(mean-time '{"23:00:17" "23:40:20" "00:12:45" "00:17:19"})
      "23:47:43"

Erlang

-module( mean_time_of_day ).
-export( [from_times/1, task/0] ).

from_times( Times ) ->
	Seconds = [seconds_from_time(X) || X <- Times],
	Degrees = [degrees_from_seconds(X) || X <- Seconds],
	Average = mean_angle:from_degrees( Degrees ),
	time_from_seconds( seconds_from_degrees(Average) ).

task() ->
	Times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"],
	io:fwrite( "The mean time of  ~p is: ~p~n", [Times, from_times(Times)] ).



degrees_from_seconds( Seconds ) when Seconds < (24 * 3600) -> (Seconds * 360) / (24 * 3600).

seconds_from_degrees( Degrees ) when Degrees < 0 -> seconds_from_degrees( Degrees + 360 );
seconds_from_degrees( Degrees ) when Degrees < 360 -> (Degrees * 24 * 3600) / 360.

seconds_from_time( Time ) ->
	{ok, [Hours, Minutes, Seconds], _Rest} = io_lib:fread( "~d:~d:~d", Time ),
	Hours * 3600 + Minutes * 60 + Seconds.

time_from_seconds( Seconds_float ) ->
	Seconds = erlang:round( Seconds_float ),
	Hours = Seconds div 3600,
	Minutes = (Seconds - (Hours * 3600)) div 60,
	Secs = Seconds - (Hours * 3600) - (Minutes * 60),
	lists:flatten( io_lib:format("~2.10.0B:~2.10.0B:~2.10.0B", [Hours, Minutes, Secs]) ).
Output:
17> mean_time_of_day:task().
The mean time of  ["23:00:17","23:40:20","00:12:45","00:17:19"] is: "23:47:43"

Euphoria

Works with: OpenEuphoria
include std/console.e
include std/math.e
include std/mathcons.e
include std/sequence.e
include std/get.e

function T2D(sequence TimeSeq)
	return (360 * TimeSeq[1] / 24 + 360 * TimeSeq[2] / (24 * 60) +
			360 * TimeSeq[3] / (24 * 3600))
end function

function D2T(atom angle)
	sequence TimeSeq = {0,0,0}
	atom seconds = 24 * 60 * 60 * angle / 360
	
	TimeSeq[3] = mod(seconds,60)
	TimeSeq[2] = (mod(seconds,3600) - TimeSeq[3]) / 60
	TimeSeq[1] = seconds / 3600
	
	return TimeSeq
end function

function MeanAngle(sequence angles)
	atom x = 0, y = 0
	integer l = length(angles)
	
	for i = 1 to length(angles) do
		x += cos(angles[i] * PI / 180)
		y += sin(angles[i] * PI / 180)
	end for
	
	return atan2(y / l, x / l) * 180 / PI
end function

sequence TimeEntry, TimeList = {}, TimeSeq

puts(1,"Enter times.  Enter with no input to end\n")
while 1 do
 TimeEntry = prompt_string("")
 if equal(TimeEntry,"") then  -- no more entries
 	for i = 1 to length(TimeList) do
 		TimeList[i] = split(TimeList[i],":") -- split the times into sequences 
 		for j = 1 to 3 do
 			TimeList[i][j] = defaulted_value(TimeList[i][j],0) -- convert to numerical values
 		end for
 	end for
 	exit
 end if
 TimeList = append(TimeList,TimeEntry)
end while

sequence AngleList = repeat({},length(TimeList))

for i = 1 to length(AngleList) do
	AngleList[i] = T2D(TimeList[i])
end for

sequence MeanTime = D2T(360+MeanAngle(AngleList))

printf(1,"\nMean Time: %d:%d:%d\n",MeanTime)

	
if getc(0) then end if
Output:
Enter Times.  Enter with no input to end.
23:00:17
23:40:20
00:12:45
00:17:19

Mean Time: 23:47:43

F#

open System
open System.Numerics

let deg2rad d = d * Math.PI / 180.
let rad2deg r = r * 180. / Math.PI
let makeComplex = fun r ->  Complex.FromPolarCoordinates(1., r)
// 1 msec = 10000 ticks
let time2deg = TimeSpan.Parse >> (fun ts -> ts.Ticks) >> (float) >> (*) (10e-9/24.)
let deg2time = (*) (24. * 10e7) >> (int64) >> TimeSpan

[<EntryPoint>]
let main argv =
    let msg = "Average time for [" + (String.Join("; ",argv)) + "] is"
    argv
    |> Seq.map (time2deg >> deg2rad >> makeComplex)
    |> Seq.fold (fun x y -> Complex.Add(x,y)) Complex.Zero
    |> fun c -> c.Phase |> rad2deg
    |> fun d -> if d < 0. then d + 360. else d
    |> deg2time |> fun t -> t.ToString(@"hh\:mm\:ss")
    |> printfn "%s: %s" msg 
    0
Output:
>RosettaCode 23:00:17 23:40:20 00:12:45 00:17:19
Average time for [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43

Factor

USING: arrays formatting kernel math math.combinators
math.functions math.libm math.parser math.trig qw sequences
splitting ;
IN: rosetta-code.mean-time

CONSTANT: input qw{ 23:00:17 23:40:20 00:12:45 00:17:19 }

: time>deg ( hh:mm:ss -- x )
    ":" split [ string>number ] map first3
    [ 15 * ] [ 1/4 * ] [ 1/240 * ] tri* + + ;

: mean-angle ( seq -- x )
    [ deg>rad ] map [ [ sin ] map-sum ] [ [ cos ] map-sum ]
    [ length ] tri recip [ * ] curry bi@ fatan2 rad>deg ;

: cutf ( x -- str y )
    [ >integer number>string ] [ dup floor - ] bi ;

: mean-time ( seq -- str )
    [ time>deg ] map mean-angle [ 360 + ] when-negative 24 *
    360 / cutf 60 * cutf 60 * round cutf drop 3array ":" join ; 

: mean-time-demo ( -- )
    input dup mean-time "Mean time for %u is %s.\n" printf ;

MAIN: mean-time-demo
Output:
Mean time for { "23:00:17" "23:40:20" "00:12:45" "00:17:19" } is 23:47:43.

Fortran

Works with: gfortran 5.1.0
program mean_time_of_day
  implicit none
  integer(kind=4), parameter :: dp = kind(0.0d0)

  type time_t
    integer(kind=4) :: hours, minutes, seconds
  end type

  character(len=8), dimension(4), parameter :: times = &
    (/ '23:00:17', '23:40:20', '00:12:45', '00:17:19' /)
  real(kind=dp), dimension(size(times)) :: angles
  real(kind=dp) :: mean

  angles = time_to_angle(str_to_time(times))
  mean = mean_angle(angles)
  if (mean < 0) mean = 360 + mean

  write(*, fmt='(I2.2, '':'', I2.2, '':'', I2.2)') angle_to_time(mean)
contains
  real(kind=dp) function mean_angle(angles)
    real(kind=dp), dimension(:), intent (in) :: angles
    real(kind=dp) :: x, y

    x = sum(sin(radians(angles)))/size(angles)
    y = sum(cos(radians(angles)))/size(angles)

    mean_angle = degrees(atan2(x, y))
  end function

  elemental real(kind=dp) function radians(angle)
    real(kind=dp), intent (in) :: angle
    real(kind=dp), parameter :: pi = 4d0*atan(1d0)
    radians = angle/180*pi
  end function

  elemental real(kind=dp) function degrees(angle)
    real(kind=dp), intent (in) :: angle
    real(kind=dp), parameter :: pi = 4d0*atan(1d0)
    degrees = 180*angle/pi
  end function

  elemental type(time_t) function str_to_time(str)
    character(len=*), intent (in) :: str
    ! Assuming time in format hh:mm:ss
    read(str, fmt='(I2, 1X, I2, 1X, I2)') str_to_time
  end function

  elemental real(kind=dp) function time_to_angle(time) result (res)
    type(time_t), intent (in) :: time

    real(kind=dp) :: seconds
    real(kind=dp), parameter :: seconds_in_day = 24*60*60

    seconds = time%seconds + 60*time%minutes + 60*60*time%hours
    res = 360*seconds/seconds_in_day
  end function

  elemental type(time_t) function angle_to_time(angle)
    real(kind=dp), intent (in) :: angle

    real(kind=dp) :: seconds
    real(kind=dp), parameter :: seconds_in_day = 24*60*60

    seconds = seconds_in_day*angle/360d0
    angle_to_time%hours = int(seconds/60d0/60d0)
    seconds = mod(seconds, 60d0*60d0)
    angle_to_time%minutes = int(seconds/60d0)
    angle_to_time%seconds = mod(seconds, 60d0)
  end function
end program
Output:
23:47:43

FreeBASIC

' FB 1.05.0 Win64

Const pi As Double = 3.1415926535897932
 
Function meanAngle(angles() As Double) As Double
  Dim As Integer length = Ubound(angles) - Lbound(angles) + 1
  Dim As Double sinSum = 0.0
  Dim As Double cosSum = 0.0
  For i As Integer = LBound(angles) To UBound(angles)
    sinSum += Sin(angles(i) * pi / 180.0)
    cosSum += Cos(angles(i) * pi / 180.0)    
  Next
  Return Atan2(sinSum / length, cosSum / length) * 180.0 / pi
End Function

' time string assumed to be in format "hh:mm:ss"
Function timeToSecs(t As String) As Integer
  Dim As Integer hours = Val(Left(t, 2))
  Dim As Integer mins =  Val(Mid(t, 4, 2))
  Dim As Integer secs =  Val(Right(t, 2))
  Return 3600 * hours + 60 * mins + secs  
End Function

' 1 second of time = 360/(24 * 3600) = 1/240th degree
Function timeToDegrees(t As String) As Double
  Dim secs As Integer = timeToSecs(t)
  Return secs/240.0
End Function

Function degreesToTime(d As Double) As String
  If d < 0 Then d += 360.0 
  Dim secs As Integer  = d * 240.0
  Dim hours As Integer = secs \ 3600
  Dim mins As Integer  = secs Mod 3600
  secs = mins Mod 60
  mins = mins \ 60
  Dim hBuffer As String = Right("0" + Str(hours), 2)
  Dim mBuffer As String = Right("0" + Str(mins), 2)
  Dim sBuffer As String = Right("0" + Str(secs), 2)
  Return hBuffer + ":" + mBuffer + ":" + sBuffer
End Function

Dim tm(1 To 4) As String = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"}
Dim angles(1 To 4) As Double

For i As Integer = 1 To 4
  angles(i) = timeToDegrees(tm(i))
Next

Dim mean As Double = meanAngle(angles())
Print "Average time is : "; degreesToTime(mean)
Print
Print "Press any key to quit"
Sleep
Output:
Average time is : 23:47:43

Go

package main

import (
    "errors"
    "fmt"
    "log"
    "math"
    "time"
)

var inputs = []string{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}

func main() {
    tList := make([]time.Time, len(inputs))
    const clockFmt = "15:04:05"
    var err error
    for i, s := range inputs {
        tList[i], err = time.Parse(clockFmt, s)
        if err != nil {
            log.Fatal(err)
        }
    }
    mean, err := meanTime(tList)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(mean.Format(clockFmt))
}

func meanTime(times []time.Time) (mean time.Time, err error) {
    if len(times) == 0 {
        err = errors.New("meanTime: no times specified")
        return
    }
    var ssum, csum float64
    for _, t := range times {
        h, m, s := t.Clock()
        n := t.Nanosecond()
        fSec := (float64((h*60+m)*60+s) + float64(n)*1e-9)
        sin, cos := math.Sincos(fSec * math.Pi / (12 * 60 * 60))
        ssum += sin
        csum += cos
    }
    if ssum == 0 && csum == 0 {
        err = errors.New("meanTime: mean undefined")
        return
    }
    _, dayFrac := math.Modf(1 + math.Atan2(ssum, csum)/(2*math.Pi))
    return mean.Add(time.Duration(dayFrac * 24 * float64(time.Hour))), nil
}
Output:
23:47:43

Groovy

Solution:

import static java.lang.Math.*

final format = 'HH:mm:ss',  clock = PI / 12,  millisPerHr = 3600*1000
final tzOffset = new Date(0).timezoneOffset / 60
def parseTime = { time -> (Date.parse(format, time).time / millisPerHr) - tzOffset }
def formatTime = { time -> new Date((time + tzOffset) * millisPerHr as int).format(format) }
def mean = { list, closure -> list.sum(closure)/list.size() }
def meanTime = { ... timeStrings ->
    def times = timeStrings.collect(parseTime)
    formatTime(atan2( mean(times) { sin(it * clock) }, mean(times) { cos(it * clock) }) / clock)
}

Test:

println (meanTime("23:00:17", "23:40:20", "00:12:45", "00:17:19"))
Output:
23:47:43

Haskell

import Data.Complex (cis, phase)
import Data.List.Split (splitOn)
import Text.Printf (printf)

timeToRadians :: String -> Float 
timeToRadians time = 
        let hours:minutes:seconds:_ = splitOn ":" time
            s = fromIntegral (read seconds :: Int)
            m = fromIntegral (read minutes :: Int)
            h = fromIntegral (read hours :: Int)
        in  (2*pi)*(h+ (m + s/60.0 )/60.0 )/24.0
   
radiansToTime :: Float -> String
radiansToTime  r =
        let tau = pi*2
            (_,fDay) = properFraction (r / tau) :: (Int, Float)
            fDayPositive = if fDay < 0 then 1.0+fDay else fDay 
            (hours, fHours) = properFraction $ 24.0 * fDayPositive
            (minutes, fMinutes) = properFraction $ 60.0 * fHours
            seconds = 60.0 * fMinutes
        in printf "%0d" (hours::Int) ++ ":" ++ printf "%0d" (minutes::Int) ++ ":" ++ printf "%0.0f" (seconds::Float)
 
meanAngle :: [Float] -> Float
meanAngle = phase . sum . map cis
 
main :: IO ()        
main = putStrLn $ radiansToTime $ meanAngle $ map timeToRadians ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
Output:
23:47:43

Icon and Unicon

procedure main(A)
    every put(B := [], ct2a(!A))
    write(ca2t(meanAngle(B)))
end

procedure ct2a(t)
    t ? {s := ((1(move(2),move(1))*60 + 1(move(2),move(1)))*60 + move(2))}
    return (360.0/86400.0) * s
end

procedure ca2t(a)
    while a < 0 do a +:= 360.0
    t := integer((86400.0/360.0)*a + 0.5)
    s := left(1(.t % 60, t /:= 60),2,"0")
    s := left(1(.t % 60, t /:= 60),2,"0")||":"||s
    s := left(t,2,"0")||":"||s
    return s
end

procedure meanAngle(A)
    every (sumSines := 0.0) +:= sin(dtor(!A))
    every (sumCosines := 0.0) +:= cos(dtor(!A))
    return rtod(atan(sumSines/*A,sumCosines/*A))
end

Sample run:

->amtod 23:00:17 23:40:20 00:12:45 00:17:19
23:47:43
->

J

use avgAngleR from Averages/Mean angle#J

require 'types/datetime'
parseTimes=: ([: _&".;._2 ,&':');._2
secsFromTime=:  24 60 60 #. ]     NB. convert from time to seconds
rft=: 2r86400p1 * secsFromTime    NB. convert from time to radians
meanTime=: 'hh:mm:ss' fmtTime [: secsFromTime [: avgAngleR&.rft parseTimes
Example Use:
   meanTime '23:00:17 23:40:20 00:12:45 00:17:19 '
23:47:43

Java

Translation of: Kotlin
public class MeanTimeOfDay {
    
    static double meanAngle(double[] angles) {
        int len = angles.length;
        double sinSum = 0.0;
        for (int i = 0; i < len; i++) {
            sinSum += Math.sin(angles[i] * Math.PI / 180.0);
        }
 
        double cosSum = 0.0;
        for (int i = 0; i < len; i++) {
            cosSum += Math.cos(angles[i] * Math.PI / 180.0);
        }

        return Math.atan2(sinSum / len, cosSum / len) * 180.0 / Math.PI;
    }

    /* time string assumed to be in format "hh:mm:ss" */
    static int timeToSecs(String t) {
        int hours = Integer.parseInt(t.substring(0, 2));
        int mins  = Integer.parseInt(t.substring(3, 5));
        int secs  = Integer.parseInt(t.substring(6, 8));
        return 3600 * hours + 60 * mins + secs;
    }

    /* 1 second of time = 360/(24 * 3600) = 1/240th degree */
    static double timeToDegrees(String t) {
        return timeToSecs(t) / 240.0;
    }

    static String degreesToTime(double d) {
        if (d < 0.0) d += 360.0;
        int secs  = (int)(d * 240.0);
        int hours = secs / 3600;
        int mins  = secs % 3600;
        secs = mins % 60;
        mins /= 60;
        return String.format("%2d:%2d:%2d", hours, mins, secs);
    }

    public static void main(String[] args) {
        String[] tm = {"23:00:17", "23:40:20", "00:12:45", "00:17:19"};
        double[] angles = new double[4];
        for (int i = 0; i < 4; i++) angles[i] = timeToDegrees(tm[i]);        
        double mean = meanAngle(angles);
        System.out.println("Average time is : " + degreesToTime(mean));
    }
}
Output:
Average time is : 23:47:43

JavaScript

Works with: Node.js
var args  = process.argv.slice(2);

function time_to_seconds( hms ) {
    var parts = hms.split(':');
    var h = parseInt(parts[0]);
    var m = parseInt(parts[1]);
    var s = parseInt(parts[2]);
    if ( h < 12 ) {
        h += 24;
    }
    var seconds = parseInt(parts[0]) * 60 * 60 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
    return seconds;
}
function seconds_to_time( s ) {
    var h = Math.floor( s/(60 * 60) );
    if ( h < 10 ) {
        h = '0' + h;
    }
    s = s % (60 * 60);

    var m = Math.floor( s/60 );
    if ( m < 10 ) {
        m = '0' + m;
    }
    s = s % 60
    if ( s < 10 ) {
        s = '0' + s;
    }
    return h + ':' + m + ':' + s;
}

var sum = 0, count = 0, idx;
for (idx in args) {
    var seconds = time_to_seconds( args[idx] );
    sum += seconds;
    count++;
}

var seconds = Math.floor( sum / count )
console.log( 'Mean time is ', seconds_to_time(seconds));
Output:
$ node mean_time.js 23:00:17 23:40:20 00:12:45 00:17:19
Mean time is  23:47:40

jq

Works with: jq version 1.4

The "mean time" of two times that differ by 12 hours (e.g. ["00:00:00", "12:00:00"]) is not very well-defined, and is accordingly computed as null here.

# input: array of "h:m:s"
def mean_time_of_day:
  def pi: 4 * (1|atan);
  def to_radians:   pi * . /(12*60*60);
  def from_radians: (. * 12*60*60) / pi;

  def secs2time:  # produce "hh:mm:ss" string
    def pad: tostring | (2 - length) * "0" + .;
    "\(./60/60 % 24 | pad):\(./60 % 60 | pad):\(. % 60 | pad)";

  def round:
    if . < 0 then -1 * ((- .) | round) | if . == -0 then 0 else . end
    else floor as $x
    | if (. - $x) < 0.5 then $x else $x+1 end
    end;

  map( split(":")
       | map(tonumber)
       | (.[0]*3600 + .[1]*60 + .[2])
       | to_radians )
   | (map(sin) | add) as $y
   | (map(cos) | add) as $x
   | if $x == 0 then (if $y > 3e-14 then pi/2 elif $y < -3e-14 then -(pi/2) else null end)
     else ($y / $x) | atan
     end
   | if . == null then null
     else from_radians
     | if (.<0) then . + (24*60*60) else . end
     | round
     | secs2time
     end ;

Examples

["0:0:0", "12:0:0" ],
["0:0:0", "24:0:0" ],
["1:0:0",  "1:0:0" ],
["20:0:0", "4:0:0" ],
["20:0:0", "4:0:2" ],
["23:0:0", "23:0:0" ],
["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
| mean_time_of_day
Output:
$ jq -r -n -f Mean_time_of_day.jq
null
00:00:00
01:00:00
00:00:00
00:00:01
23:00:00
23:47:43

Julia

Works with: Julia version 0.6
Translation of: MATLAB
using Statistics

function meantime(times::Array, dlm::String=":")
    c = π / (12 * 60 * 60)
    a = map(x -> parse.(Int, x), split.(times, dlm))
    ϕ = collect(3600t[1] + 60t[2] + t[3] for t in a)
    d = angle(mean(exp.(c * im * ϕ))) / 2π # days
    if d < 0 d += 1 end
    # Convert to h:m:s
    h = trunc(Int, d * 24)
    m = trunc(Int, d * 24 * 60) - h * 60
    s = trunc(Int, d * 24 * 60 * 60) - h * 60 * 60 - m * 60
    return "$h:$m:$s"
end

times = String["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
mtime = meantime(times)
println("Times:")
println.(times)
println("Mean: $mtime")
Output:
Times:
23:00:17
23:40:20
00:12:45
00:17:19
Mean: 23:47:43

Kotlin

Translation of: FreeBASIC
// version 1.0.6

fun meanAngle(angles: DoubleArray): Double {
    val sinSum = angles.sumByDouble {  Math.sin(it * Math.PI / 180.0) }
    val cosSum = angles.sumByDouble {  Math.cos(it * Math.PI / 180.0) }
    return Math.atan2(sinSum / angles.size, cosSum / angles.size) * 180.0 / Math.PI
}

/* time string assumed to be in format "hh:mm:ss" */
fun timeToSecs(t: String): Int {
    val hours = t.slice(0..1).toInt()
    val mins  = t.slice(3..4).toInt()
    val secs  = t.slice(6..7).toInt()
    return 3600 * hours + 60 * mins + secs
}

/* 1 second of time = 360/(24 * 3600) = 1/240th degree */
fun timeToDegrees(t: String): Double = timeToSecs(t) / 240.0

fun degreesToTime(d: Double): String {
    var dd = d
    if (dd < 0.0) dd += 360.0
    var secs  = (dd * 240.0).toInt()
    val hours = secs / 3600
    var mins  = secs % 3600
    secs  = mins % 60
    mins /= 60
    return String.format("%2d:%2d:%2d", hours, mins, secs)
}

fun main(args: Array<String>) {
    val tm = arrayOf("23:00:17", "23:40:20", "00:12:45", "00:17:19")
    val angles = DoubleArray(4) { timeToDegrees(tm[it]) }
    val mean = meanAngle(angles)
    println("Average time is : ${degreesToTime(mean)}")
}
Output:
Average time is : 23:47:43

Liberty BASIC

global pi
pi = acs(-1)

Print "Average of:"
for i = 1 to 4
    read t$ 
    print t$
    a=time2angle(t$)
    ss=ss+sin(a)
    sc=sc+cos(a)
next
a=atan2(ss,sc)
if a<0 then a=a+2*pi
print "is ";angle2time$(a)

end
data "23:00:17", "23:40:20", "00:12:45", "00:17:19"

function nn$(n)
    nn$=right$("0";n, 2)
end function

function angle2time$(a)
    a=int(a/2/pi*24*60*60)
    ss=a mod 60
    a=int(a/60)
    mm=a mod 60
    hh=int(a/60)
    angle2time$=nn$(hh);":";nn$(mm);":";nn$(ss)
end function

function time2angle(time$)
    hh=val(word$(time$,1,":"))
    mm=val(word$(time$,2,":"))
    ss=val(word$(time$,3,":"))
    time2angle=2*pi*(60*(60*hh+mm)+ss)/24/60/60
end function

function atan2(y, x)
    On Error GoTo [DivZero]      'If y is 0 catch division by zero error
        atan2 = (2 * (atn((sqr((x * x) + (y * y)) - x)/ y)))
        exit function
    [DivZero]
        atan2 = (y=0)*(x<0)*pi
End Function
Output:
Average of:
23:00:17
23:40:20
00:12:45
00:17:19
is 23:47:43 

Lua

local times = {"23:00:17","23:40:20","00:12:45","00:17:19"}

-- returns time converted to a radian format
local function timeToAngle(str)
	local h,m,s = str:match("(..):(..):(..)")
	return (h + m / 60 + s / 3600)/12 * math.pi
end

-- computes the mean of the angles inside a list
local function meanAngle(angles)
	local sumSin,sumCos = 0,0
	for k,v in pairs(angles) do
		sumSin = sumSin + math.sin(v)
		sumCos = sumCos + math.cos(v)
	end
	return math.atan2(sumSin,sumCos)
end

-- converts and angle back to a time string
local function angleToTime(angle)
	local abs = angle % (math.pi * 2)
	local time = abs / math.pi * 12
	local h = math.floor(time)
	local m = math.floor(time * 60) % 60
	local s = math.floor(time * 3600) % 60
	return string.format("%02d:%02d:%02d", h, m, s)
end

-- convert times to angles
for k,v in pairs(times) do
	times[k] = timeToAngle(v)
end

print(angleToTime(meanAngle(times)))
Output:
23:47:43 

Mathematica / Wolfram Language

meanTime[list_] := 
  StringJoin@
   Riffle[ToString /@ 
       Floor@{Mod[24 #, 24], Mod[24*60 #, 60], Mod[24*60*60 #, 60]} &[
     Arg[Mean[
        Exp[FromDigits[ToExpression@StringSplit[#, ":"], 60] & /@ 
            list/(24*60*60) 2 Pi I]]]/(2 Pi)], ":"];
meanTime[{"23:00:17", "23:40:20", "00:12:45", "00:17:19"}]
Output:
23:47:43

MATLAB / Octave

function t = mean_time_of_day(t) 
    c = pi/(12*60*60);
    for k=1:length(t)
	a = sscanf(t{k},'%d:%d:%d');
	phi(k) = (a(1)*3600+a(2)*60+a(3));
    end;
    d = angle(mean(exp(i*phi*c)))/(2*pi); % days 
    if (d<0) d += 1;
    t = datestr(d,"HH:MM:SS");
end;
mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'})
ans = 23:47:43

Nim

Works with: Nim version 0.20.0+
import math, complex, strutils, sequtils
 
proc meanAngle(deg: openArray[float]): float =
  var c: Complex[float]
  for d in deg:
    c += rect(1.0, degToRad(d))
  radToDeg(phase(c / float(deg.len)))
 
proc meanTime(times: openArray[string]): string =
  const day = 24 * 60 * 60
  let
    angles = times.map(proc(time: string): float =
      let t = time.split(":")
      (t[2].parseInt + t[1].parseInt * 60 + t[0].parseInt * 3600) * 360 / day)
    ms = (angles.meanAngle * day / 360 + day) mod day
    (h,m,s) = (ms.int div 3600, (ms.int mod 3600) div 60, ms.int mod 60)
 
  align($h, 2, '0') & ":" & align($m, 2, '0') & ":" & align($s, 2, '0')
 
echo meanTime(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
Output:
23:47:43

Oberon-2

Works with: oo2c
MODULE AvgTimeOfDay;
IMPORT
  M := LRealMath,
  T := NPCT:Tools,
  Out := NPCT:Console;

CONST
  secsDay = 86400;
  secsHour = 3600;
  secsMin = 60;

  toRads = M.pi / 180;

VAR
  h,m,s: LONGINT;
  data: ARRAY 4 OF LONGREAL;

PROCEDURE TimeToDeg(time: STRING): LONGREAL;
VAR
  parts: ARRAY 3 OF STRING;
  h,m,s: LONGREAL;
BEGIN
  T.Split(time,':',parts);
  h := T.StrToInt(parts[0]);
  m := T.StrToInt(parts[1]);
  s := T.StrToInt(parts[2]);
  RETURN (h * secsHour + m * secsMin + s) * 360 / secsDay;
END TimeToDeg;

PROCEDURE DegToTime(d: LONGREAL; VAR h,m,s: LONGINT);
VAR
  ds: LONGREAL;
  PROCEDURE Mod(x,y: LONGREAL): LONGREAL;
  VAR
    c: LONGREAL;
  BEGIN
    c := ENTIER(x / y);
    RETURN x - c * y
  END Mod;
BEGIN
  ds :=  Mod(d,360.0) * secsDay / 360.0;
  h := ENTIER(ds / secsHour);
  m := ENTIER(Mod(ds,secsHour) / secsMin);
  s := ENTIER(Mod(ds,secsMin));
END DegToTime;

PROCEDURE Mean(g: ARRAY OF LONGREAL): LONGREAL;
VAR
  i,l: LONGINT;
  sumSin, sumCos: LONGREAL;
BEGIN
  i := 0;l := LEN(g);sumSin := 0.0;sumCos := 0.0;
  WHILE i < l  DO
    sumSin := sumSin + M.sin(g[i] * toRads);
    sumCos := sumCos + M.cos(g[i] * toRads);  
    INC(i)
  END;
  RETURN M.arctan2(sumSin / l,sumCos / l) * 180 / M.pi;
END Mean;

BEGIN
  data[0] := TimeToDeg("23:00:17");
  data[1] := TimeToDeg("23:40:20");
  data[2] := TimeToDeg("00:12:45");
  data[3] := TimeToDeg("00:17:19");

  DegToTime(Mean(data),h,m,s);
  Out.String(":> ");Out.Int(h,0);Out.Char(':');Out.Int(m,0);Out.Char(':');Out.Int(s,0);Out.Ln

END AvgTimeOfDay.
Output:
:> 23:47:43

OCaml

let pi_twice = 2.0 *. 3.14159_26535_89793_23846_2643
let day = float (24 * 60 * 60)

let rad_of_time t =
  t *. pi_twice /. day
 
let time_of_rad r =
  r *. day /. pi_twice

let mean_angle angles =
  let sum_sin = List.fold_left (fun sum a -> sum +. sin a) 0.0 angles
  and sum_cos = List.fold_left (fun sum a -> sum +. cos a) 0.0 angles in
  atan2 sum_sin sum_cos

let mean_time times =
  let angles = List.map rad_of_time times in
  let t = time_of_rad (mean_angle angles) in
  if t < 0.0 then t +. day else t

let parse_time t =
  Scanf.sscanf t "%d:%d:%d" (fun h m s -> float (s + m * 60 + h * 3600))

let round x = int_of_float (floor (x +. 0.5))

let string_of_time t =
  let t = round t in
  let h = t / 3600 in
  let rem = t mod 3600 in
  let m = rem / 60 in
  let s = rem mod 60 in
  Printf.sprintf "%d:%d:%d" h m s

let () =
  let times = ["23:00:17"; "23:40:20"; "00:12:45"; "00:17:19"] in
  Printf.printf "The mean time of [%s] is: %s\n"
    (String.concat "; " times)
    (string_of_time (mean_time (List.map parse_time times)))
Output:
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43

ooRexx

/* REXX ---------------------------------------------------------------
* 25.06.2014 Walter Pachl
*--------------------------------------------------------------------*/
times='23:00:17 23:40:20 00:12:45 00:17:19'
sum=0
day=86400
x=0
y=0
Do i=1 To words(times)                 /* loop over times            */
  time.i=word(times,i)                 /* pick a time                */
  alpha.i=t2a(time.i)                  /* convert to angle (degrees) */
  /* Say time.i format(alpha.i,6,9) */
  x=x+rxcalcsin(alpha.i)               /* accumulate sines           */
  y=y+rxcalccos(alpha.i)               /* accumulate cosines         */
  End
ww=rxcalcarctan(x/y)                   /* compute average angle      */
ss=ww*86400/360                        /* convert to seconds         */
If ss<0 Then ss=ss+day                 /* avoid negative value       */
m=ss%60                                /* split into hh mm ss        */
s=ss-m*60
h=m%60
m=m-h*60
Say f2(h)':'f2(m)':'f2(s)              /* show the mean time         */
Exit

t2a: Procedure Expose day              /* convert time to angle      */
  Parse Arg hh ':' mm ':' ss
  sec=(hh*60+mm)*60+ss
  If sec>(day/2) Then
    sec=sec-day
  a=360*sec/day
  Return a

f2: return right(format(arg(1),2,0),2,0)

::requires rxmath library
Output:
23:47:43

PARI/GP

meanAngle(v)=atan(sum(i=1,#v,sin(v[i]))/sum(i=1,#v,cos(v[i])))%(2*Pi)
meanTime(v)=my(x=meanAngle(2*Pi*apply(u->u[1]/24+u[2]/1440+u[3]/86400, v))*12/Pi); [x\1, 60*(x-=x\1)\1, round(60*(60*x-60*x\1))]
meanTime([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])
Output:
[23, 47, 43]

Perl

Traditional

Using the core module Math::Complex to enable use of complex numbers. The POSIX CPAN module provides the fmod routine for non-integer modulus calculations.

Translation of: Raku
use strict;
use warnings;
use POSIX 'fmod';
use Math::Complex;
use List::Util qw(sum);
use utf8;

use constant τ => 2 * 3.1415926535;

# time-of-day to radians
sub tod2rad {
    ($h,$m,$s) = split /:/, @_[0];
    (3600*$h + 60*$m + $s) * τ / 86400;
}

# radians to time-of-day
sub rad2tod {
    my $x = $_[0] * 86400 / τ;
    sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60);
}

# float modulus, normalized to positive values
sub fm  {
    my($n,$b) = @_;
    $x = fmod($n,$b);
    $x += $b if $x < 0;
}

sub phase     { arg($_[0]) }  # aka theta
sub cis       { cos($_[0]) + i*sin($_[0]) }
sub mean_time { rad2tod phase sum map { cis tod2rad $_ } @_ }

@times = ("23:00:17", "23:40:20", "00:12:45", "00:17:19");
print mean_time(@times) . " is the mean time of " . join(' ', @times) . "\n";
Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19

v5.36

As previous, but using features from an up-to-date release of Perl, e.g. strict/warn/subroutine signatures without the use boilerplate.

use v5.36;
use POSIX 'fmod';
use Math::Complex;
use List::Util 'sum';
use utf8;

use constant τ => 2 * 2 * atan2(1, 0);

sub R_to_ToD ($radians) { my $x = $radians * 86400 / τ; sprintf '%02d:%02d:%02d', fm($x/3600,24), fm($x/60,60), fm($x,60) }
sub ToD_to_R ($h,$m,$s) { (3600*$h + 60*$m + $s) * τ / 86400 }
sub fm       ($n,$b)    { my $x = fmod($n,$b); $x += $b if $x < 0 }
sub cis      ($radians) { cos($radians) + i*sin($radians) }
sub phase    ($Θ)       { arg(  ) }
sub mean_time(@t)       { R_to_ToD phase sum map { cis ToD_to_R split ':', $_ } @t }

my @times = <23:00:17 23:40:20 00:12:45 00:17:19>;
say my $result = mean_time(@times) . ' is the mean time of ' . join ' ', @times;
Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19

Phix

with javascript_semantics
function MeanAngle(sequence angles)
    atom x = 0, y = 0
    for i=1 to length(angles) do
        atom ai_rad = angles[i]*PI/180
        x += cos(ai_rad)
        y += sin(ai_rad)
    end for
    if abs(x)<1e-16 then return "not meaningful" end if
    return atan2(y,x)*180/PI
end function
 
function toSecAngle(integer hours, integer minutes, integer seconds)
    return ((hours*60+minutes)*60+seconds)/(24*60*60)*360
end function
 
constant Times = {toSecAngle(23,00,17),
                  toSecAngle(23,40,20),
                  toSecAngle(00,12,45),
                  toSecAngle(00,17,19)}
 
function toHMS(object s)
    if not string(s) then
        if s<0 then s+=360 end if
        s = 24*60*60*s/360
        atom hours = floor(s/3600),
             mins = floor(remainder(s,3600)/60),
             secs = remainder(s,60)
        s = sprintf("%02d:%02d:%02d",{hours,mins,secs})
    end if
    return s
end function
 
printf(1,"Mean Time is %s\n",{toHMS(MeanAngle(Times))})
Output:
Mean Time is 23:47:43

PHP

<?php
function time2ang($tim) {
        if (!is_string($tim)) return $tim;
        $parts = explode(':',$tim);
        if (count($parts)!=3) return $tim;
        $sec = ($parts[0]*3600)+($parts[1]*60)+$parts[2];
        $ang = 360.0 * ($sec/86400.0);
        return $ang;
}
function ang2time($ang) {
        if (!is_numeric($ang)) return $ang;
        $sec = 86400.0 * $ang / 360.0;
        $parts = array(floor($sec/3600),floor(($sec % 3600)/60),$sec % 60);
        $tim = sprintf('%02d:%02d:%02d',$parts[0],$parts[1],$parts[2]);
        return $tim;
}
function meanang($ang) {
        if (!is_array($ang)) return $ang;
        $sins = 0.0;
        $coss = 0.0;
        foreach($ang as $a) {
                $sins += sin(deg2rad($a));
                $coss += cos(deg2rad($a));
        }
        $avgsin = $sins / (0.0+count($ang));
        $avgcos = $coss / (0.0+count($ang));
        $avgang = rad2deg(atan2($avgsin,$avgcos));
        while ($avgang < 0.0) $avgang += 360.0;
        return $avgang;
}
$bats = array('23:00:17','23:40:20','00:12:45','00:17:19');
$angs = array();
foreach ($bats as $t) $angs[] = time2ang($t);
$ma = meanang($angs);
$result = ang2time($ma);
print "The mean time of day is $result (angle $ma).\n";
?>
Output:
The mean time of day is 23:47:43 (angle 356.9306730355).

PicoLisp

(load "@lib/math.l")

(de meanTime (Lst)
   (let Tim
      (*/
         (atan2
            (sum '((S) (sin (*/ ($tim S) pi 43200))) Lst)
            (sum '((S) (cos (*/ ($tim S) pi 43200))) Lst) )
         43200 pi )
      (tim$ (% (+ Tim 86400) 86400) T) ) )
Test:
: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
-> "23:47:43"

PL/I

*process source attributes xref;
 avt: Proc options(main);
 /*--------------------------------------------------------------------
 * 25.06.2014 Walter Pachl taken from REXX
 *-------------------------------------------------------------------*/
 Dcl (addr,hbound,sin,cos,atan) Builtin;
 Dcl sysprint Print;
 Dcl times(4) Char(8) Init('23:00:17','23:40:20','00:12:45','00:17:19');
 Dcl time Char(8);
 Dcl (alpha,x,y,ss,ww) Dec Float(18) Init(0);
 Dcl day Bin Fixed(31) Init(86400);
 Dcl pi Dec Float(18) Init(3.14159265358979323846);
 Dcl (i,h,m,s) bin Fixed(31) Init(0);
 Do i=1 To hbound(times);              /* loop over times            */
  time=times(i);                       /* pick a time                */
  alpha=t2a(time);                     /* convert to angle (radians) */
  x=x+sin(alpha);                      /* accumulate sines           */
  y=y+cos(alpha);                      /* accumulate cosines         */
  End;
 ww=atan(x/y);                         /* compute average angle      */
 ss=ww*day/(2*pi);                     /* convert to seconds         */
 If ss<0 Then ss=ss+day;               /* avoid negative value       */
 m=ss/60;                              /* split into hh mm ss        */
 s=ss-m*60;
 h=m/60;
 m=m-h*60;
 Put Edit(h,':',m,':',s)(Skip,3(p'99',a));

 t2a: Procedure(t) Returns(Bin Float(18)); /* convert time to angle  */
 Dcl t Char(8);
 Dcl 1 tt Based(addr(t)),
      2 hh Pic'99',
      2 * Char(1),
      2 mm Pic'99',
      2 * Char(1),
      2 ss Pic'99';
 Dcl sec Bin Fixed(31);
 Dcl a   Bin Float(18);
 sec=(hh*60+mm)*60+ss;
 If sec>(day/2) Then
   sec=sec-day;
 a=2*pi*sec/day;
 Return (a);
 End;

 End;
Output:
23:47:43

PowerShell

function Get-MeanTimeOfDay
{
    [CmdletBinding()]
    [OutputType([timespan])]
    Param
    (
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [ValidatePattern("(?:2[0-3]|[01]?[0-9])[:.][0-5]?[0-9][:.][0-5]?[0-9]")]
        [string[]]
        $Time
    )

    Begin
    {
        [double[]]$angles = @()

        function ConvertFrom-Time ([timespan]$Time)
        {
            [double]((360 * $Time.Hours / 24) + (360 * $Time.Minutes / (24 * 60)) + (360 * $Time.Seconds / (24 * 3600)))
        }

        function ConvertTo-Time ([double]$Angle)
        {
            $t = New-TimeSpan -Hours   ([int](24 * 60 * 60 * $Angle / 360) / 3600) `
                              -Minutes (([int](24 * 60 * 60 * $Angle / 360) % 3600 - [int](24 * 60 * 60 * $Angle / 360) % 60) / 60) `
                              -Seconds ([int]((24 * 60 * 60 * $Angle / 360) % 60))

            if ($t.Days -gt 0)
            {
                return ($t - (New-TimeSpan -Hours 1))
            }

            $t
        }

        function Get-MeanAngle ([double[]]$Angles)
        {
            [double]$x,$y = 0

            for ($i = 0; $i -lt $Angles.Count; $i++)
            { 
                $x += [Math]::Cos($Angles[$i] * [Math]::PI / 180)
                $y += [Math]::Sin($Angles[$i] * [Math]::PI / 180)
            }

            $result = [Math]::Atan2(($y / $Angles.Count), ($x / $Angles.Count)) * 180 / [Math]::PI

            if ($result -lt 0)
            {
                return ($result + 360)
            }

            $result
        }
    }
    Process
    {
        $angles += ConvertFrom-Time $_
    }
    End
    {
        ConvertTo-Time (Get-MeanAngle $angles)
    }
}
[timespan]$meanTimeOfDay = "23:00:17","23:40:20","00:12:45","00:17:19" | Get-MeanTimeOfDay
"Mean time is {0}" -f (Get-Date $meanTimeOfDay.ToString()).ToString("hh:mm:ss tt")
Output:
Mean time is 11:47:43 PM

Python

from cmath import rect, phase
from math import radians, degrees


def mean_angle(deg):
    return degrees(phase(sum(rect(1, radians(d)) for d in deg)/len(deg)))

def mean_time(times):
    t = (time.split(':') for time in times)
    seconds = ((float(s) + int(m) * 60 + int(h) * 3600) 
               for h, m, s in t)
    day = 24 * 60 * 60
    to_angles = [s * 360. / day for s in seconds]
    mean_as_angle = mean_angle(to_angles)
    mean_seconds = mean_as_angle * day / 360.
    if mean_seconds < 0:
        mean_seconds += day
    h, m = divmod(mean_seconds, 3600)
    m, s = divmod(m, 60)
    return '%02i:%02i:%02i' % (h, m, s)


if __name__ == '__main__':
    print( mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"]) )
Output:
23:47:43

Racket

#lang racket
(define (mean-angle/radians as)
  (define n (length as))
  (atan (* (/ 1 n) (for/sum ([αj as]) (sin αj)))
        (* (/ 1 n) (for/sum ([αj as]) (cos αj)))))
(define (mean-time times)
  (define secs/day (* 60 60 24))
  (define (time->deg time)
    (/ (for/fold ([sum 0]) ([t (map string->number (string-split time ":"))])
         (+ (* 60 sum) t))
       secs/day 1/360 (/ 180 pi)))
  (define secs
    (modulo (inexact->exact (round (* (mean-angle/radians (map time->deg times))
                                      (/ 180 pi) 1/360 secs/day)))
            secs/day))
  (let loop ([s secs] [ts '()])
    (if (zero? s) (string-join ts ":")
        (let-values ([(q r) (quotient/remainder s 60)])
          (loop q (cons (~r r #:min-width 2 #:pad-string "0") ts))))))
(mean-time '("23:00:17" "23:40:20" "00:12:45" "00:17:19"))
Output:
"23:47:43"

Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12
sub tod2rad($_) { [+](.comb(/\d+/) Z* 3600,60,1) * tau / 86400 }
 
sub rad2tod ($r) {
    my $x = $r * 86400 / tau;
    (($x xx 3 Z/ 3600,60,1) Z% 24,60,60).fmt('%02d',':');
}
 
sub phase ($c) { $c.polar[1] }
 
sub mean-time (@t) { rad2tod phase [+] map { cis tod2rad $_ }, @t }

my @times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"];
 
say "{ mean-time(@times) } is the mean time of @times[]";
Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19

REXX

/* REXX ---------------------------------------------------------------
* 25.06.2014 Walter Pachl
* taken from ooRexx using my very aged sin/cos/artan functions
*--------------------------------------------------------------------*/
times='23:00:17 23:40:20 00:12:45 00:17:19'
sum=0
day=86400
pi=3.14159265358979323846264
x=0
y=0
Do i=1 To words(times)                 /* loop over times            */
  time.i=word(times,i)                 /* pick a time                */
  alpha.i=t2a(time.i)                  /* convert to angle (radians) */
  /* Say time.i format(alpha.i,6,9) */
  x=x+sin(alpha.i)                     /* accumulate sines           */
  y=y+cos(alpha.i)                     /* accumulate cosines         */
  End
ww=arctan(x/y)                         /* compute average angle      */
ss=ww*86400/(2*pi)                     /* convert to seconds         */
If ss<0 Then ss=ss+day                 /* avoid negative value       */
m=ss%60                                /* split into hh mm ss        */
s=ss-m*60
h=m%60
m=m-h*60
Say f2(h)':'f2(m)':'f2(s)              /* show the mean time         */
Exit

t2a: Procedure Expose day pi           /* convert time to angle      */
  Parse Arg hh ':' mm ':' ss
  sec=(hh*60+mm)*60+ss
  If sec>(day/2) Then
    sec=sec-day
  a=2*pi*sec/day
  Return a

f2: return right(format(arg(1),2,0),2,0)


sin: Procedure Expose pi
  Parse Arg x
  prec=digits()
  Numeric Digits (2*prec)
  Do While x>pi
    x=x-pi
    End
  Do While x<-pi
    x=x+pi
    End
  o=x
  u=1
  r=x
  Do i=3 By 2
    ra=r
    o=-o*x*x
    u=u*i*(i-1)
    r=r+(o/u)
    If r=ra Then Leave
    End
  Numeric Digits prec
  Return r+0

cos: Procedure Expose pi
  Parse Arg x
  prec=digits()
  Numeric Digits (2*prec)
  Numeric Fuzz 3
  o=1
  u=1
  r=1
  Do i=1 By 2
    ra=r
    o=-o*x*x
    u=u*i*(i+1)
    r=r+(o/u)
    If r=ra Then Leave
    End
  Numeric Digits prec
  Return r+0

arctan: Procedure
  Parse Arg x
  prec=digits()
  Numeric Digits (2*prec)
  Numeric Fuzz 3
  o=x
  u=1
  r=x
  k=0
  Do i=3 By 2
    ra=r
    o=-o*x*x
    r=r+(o/i)
    If r=ra Then
      Leave
    k=k+1
    If k//1000=0 Then
      Say i left(r,40) format(abs(o/i),15,5)
    End
  Numeric Digits (prec)
  Return r+0
Output:
23:47:43

RPL

Works with: Halcyon Calc version 4.2.7
≪ → angles
  ≪  0 1 angles SIZE FOR j
        1 angles j GET R→C P→R + NEXT
      angles SIZE / ARG      
≫ ≫ 'MEANG' STO 
≪ → times
  ≪  { } 1 times SIZE FOR j
        1 times j GET HMS→ 15 * + NEXT
      MEANG 15 / 24 MOD →HMS 4 FIX RND STD
≫ ≫ 'MTIME' STO
{23.0017 23.4020 0.1245 0.1719 } MTIME
Output:
1: 23.4743

Ruby

Using the methods at [angle]

def time2deg(t)
  raise "invalid time" unless m = t.match(/^(\d\d):(\d\d):(\d\d)$/)
  hh,mm,ss = m[1..3].map {|e| e.to_i}
  raise "invalid time" unless (0..23).include? hh and
                              (0..59).include? mm and
                              (0..59).include? ss
  (hh*3600 + mm*60 + ss) * 360 / 86400.0
end

def deg2time(d)
  sec = (d % 360) * 86400 / 360.0
  "%02d:%02d:%02d" % [sec/3600, (sec%3600)/60, sec%60]
end

def mean_time(times)
  deg2time(mean_angle(times.map {|t| time2deg t}))
end

puts mean_time ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
Output:
23:47:43

Run BASIC

global pi
pi = acs(-1)
 
Print "Average of:"
for i = 1 to 4
    read t$ 
    print t$
    a  = time2angle(t$)
    ss = ss+sin(a)
    sc = sc+cos(a)
next
a = atan2(ss,sc)
if a < 0 then a = a + 2 * pi
print "is ";angle2time$(a)
end
data "23:00:17", "23:40:20", "00:12:45", "00:17:19"
 
function nn$(n)
    nn$ = right$("0";n, 2)
end function
 
function angle2time$(a)
    a  = int(a / 2 / pi * 24 * 60 * 60)
    ss = a mod 60
    a  = int(a / 60)
    mm=a mod 60
    hh=int(a/60)
    angle2time$=nn$(hh);":";nn$(mm);":";nn$(ss)
end function
 
function time2angle(time$)
    hh=val(word$(time$,1,":"))
    mm=val(word$(time$,2,":"))
    ss=val(word$(time$,3,":"))
    time2angle=2*pi*(60*(60*hh+mm)+ss)/24/60/60
end function
 
function atan2(y, x)
       if y <> 0 then
        atan2 = (2 * (atn((sqr((x * x) + (y * y)) - x)/ y)))
        else
        atan2 = (y=0)*(x<0)*pi
       end if
End Function

Rust

use std::f64::consts::PI;

#[derive(Debug, PartialEq, Eq)]
struct Time {
    h: u8,
    m: u8,
    s: u8,
}

impl Time {
    /// Create a Time from equivalent radian measure
    fn from_radians(mut rads: f64) -> Time {
        rads %= 2.0 * PI;
        if rads < 0.0 {
            rads += 2.0 * PI
        }
        Time {
            h: (rads * 12.0 / PI) as u8,
            m: ((rads * 720.0 / PI) % 60.0) as u8,
            s: ((rads * 43200.0 / PI) % 60.0).round() as u8,
        }
    }

    /// Create a Time from H/M/S
    fn from_parts(h: u8, m: u8, s: u8) -> Result<Time, ()> {
        if h > 23 || m > 59 || s > 59 {
            return Err(());
        }
        Ok(Time { h, m, s })
    }

    /// Return time as measure in radians
    fn as_radians(&self) -> f64 {
        ((self.h as f64 / 12.0) + (self.m as f64 / 720.0) + (self.s as f64 / 43200.0)) * PI
    }
}

/// Compute the mean time from a slice of times
fn mean_time(times: &[Time]) -> Time {
    // compute sum of sines and cosines
    let (ss, sc) = times
        .iter()
        .map(Time::as_radians)
        .map(|a| (a.sin(), a.cos()))
        .fold((0.0, 0.0), |(ss, sc), (s, c)| (ss + s, sc + c));
    // scaling does not matter for atan2, meaning we do not have to divide sums by len
    Time::from_radians(ss.atan2(sc))
}

fn main() {
    let times = [
        Time::from_parts(23, 00, 17).unwrap(),
        Time::from_parts(23, 40, 20).unwrap(),
        Time::from_parts(00, 12, 45).unwrap(),
        Time::from_parts(00, 17, 19).unwrap(),
    ];

    let mean = mean_time(&times);

    println!("{:02}:{:02}:{:02}", mean.h, mean.m, mean.s);
}
Output:
23:47:43

Scala

import java.time.LocalTime
import scala.compat.Platform

trait MeanAnglesComputation {
  import scala.math.{Pi, atan2, cos, sin}

  def meanAngle(angles: List[Double], convFactor: Double = 180.0 / Pi) = {
    val sums = angles.foldLeft((.0, .0))((r, c) => {
      val rads = c / convFactor
      (r._1 + sin(rads), r._2 + cos(rads))
    })
    val result = atan2(sums._1, sums._2)
    (result + (if (result.signum == -1) 2 * Pi else 0.0)) * convFactor
  }
}

object MeanBatTime extends App with MeanAnglesComputation {
  val dayInSeconds = 60 * 60 * 24

  def times = batTimes.map(t => afterMidnight(t).toDouble)

  def afterMidnight(twentyFourHourTime: String) = {
    val t = LocalTime.parse(twentyFourHourTime)
    (if (t.isBefore(LocalTime.NOON)) dayInSeconds else 0) + LocalTime.parse(twentyFourHourTime).toSecondOfDay
  }

  def batTimes = List("23:00:17", "23:40:20", "00:12:45", "00:17:19")
  assert(LocalTime.MIN.plusSeconds(meanAngle(times, dayInSeconds).round).toString == "23:47:40")
  println(s"Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")
}

Scheme

Library: Scheme/SRFIs

To be self-contained, this starts with the functions from Averages/Mean angle

(import (scheme base)
        (scheme inexact)
        (scheme read)
        (scheme write)
        (srfi 1))         ; for fold

;; functions copied from "Averages/Mean angle" task
(define (average l)
  (/ (fold + 0 l) (length l)))

(define pi 3.14159265358979323846264338327950288419716939937510582097) 

(define (radians a)
  (* pi 1/180 a))

(define (degrees a)
  (* 180 (/ 1 pi) a))

(define (mean-angle angles)
  (let* ((angles (map radians angles))
         (cosines (map cos angles))
         (sines (map sin angles)))
    (degrees (atan (average sines) (average cosines)))))

;; -- new functions for this task
(define (time->angle time)
  (let* ((time2 ; replaces : with space in string
           (string-map (lambda (c) (if (char=? c #\:) #\space c)) time))
         (string-port (open-input-string time2))
         (hour (read string-port))
         (minutes (read string-port))
         (seconds (read string-port)))
    (/ (* 360 (+ (* hour 3600) (* minutes 60) seconds))
       (* 24 60 60))))

(define (angle->time angle)
  (let* ((nom-angle (if (negative? angle) (+ 360 angle) angle))
         (time (/ (* nom-angle 24 60 60) 360))
         (hour (exact (floor (/ time 3600))))
         (minutes (exact (floor (/ (- time (* 3600 hour)) 60))))
         (seconds (exact (floor (- time (* 3600 hour) (* 60 minutes))))))
    (string-append (number->string hour)
                   ":"
                   (number->string minutes)
                   ":"
                   (number->string seconds))))

(define (mean-time-of-day times)
  (angle->time (mean-angle (map time->angle times))))

(write (mean-time-of-day '("23:00:17" "23:40:20" "00:12:45" "00:17:19")))
(newline)
Output:
"23:47:43"

Sidef

Translation of: Ruby

Using the mean_angle() function from: "Averages/Mean angle"

func time2deg(t) {
  (var m = t.match(/^(\d\d):(\d\d):(\d\d)$/)) || die "invalid time"
  var (hh,mm,ss) = m.cap.map{.to_i}...
  ((hh ~~ 24.range) && (mm ~~ 60.range) && (ss ~~ 60.range)) || die "invalid time"
  (hh*3600 + mm*60 + ss) * 360 / 86400
}
 
func deg2time(d) {
  var sec = ((d % 360) * 86400 / 360)
  "%02d:%02d:%02d" % (sec/3600, (sec%3600)/60, sec%60)
}
 
func mean_time(times) {
  deg2time(mean_angle(times.map {|t| time2deg(t)}))
}
 
say mean_time(["23:00:17", "23:40:20", "00:12:45", "00:17:19"])
Output:
23:47:43

SQL/PostgreSQL

Translation of: Python
--Setup table for testing
CREATE TABLE time_table(times time);
INSERT INTO time_table values ('23:00:17'::time),('23:40:20'::time),('00:12:45'::time),('00:17:19'::time)

--Compute mean time
SELECT to_timestamp((degrees(atan2(AVG(sin),AVG(cos))))* (24*60*60)/360)::time
FROM
	(SELECT
	cos(radians(t*360/(24*60*60))),sin(radians(t*360/(24*60*60)))
	FROM
		(SELECT EXTRACT(epoch from times) t
		FROM time_table) T1
	)T2

Output:

23:47:43.361529

Swift

import Foundation

@inlinable public func d2r<T: FloatingPoint>(_ f: T) -> T { f * .pi / 180 }
@inlinable public func r2d<T: FloatingPoint>(_ f: T) -> T { f * 180 / .pi }

public func meanOfAngles(_ angles: [Double]) -> Double {
  let cInv = 1 / Double(angles.count)
  let (y, x) =
    angles.lazy
      .map(d2r)
      .map({ (sin($0), cos($0)) })
      .reduce(into: (0.0, 0.0), { $0.0 += $1.0; $0.1 += $1.1 })

  return r2d(atan2(cInv * y, cInv * x))
}

struct DigitTime {
  var hour: Int
  var minute: Int
  var second: Int

  init?(fromString str: String) {
    let split = str.components(separatedBy: ":").compactMap(Int.init)

    guard split.count == 3 else {
      return nil
    }

    (hour, minute, second) = (split[0], split[1], split[2])
  }

  init(fromDegrees angle: Double) {
    let totalSeconds = 24 * 60 * 60 * angle / 360

    second = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
    minute = Int((totalSeconds.truncatingRemainder(dividingBy: 3600) - Double(second)) / 60)
    hour = Int(totalSeconds / 3600)
  }

  func toDegrees() -> Double {
    return 360 * Double(hour) / 24.0 + 360 * Double(minute) / (24 * 60.0) + 360 * Double(second) / (24 * 3600.0)
  }
}

extension DigitTime: CustomStringConvertible {
  var description: String { String(format: "%02i:%02i:%02i", hour, minute, second) }
}

let times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"].compactMap(DigitTime.init(fromString:))

guard times.count == 4 else {
  fatalError()
}

let meanTime = DigitTime(fromDegrees: 360 + meanOfAngles(times.map({ $0.toDegrees() })))

print("Given times \(times), the mean time is \(meanTime)")
Output:
Given times [23:00:17, 23:40:20, 00:12:45, 00:17:19], the mean time is 23:47:43

Tcl

proc meanTime {times} {
    set secsPerRad [expr {60 * 60 * 12 / atan2(0,-1)}]
    set sumSin [set sumCos 0.0]
    foreach t $times {
	# Convert time to count of seconds from midnight
	scan $t "%02d:%02d:%02d" h m s
	incr s [expr {[incr m [expr {$h * 60}]] * 60}]
	# Feed into averaging
	set sumSin [expr {$sumSin + sin($s / $secsPerRad)}]
	set sumCos [expr {$sumCos + cos($s / $secsPerRad)}]
    }
    # Don't need to divide by counts; atan2() cancels that out
    set a [expr {round(atan2($sumSin, $sumCos) * $secsPerRad)}]
    # Convert back to human-readable
    format "%02d:%02d:%02d" [expr {$a / 60 / 60 % 24}] [expr {$a / 60 % 60}] [expr {$a % 60}]
}

puts [meanTime {23:00:17 23:40:20 00:12:45 00:17:19}]
Output:
23:47:43

VBA

Uses Excel and mean angle.

Public Sub mean_time()
    Dim angles() As Double
    s = [{"23:00:17","23:40:20","00:12:45","00:17:19"}]
    For i = 1 To UBound(s)
        s(i) = 360 * TimeValue(s(i))
    Next i
    Debug.Print Format(mean_angle(s) / 360 + 1, "hh:mm:ss")
End Sub
Output:
23:47:43

Visual Basic .NET

Translation of: C#
Module Module1

    Function TimeToDegrees(time As TimeSpan) As Double
        Return 360 * time.Hours / 24.0 + 360 * time.Minutes / (24 * 60.0) + 360 * time.Seconds / (24 * 3600.0)
    End Function

    Function DegreesToTime(angle As Double) As TimeSpan
        Return New TimeSpan((24 * 60 * 60 * angle \ 360) \ 3600, ((24 * 60 * 60 * angle \ 360) Mod 3600 - (24 * 60 * 60 * angle \ 360) Mod 60) \ 60, (24 * 60 * 60 * angle \ 360) Mod 60)
    End Function

    Function MeanAngle(angles As List(Of Double)) As Double
        Dim y_part = 0.0
        Dim x_part = 0.0
        Dim numItems = angles.Count

        For Each angle In angles
            x_part += Math.Cos(angle * Math.PI / 180)
            y_part += Math.Sin(angle * Math.PI / 180)
        Next

        Return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI
    End Function

    Sub Main()
        Dim digitimes As New List(Of Double)
        Dim digitime As TimeSpan
        Dim input As String

        Console.WriteLine("Enter times, end with no input: ")
        Do
            input = Console.ReadLine
            If Not String.IsNullOrWhiteSpace(input) Then
                If TimeSpan.TryParse(input, digitime) Then
                    digitimes.Add(TimeToDegrees(digitime))
                Else
                    Console.WriteLine("Seems this is wrong input: ingnoring time")
                End If
            End If
        Loop Until String.IsNullOrWhiteSpace(input)

        If digitimes.Count > 0 Then
            Console.WriteLine("The mean time is : {0}", DegreesToTime(360 + MeanAngle(digitimes)))
        End If
    End Sub

End Module
Output:
Enter times, end with no input:
23:00:17
23:40:20
00:12:45
00:17:19

The mean time is : 23:47:43

V (Vlang)

Translation of: Wren
import math

const inputs = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
 
fn main() {    
    angles := inputs.map(time_to_degs(it))
    println('Mean time of day is: ${degs_to_time(mean_angle(angles))}')
}
fn mean_angle(angles []f64) f64 {
    n := angles.len
    mut sin_sum := f64(0)
    mut cos_sum := f64(0)
    for angle in angles {
        sin_sum += math.sin(angle * math.pi / 180)
        cos_sum += math.cos(angle * math.pi / 180)
    }
    return math.atan2(sin_sum/n, cos_sum/n) * 180 / math.pi
}

fn degs_to_time(dd f64) string{
    mut d := dd
    for d < 0 {
        d += 360
    }
    mut s := math.round(d * 240)
    h := math.floor(s/3600)
    mut m := math.fmod(s, 3600)
    s = math.fmod(m, 60)
    m = math.floor(m / 60)
    return "${h:02}:${m:02}:${s:02}"
}
 
fn time_to_degs(time string) f64 {
    t := time.split(":")
    h := t[0].f64() * 3600
    m := t[1].f64() * 60
    s := t[2].f64()
    return (h + m + s) / 240
}
Output:
Mean time of day is: 23:47:43

Wren

Library: Wren-fmt
import "./fmt" for Fmt

var timeToDegs = Fn.new { |time|
    var t = time.split(":")
    var h = Num.fromString(t[0]) * 3600
    var m = Num.fromString(t[1]) * 60
    var s = Num.fromString(t[2])
    return (h + m + s) / 240
}

var degsToTime = Fn.new { |d|
    while (d < 0) d = d + 360
    var s = (d * 240).round
    var h = (s/3600).floor
    var m = s % 3600
    s = m % 60
    m = (m / 60).floor
    return Fmt.swrite("$2d:$2d:$2d", h, m, s)
}

var meanAngle = Fn.new { |angles|
    var n = angles.count
    var sinSum = 0
    var cosSum = 0
    for (angle in angles) {
        sinSum = sinSum + (angle * Num.pi / 180).sin
        cosSum = cosSum + (angle * Num.pi / 180).cos
    }
    return (sinSum/n).atan(cosSum/n) * 180 / Num.pi
}

var times = ["23:00:17", "23:40:20", "00:12:45", "00:17:19"]
var angles = times.map { |t| timeToDegs.call(t) }.toList
System.print("Mean time of day is : %(degsToTime.call(meanAngle.call(angles)))")
Output:
Mean time of day is : 23:47:43

XPL0

include c:\cxpl\codes;

proc NumOut(N);                 \Display 2-digit N with leading zero
int  N;
[if N<10 then ChOut(0, ^0);
IntOut(0, N);
];

proc TimeOut(Sec);              \Display real seconds as HH:MM:SS
real Sec;
[NumOut(fix(Sec)/3600);  ChOut(0, ^:);
 NumOut(rem(0)/60);      ChOut(0, ^:);
 NumOut(rem(0));
];

func real HMS2Sec(H, M, S);     \Convert hours, minutes, seconds to real seconds
int  H, M, S;
return float(((H*60 + M)*60) + S);

func real MeanTime(A);          \Return the mean of the given list of times
int  A;
real X, Y, Sec;
int  I;
def Pi  = 3.14159265358979323846;
def S2R = Pi/(12.*60.*60.);     \coefficient to convert seconds to radians
[X:= 0.0;  Y:= 0.0;
for I:= 1 to A(0) do
    [Sec:= HMS2Sec(A(I,0), A(I,1), A(I,2));
    X:= X + Cos(Sec*S2R);
    Y:= Y + Sin(Sec*S2R);
    ];
Sec:= ATan2(Y,X)/S2R;
if Sec < 0.0 then Sec:= Sec + 24.*60.*60.;
return Sec;
];

TimeOut(MeanTime([4, [23,00,17], [23,40,20], [00,12,45], [00,17,19]]))
Output:
23:47:43

Yabasic

Translation of: Phix
sub atan2(y, x)
    return 2 * atan((sqrt(x **2 + y ** 2) - x) / y)
end sub
 
sub MeanAngle(angles())
    local x, y, ai_rad, l, i
	
    l = arraysize(angles(), 1)
 
    for i = 1 to l
        ai_rad = angles(i) * PI / 180
        x = x + cos(ai_rad)
        y = y + sin(ai_rad)
    next i
    if abs(x) < 1e-16 return false
    return atan2(y, x) * 180 / PI
end sub
 
sub toSecAngle(hours, minutes, seconds)
    return ((hours * 60 + minutes) * 60 + seconds) / (24 * 60 * 60) * 360
end sub

dim Times(4)

Times(1) = toSecAngle(23,00,17)
Times(2) = toSecAngle(23,40,20)
Times(3) = toSecAngle(00,12,45)
Times(4) = toSecAngle(00,17,19)

sub toHMS$(t)
    local s$
	
    if t then
        if t < 0 t = t + 360
        t = 24 * 60 * 60 * t / 360
        s$ = str$(int(t / 3600), "%02g") + ":" + str$(int(mod(t, 3600) / 60), "%02g") + ":" + str$(int(mod(t, 60)), "%02g")
    else
	s$ = "not meaningful"
    end if
    return s$
end sub

print "Mean Time is ", toHMS$(MeanAngle(Times()))

// Output: Mean Time is 23:47:43

zkl

This solution is a bit greasy, combining the solution to task "Averages/Mean angle" and some on-the-fly time-to-angle and back conversions.

var D=Time.Date;
fcn meanT(t1,t2,etc){
   ts:=vm.arglist.apply(fcn(hms){
     (D.toFloat(hms.split(":").xplode())*15).toRad()
   });
   n:=ts.len(); 
   mt:=(ts.apply("sin").sum(0.0)/n)
       .atan2(ts.apply("cos").sum(0.0)/n)
       .toDeg() /15;
   if(mt<0) mt+=24;  //-0.204622-->23.7954
   D.toHour(mt).concat(":")
}

Time.Date.toFloat/toHour convert 24hr HMS to fractional time and back. Multiplying fractional time by 360/24=15 yields angle.

Output:
meanT("23:00:17", "23:40:20", "00:12:45", "00:17:19")
23:47:43