I have to compare the time duration of the recorded audio file against a fixed time duration value of 10 mins (10:00). The duration of the audio file is a string.
Doing string comparison works fine if the format of recorded files duration and the format of the fixed duration is same i.e mm:ss. If the audio file has duration of format hh:mm:ss , it gives false values in certain cases.
Is there any way to handle this?
You can use this String Extension to calculate total minutes from string
extension String {
func getTimeInSeconds()-> Int? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mm:ss" //Your date format
dateFormatter.timeZone = TimeZone.current //Current time zone
var date = Date()
if let getDate = dateFormatter.date(from: self) {//according to date format your date string
date = getDate //Convert String to Date
} else {
dateFormatter.dateFormat = "hh:mm:ss"
if let getDate = dateFormatter.date(from: self) {//according to date format your date string
date = getDate //Convert String to Date
} else {
return nil
}
}
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute,.second], from: date)
let hour = components.hour ?? 0
let minute = components.minute ?? 0
let seconds = components.second ?? 0
return (hour * 360) + minute*60 + seconds
}
}
You can use this extension like this
let getSeconds = "01:20".getTimeInSeconds()
it will cover both formats mm:ss and hh:mm:ss and return seconds ... you can use these seconds to compare instead of string
I have a datePickerthat I use to select a starting date and time, and a durationTextLabelto add minutes to that date and time. I set the duration to be minimum 30 if no text is inserted, but the value in
resulting date and time is identical.
Can you see where I'm mistaking?
Thank you very much as usual.
Here's the function:
func setQueryParameters() {
let dateFormatter = DateFormatter()
var convertedDate: String!
dateFormatter.dateFormat = "yyyy/MM/dd/hh/mm"
convertedDate = dateFormatter.string(from: datePicker.date)
let calendar = Calendar.current
let components = (calendar as NSCalendar).components([.year, .month, .day, .weekday, .hour, .minute] , from: datePicker.date)
let year: Int = components.year!
let month: Int = components.month!
let day: Int = components.day!
let weekday: Int = components.weekday!
let hour: Int = components.hour!
let minute: Int = components.minute!
var duration: Double?
duration = Double(durationTextField.text!)
let endDate = datePicker.date.addingTimeInterval(duration!)
let endComponents = (calendar as NSCalendar).components([.hour, .minute], from: endDate)
let endHour: Int = endComponents.hour!
let endMinute: Int = endComponents.minute!
if durationTextField.text != nil {
duration = Double(durationTextField.text!) ?? 30.00
} else { return}
// Opening Time Query parameter
openingTimeQueryStart = Int("\(String(describing: weekday))"+"00"+"00")!
openingTimeQueryEnd = Int("\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))")!
print("opening query is \(openingTimeQueryEnd)")
// Closing Time Query parameter
closingTimeQueryStart = Int("\(String(describing: weekday))"+"\(String(endHour))"+"\(String(endMinute))")!
closingTimeQueryEnd = Int("\(String(describing: weekday))"+"00"+"00")!
print("closing time query is \(closingTimeQueryStart)")
// Booking Query parameter
let bookingQueryString = "\(String(describing: year))"+"\(String(describing: month))"+"\(String(describing: day))"+"\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))"+"\(String(endHour))"+"\(String(endMinute))"
bookingQuery = Int(bookingQueryString)!// ?? openingTimeQuery // found nil unwripping optional
}
There are many problems here.
You actually never make any use of dateFormatter other than creating and then never using convertedDate. So delete that unused code.
You have indicated at duration should be in minutes but you treat it as seconds. You need to multiply by 60 to convert it to minutes.
All of your code for calculating things such as openingTimeQueryEnd depend on each value being two digits but your code doesn't give the desired results.
For example, the line:
openingTimeQueryEnd = Int("\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))")!
should be rewritten as:
openingTimeQueryEnd = Int(String(format: "%02d%02d%02d", weekday, hour, minute))!
or as:
openingTimeQueryEnd = weekday * 10000 + hour * 100 + minute
Make similar changes to the other similar lines.
in my app I get a JSON response as a string -> "16:00:00"
What I want to do is to get the timeInterval in seconds from the current date until "16:00:00"
this is my code so far. PS sorry for the bad description, thanks for your help
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
if let date = dateFormatter.date(from:task.start) {
print(date.timeDifference(date: Date()))
}
func timeDifference(date: Date) -> String {
let hourMinuteSecond: Set<Calendar.Component> = [.hour, .minute, .second]
let difference = Calendar.current.dateComponents(hourMinuteSecond, from: date, to: self);
let seconds = "\(difference.second ?? 0)s"
let minutes = "\(difference.minute ?? 0)m" + " " + seconds
let hours = "\(difference.hour ?? 0)h" + " " + minutes
if let hour = difference.hour, hour > 0 { return hours }
if let minute = difference.minute, minute > 0 { return minutes }
if let second = difference.second, second > 0 { return seconds }
return ""
}
There are many ways to solve this. Here's one:
let df = DateFormatter()
df.dateFormat = "HH:mm:ss"
df.defaultDate = Date() // default to today's date
if let date = df.date(from:task.start) {
print(date.timeDifference(date: Date()))
}
func timeDifference(date: Date) -> String {
let diff = timeIntervalSince(date)
let fmt = DateComponentsFormatter()
fmt.unitsStyle = .abbreviated
let res = fmt.string(from: diff)
return res
}
This code assumes that timeDifference is an extension method of Date.
Also note that this will give a negative time difference if the time in the string is earlier than "now". If you want a positive time difference no matter if the time string is before or after "now", use the abs function:
let res = fmt.string(from: abs(diff))
func updateTime() {
var date = NSDate()
var calendar = NSCalendar.currentCalendar()
var components = calendar.components(.CalendarUnitSecond, fromDate: date)
var hour = components.hour
var minutes = components.minute
var seconds = components.second
counterLabel.text = "\(seconds)"
var myIndicator = counterLabel.text?.toInt()
if myIndicator! % 2 == 0 {
// do this
} else {
// do that
}
}
I'd like to know how I can change this code so I get 1/10 or 1/100 or 1/1000 of a second to display in counterlabel.text.
Just can't figure it out... thanks!
There is a calendar unit for nanoseconds:
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitNanosecond, fromDate: date)
let nanoSeconds = components.nanosecond
Update for Swift 3
let date = Date()
let calendar = NSCalendar.current
let components = calendar.dateComponents([.nanosecond], from: date)
let nanoSeconds = components.nanosecond
This gives the fractional part of the seconds in units of 10-9 seconds.
For milliseconds, just divide this value by 106:
let milliSeconds = nanoSeconds / 1_000_000
Alternatively, if you just want to display the fractional
seconds, use a NSDateFormatter and the SSS format. Example:
let fmt = NSDateFormatter()
fmt.dateFormat = "HH:mm:ss.SSS"
counterLabel.text = fmt.stringFromDate(date)
Update for Swift 3
let fmt = DateFormatter()
fmt.dateFormat = "HH:mm:ss.SSS"
counterLabel.text = fmt.stringFromDate(date)
I am new to Swift and am trying a scheduler. I have the start time selected and I need to add 5 minutes (or multiples of it) to the start time and display it in an UILabel?
#IBAction func timePickerClicked(sender: UIDatePicker) {
var dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
var dateStr = dateFormatter.stringFromDate(startTime.date)
let sttime = dateStr
startTimeDisplay.text = dateStr
}
// How to advance time by 5 minutes for each section based on the start time selected and display time
// section 1 = start time + 5
// section 2 = start time + 10*
Two approaches:
Use Calendar and date(byAdding:to:wrappingComponents:). E.g., in Swift 3 and later:
let calendar = Calendar.current
let date = calendar.date(byAdding: .minute, value: 5, to: startDate)
Just use + operator (see +(_:_:)) to add a TimeInterval (i.e. a certain number of seconds). E.g. to add five minutes, you can:
let date = startDate + 5 * 60
(Note, the order is specific here: The date on the left side of the + and the seconds on the right side.)
You can also use addingTimeInterval, if you’d prefer:
let date = startDate.addingTimeInterval(5 * 60)
Bottom line, +/addingTimeInterval is easiest for simple scenarios, but if you ever want to add larger units (e.g., days, months, etc.), you would likely want to use the calendrical calculations because those adjust for daylight savings, whereas addingTimeInterval doesn’t.
For Swift 2 renditions, see the previous revision of this answer.
You can use Calendar's method
func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = default) -> Date?
to add any Calendar.Component to any Date. You can create a Date extension to add x minutes to your UIDatePicker's date:
Xcode 8 and Xcode 9 • Swift 3.0 and Swift 4.0
extension Date {
func adding(minutes: Int) -> Date {
return Calendar.current.date(byAdding: .minute, value: minutes, to: self)!
}
}
Then you can just use the extension method to add minutes to the sender (UIDatePicker):
let section1 = sender.date.adding(minutes: 5)
let section2 = sender.date.adding(minutes: 10)
Playground testing:
Date().adding(minutes: 10) // "Jun 14, 2016, 5:31 PM"
Swift 4:
// add 5 minutes to date
let date = startDate.addingTimeInterval(TimeInterval(5.0 * 60.0))
// subtract 5 minutes from date
let date = startDate.addingTimeInterval(TimeInterval(-5.0 * 60.0))
Swift 5.1:
// subtract 5 minutes from date
transportationFromDate.addTimeInterval(TimeInterval(-5.0 * 60.0))
extension Date {
func withAddedMinutes(minutes: Double) -> Date {
addingTimeInterval(minutes * 60)
}
func withAddedHours(hours: Double) -> Date {
withAddedMinutes(minutes: hours * 60)
}
}
useCase
let anHourFromNow = Date().withAddedHours(hours: 1)
let aMinuteFromNow = Date().withAddedMinutes(minutes: 1)
You can use in swift 4 or 5
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd H:mm:ss"
let current_date_time = dateFormatter.string(from: date)
print("before add time-->",current_date_time)
//adding 5 miniuts
let addminutes = date.addingTimeInterval(5*60)
dateFormatter.dateFormat = "yyyy-MM-dd H:mm:ss"
let after_add_time = dateFormatter.string(from: addminutes)
print("after add time-->",after_add_time)
output:
before add time--> 2020-02-18 10:38:15
after add time--> 2020-02-18 10:43:15
You can do date arithmetic by using NSDateComponents. For example:
import Foundation
let comps = NSDateComponents()
comps.minute = 5
let cal = NSCalendar.currentCalendar()
let r = cal.dateByAddingComponents(comps, toDate: NSDate(), options: nil)
It is what you see when you try it in playground
NSDate.init with timeIntervalSinceNow:
Ex:
let dateAfterMin = NSDate.init(timeIntervalSinceNow: (minutes * 60.0))
Save this little extension:
extension Int {
var seconds: Int {
return self
}
var minutes: Int {
return self.seconds * 60
}
var hours: Int {
return self.minutes * 60
}
var days: Int {
return self.hours * 24
}
var weeks: Int {
return self.days * 7
}
var months: Int {
return self.weeks * 4
}
var years: Int {
return self.months * 12
}
}
Then use it intuitively like:
let threeDaysLater = TimeInterval(3.days)
date.addingTimeInterval(threeDaysLater)
Swift 3:
let minutes: TimeInterval = 1 * 60
let nowPlusOne = Date() + minutes
I think the simplest will be
let minutes = Date(timeIntervalSinceNow:(minutes * 60.0))
In case you want unix timestamp
let now : Date = Date()
let currentCalendar : NSCalendar = Calendar.current as NSCalendar
let nowPlusAddTime : Date = currentCalendar.date(byAdding: .second, value: accessTime, to: now, options: .matchNextTime)!
let unixTime = nowPlusAddTime.timeIntervalSince1970