Averages/Mean time of day

From Rosetta Code
Revision as of 07:27, 15 October 2018 by Chunes (talk | contribs) (Add Factor example)
Task
Averages/Mean time of day
You are encouraged to solve this task according to the task description, using any language you may know.

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

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

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

}</lang>

Output:
The mean time is: 23:47:43

AWK

<lang 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);

}</lang>

$ 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

<lang bbcbasic> 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</lang>
Output:
Mean time is 23:47:43

C

  1. include<stdlib.h>
  2. include<math.h>
  3. 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;

}</lang>

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#

<lang csharp>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)));
       }
   }

} </lang>

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

Translation of: Python

<lang d>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;

}</lang>

Output:
23:47:43


EchoLisp

<lang scheme>

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"

</lang>

Erlang

<lang 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]) ). </lang>

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

<lang Euphoria> 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 </lang>

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#

<lang fsharp>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</lang>
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

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

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

<lang fortran> 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 </lang>

Output:
23:47:43

FreeBASIC

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

Output:
Average time is : 23:47:43

Go

<lang 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

}</lang>

Output:
23:47:43

Groovy

Solution: <lang groovy>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)

}</lang>

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

Output:
23:47:43

Haskell

<lang 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"] </lang>

Output:
23:47:43

Icon and Unicon

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

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

Example Use:

<lang J> meanTime '23:00:17 23:40:20 00:12:45 00:17:19 ' 23:47:43</lang>

Java

Translation of: Kotlin

<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));
   }

}</lang>

Output:
Average time is : 23:47:43

JavaScript

Works with: Node.js

<lang Javascript>var args = process.argv.slice(2);

function time_to_seconds( hms ) {

   var parts = hms.split(':');
   if ( parts[0] < 12 ) {
       parts[0] = 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)); </lang>

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. <lang jq># 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 ;</lang>

Examples <lang jq>["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</lang>

Output:

<lang sh>$ 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</lang>

Julia

Works with: Julia version 0.6
Translation of: MATLAB

<lang julia>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")</lang>

Output:
Times:
23:00:17
23:40:20
00:12:45
00:17:19
Mean: 23:47:43

Kotlin

Translation of: FreeBASIC

<lang scala>// 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)}")

}</lang>

Output:
Average time is : 23:47:43

Liberty BASIC

<lang lb> 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 </lang>

Output:
Average of:
23:00:17
23:40:20
00:12:45
00:17:19
is 23:47:43 


Lua

<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))) </lang>

Output:
23:47:43 

Mathematica / Wolfram Language

<lang mathematica>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"}]</lang>

Output:
23:47:43

MATLAB / Octave

<lang MATLAB>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; </lang>

mean_time_of_day({'23:00:17', '23:40:20', '00:12:45', '00:17:19'})
ans = 23:47:43

Nim

<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 =

 var c: Complex
 for d in deg:
   c += rect(1.0, radians(d))
 degrees(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"])</lang>

Output:
23:47:43

Oberon-2

Works with: oo2c

<lang oberon2> 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. </lang>

Output:
:> 23:47:43

OCaml

<lang 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)))</lang>
Output:
The mean time of [23:00:17; 23:40:20; 00:12:45; 00:17:19] is: 23:47:43

ooRexx

<lang 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</lang>
Output:
23:47:43

PARI/GP

<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([[23,0,17], [23,40,20], [0,12,45], [0,17,19]])</lang>

Output:
[23, 47, 43]

Perl

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: Perl 6

<lang Perl>use POSIX 'fmod'; use Math::Complex; use List::Util qw(sum); use utf8;

use constant τ => 2 * 3.1415926535;

  1. time-of-day to radians

sub tod2rad {

   ($h,$m,$s) = split /:/, @_[0];
   (3600*$h + 60*$m + $s) * τ / 86400;

}

  1. 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);

}

  1. 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";</lang>

Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19

Perl 6

Works with: Rakudo version 2015.12

<lang perl6>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[]";</lang>

Output:
23:47:43 is the mean time of 23:00:17 23:40:20 00:12:45 00:17:19

Phix

<lang Phix>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()</lang>

Output:
Mean Time is 23:47:43

PHP

<lang 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"; ?> </lang>

Output:
The mean time of day is 23:47:43 (angle 356.9306730355).

PicoLisp

<lang 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) ) )</lang>
Test:

<lang PicoLisp>: (meanTime '("23:00:17" "23:40:20" "00:12:45" "00:17:19")) -> "23:47:43"</lang>

PL/I

<lang pli>*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;</lang>
Output:
23:47:43

PowerShell

<lang 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)
   }

} </lang> <lang PowerShell> [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") </lang>

Output:
Mean time is 11:47:43 PM

Python

<lang 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"]) )</lang>
Output:
23:47:43

Racket

<lang racket>

  1. 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")) </lang>

Output:
"23:47:43"


REXX

<lang 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</lang>
Output:
23:47:43

Ruby

Using the methods at [angle]

<lang ruby>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"]</lang>

Output:
23:47:43

Run BASIC

<lang runbasic>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</lang>

Scala

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

}</lang>

Scheme

Library: Scheme/SRFIs

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

<lang scheme> (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) </lang>

Output:
"23:47:43"

Sidef

Translation of: Ruby

Using the mean_angle() function from: "Averages/Mean angle" <lang ruby>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"])</lang>

Output:
23:47:43

SQL/PostgreSQL

Translation of: Python

<lang SQL> --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</lang>

Output:

23:47:43.361529

Tcl

<lang 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}]</lang>

Output:
23:47:43

XPL0

<lang 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]]))</lang>

Output:
23:47:43

Yabasic

Translation of: Phix

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

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. <lang zkl>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(":")

}</lang> 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