Skip to content

Instantly share code, notes, and snippets.

@carsonfarmer
Last active October 18, 2017 00:10
Show Gist options
  • Save carsonfarmer/785a2591c2ae75191af3de8db79e5618 to your computer and use it in GitHub Desktop.
Save carsonfarmer/785a2591c2ae75191af3de8db79e5618 to your computer and use it in GitHub Desktop.
Swift version of Averages/Mean time of day (https://rosettacode.org/wiki/Averages/Mean_time_of_day)
func circularMean() {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss zzz"
let times = [Date](arrayLiteral: formatter.date(from: "2017/10/17 23:00:17 UTC")!, formatter.date(from: "2017/10/17 23:40:20 UTC")!, formatter.date(from: "2017/10/17 00:12:45 UTC")!, formatter.date(from: "2017/10/17 00:17:19 UTC")!)
// 1 second of time = 360/(24 * 3600) = 1/240th degree
let angles = times.map { secondOfDay(fromDate: $0) / 240 }
print(degreeToTime(degree: meanAngle(angles: angles), forDate: Date())!)
}
func meanAngle(angles: [Double]) -> Double {
let sinSum = angles.reduce(0) { sin($1 * Double.pi / 180) + $0 }
let cosSum = angles.reduce(0) { cos($1 * Double.pi / 180) + $0 }
return atan2(sinSum / Double(angles.count), cosSum / Double(angles.count)) * 180 / Double.pi
}
func degreeToTime(degree: Double, forDate date: Date) -> Date? {
var dd = degree
if dd < 0.0 {
dd += 360.0
}
var seconds = Int(dd * 240.0)
let hours = seconds / 3600
var minutes = seconds % 3600
seconds = minutes % 60
minutes /= 60
let calendar = Calendar.current
// Specify date components
var dateComponents = DateComponents()
dateComponents.year = calendar.component(.year, from: date)
dateComponents.month = calendar.component(.month, from: date)
dateComponents.day = calendar.component(.day, from: date)
dateComponents.timeZone = TimeZone(abbreviation: "UTC")
dateComponents.hour = hours
dateComponents.minute = minutes
dateComponents.second = seconds
return calendar.date(from: dateComponents)
}
func secondOfDay(fromDate date: Date) -> Double {
var calendar = Calendar(identifier: .iso8601)
calendar.timeZone = TimeZone(abbreviation: "UTC")
let startOfDay = calendar.startOfDay(for: date)
return date.timeIntervalSince(startOfDay)
}
circularMean()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment