-
Re: How could you improve this Swift algorithm?
Claude31 Jan 26, 2017 1:32 PM (in response to pacient)What's the purpose to improve ? Just fun of it ? Or is it cauising problem to your software ?
-
Re: How could you improve this Swift algorithm?
zach.m Jan 30, 2017 6:17 PM (in response to pacient)How about this?
enum TimeError : Error { case invalidTimeString } func convertToMilitatyTime(fromTime time: String) throws -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "hh:mm:ssaa" let date = dateFormatter.date(from: time) guard date != nil else { throw TimeError.invalidTimeString } dateFormatter.dateFormat = "HH:mm:ss" return dateFormatter.string(from: date!) }
-
Re: How could you improve this Swift algorithm?
eskimo Jan 31, 2017 3:51 AM (in response to zach.m)How about this?
That won’t work in all circumstances. Three things:
If you work with fixed-format date strings, you need to work in the
en_US_POSIX
locale. See QA1480 NSDateFormatter and Internet Dates.In situations like this, where you don’t need the actual date but rather just want a clean round trip conversion, it’s best to work in the GMT time zone. If you work in the user’s time zone you’ll run into problems if the time in question doesn’t exist in that time zone (for example, you do this calculation on a daylight savings time transition day).
When working with date format strings, it’s a good idea to quote any literal components (like the colons).
Date formatters are relatively expensive, so you should statically allocates ones that can’t change.
With these changes in place the code looks more complex:
enum TimeError : Error { case invalidTimeString } private var fromFormatter: DateFormatter = { let df = DateFormatter() df.locale = Locale(identifier: "en_US_POSIX") df.timeZone = TimeZone(secondsFromGMT: 0) df.dateFormat = "hh':'mm':'ssaa" return df }() private var toFormatter: DateFormatter = { let df = DateFormatter() df.locale = Locale(identifier: "en_US_POSIX") df.timeZone = TimeZone(secondsFromGMT: 0) df.dateFormat = "HH':'mm':'ss" return df }() func convertToMilitatyTime(fromTime time: String) throws -> String { let date = fromFormatter.date(from: time) guard date != nil else { throw TimeError.invalidTimeString } return toFormatter.string(from: date!) }
Honestly, I’m not sure if
DateFormatter
is the right way to go here. It’s a complex piece of code and it’s not clear whether the problem requirements justifies that complexity. Specifically, if the input string is very tightly constrained, you could do something hackish like this.func convertToMilitatyTime(fromTime time: String) -> String { let timeChars = Array(time.characters) let hours = String(timeChars[0..<2]) let prefix: String switch (timeChars[8], hours) { case ("A", "12"): prefix = "00" case ("P", "12"): prefix = "12" case ("A", _): prefix = hours case ("P", _): prefix = String(Int(hours)! + 12) default: fatalError() } return "\(prefix)\(String(timeChars[2..<8]))" }
Of course, this will trap if the input doesn’t exactly match the standard format.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardwarelet myEmail = "eskimo" + "1" + "@apple.com"
-
Re: How could you improve this Swift algorithm?
zach.a Feb 4, 2017 5:54 PM (in response to eskimo)Thanks, this is great information.
-
-
Re: How could you improve this Swift algorithm?
iPad_dev Feb 4, 2017 11:06 PM (in response to pacient)**** that's a lot of code for a simple function, throw this into a function, return newTime and done. regex and perl are your friends
import Foundation let AA = "07:05:45PM" let a:[String] = AA.components(separatedBy: "AM") var newTime:String = "" if a[0] != AA { newTime = a[0] } else { let b:[String] = AA.components(separatedBy: "PM") let c:[String] = b[0].components(separatedBy: ":") newTime = String("\(Int(c[0])! + 12 ):\(c[1]):\(c[2])") }