CloudFlare suffered a massive security issue affecting all of its customers, including Rosetta Code. All passwords not changed since February 19th 2017 have been expired, and session cookie longevity will be reduced until late March.--Michael Mol (talk) 05:15, 25 February 2017 (UTC)

Averages/Mean time of day

From Rosetta Code
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[edit]

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

AutoHotkey[edit]

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[edit]

#!/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[edit]

      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[edit]

/*29th August, 2012
Abhishek Ghosh*/

 
#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#[edit]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace RosettaCode
{
class Program
{
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++)
{
x_part += Math.Cos(angles[i] * Math.PI / 180);
y_part += Math.Sin(angles[i] * Math.PI / 180);
}
 
return Math.Atan2(y_part / numItems, x_part / numItems) * 180 / Math.PI;
};
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;
 
Console.WriteLine("Enter times, end with no input: ");
do
{
input = Console.ReadLine();
if (!(string.IsNullOrWhiteSpace(input)))
{
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)));
}
}
}
 
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

D[edit]

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


EchoLisp[edit]

 
;; 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[edit]

 
-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[edit]

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#[edit]

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

Fortran[edit]

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[edit]

' 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[edit]

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[edit]

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[edit]

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[edit]

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[edit]

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

jq[edit]

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

Kotlin[edit]

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[edit]

 
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 

Mathematica / Wolfram Language[edit]

meanTime[list_] := 
StringJoin@
Riffle[ToString /@
Floor@{Mod[24 #, 24], Mod[24*60 #, 60], Mod[24*60*60 #, 60]} &[
Arg[Mean[
Exp[FromDigits[[email protected][#, ":"], 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[edit]

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[edit]

import math, complex, strutils
 
proc rect(r, phi): Complex = (r * cos(phi), sin(phi))
proc phase(c): float = arctan2(c.im, c.re)
 
proc radians(x): float = (x * Pi) / 180.0
proc degrees(x): float = (x * 180.0) / Pi
 
proc meanAngle(deg): float =
var c: Complex
for d in deg:
c += rect(1.0, radians(d))
degrees(phase(c / float(deg.len)))
 
proc meanTime(times): 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[edit]

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[edit]

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[edit]

/* 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[edit]

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 6[edit]

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

Phix[edit]

function atan2(atom y, atom x)
return 2*arctan((sqrt(power(x,2)+power(y,2))-x)/y)
end function
 
function MeanAngle(sequence angles)
atom x=0, y=0, ai_rad
integer l=length(angles)
 
for i=1 to l do
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
s = sprintf("%02d:%02d:%02d",{floor(s/3600),floor(remainder(s,3600)/60),remainder(s,60)})
end if
return s
end function
 
printf(1,"Mean Time is %s\n",{toHMS(MeanAngle(Times))})
{} = wait_key()
Output:
Mean Time is 23:47:43

PHP[edit]

 
<?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[edit]

(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[edit]

*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[edit]

 
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[edit]

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[edit]

 
#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"


REXX[edit]

/* 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

Ruby[edit]

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[edit]

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

Scala[edit]

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]")
}

Sidef[edit]

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

Tcl[edit]

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

XPL0[edit]

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

zkl[edit]

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