I am not sure what I am doing wrong, I need to find difference between two dates and extract seconds from it, below is my code. I am not getting correct seconds. There is difference of seconds.
public func captureStartTime() {
captureStartDateTime = Date()
}
public func captureEndTime(eventType: String, eventElement: String) {
let difference = Date().timeIntervalSince(captureStartDateTime)
let interval = Int(difference)
let seconds = interval % 60
let secondsDescrp = String(format: "%02d", seconds)
}
interval is the answer you want. That is the total number of seconds between the two dates.
Your seconds value would only be useful if you wanted to calculate the number of hours, minutes, and seconds or the number of minutes and seconds from the total number of seconds.
Use the following code to get the difference between two dates, Store current time in startTime when pressed button 1 and store current date time in endTime when pressed button 2, See this code, I hope this helps you.
var startTime:Date!
var endTime:Date!
#IBAction func buttonStartTime(_ sender: UIButton) {
startTime = Date()
}
#IBAction func buttonEndTime(_ sender: UIButton) {
endTime = Date()
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.second]
formatter.unitsStyle = .full
let difference = formatter.string(from: startTime, to: endTime)!
print(difference)//output "8 seconds"
}
Output
8 seconds
you can also use default date components and according to that compare your dates and you can get the difference in year, month, day etc
let dateString1 = "2019-03-07T14:20:20.000Z"
let dateString2 = "2019-03-07T14:20:40.000Z"
//set date formate
let Dateformatter = DateFormatter()
Dateformatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
//convert string to date
let dateold = Dateformatter.date(from: dateString1)!
let datenew = Dateformatter.date(from: dateString2)!
//use default datecomponents with two dates
let calendar1 = Calendar.current
let components = calendar1.dateComponents([.year,.month,.day,.hour,.minute,.second], from: dateold, to: datenew)
let seconds = components.second
print("Seconds: \(seconds)")
Related
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
How to get accuracy completion days count from given input date
func floatDifferenceDays() -> Double {
let current = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let inputDate : String = "2018-07-15 05:46:12"
let input = dateFormatter.date(from: inputDate)
var result = current.timeIntervalSince(input!)
result = result / 86400
return result
}
Its zero. since the cycle of days datecomonents.day till 31 and increments to Month followed by year.
How can get the days that cycle have taken place which not include year,months.
if given inputdate 12 hours back from current date its should return 0.5 days completed
I would suggest you use Calendar and DateComponents to get the correct elapsed time between two dates. This will cater for leap years and daylight savings time changes.
E.g.
let current = Date()
let dateFormatter = DateFormatter()
let calendar = Calendar.autoupdatingCurrent
let timezone = TimeZone.autoupdatingCurrent
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let inputDate = "2018-07-15 05:46:12"
if let input = dateFormatter.date(from: inputDate) {
let components = calendar.dateComponents([.day,.hour], from: input, to: current)
let days = Float(components.day ?? 0)
let hours = Float(components.hour ?? 0)
let elapsed = days + hours/24.0
print("elapsed time is \(elapsed) days")
}
elapsed time is 366.25 days
Note that this code assumes that the input string is in the "local" timezone; If it isn't you would need to make appropriate changes.
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.
I get my date from server not device date.but there is problem with changing date
override func viewDidAppear(_ animated: Bool) {
datepicker2.datePickerMode = .date
datepicker2.timeZone = TimeZone(identifier: "IRST")
datepicker2.calendar = Calendar(identifier: .persian)
datepicker2.locale = Locale(identifier: "fa_IR")
datepicker2.date=self.minDate // this is a date var filled
datepicker2.addTarget(self, action: #selector(datepickerAction(_:)), for: .valueChanged)
}
each time I change the date prints just one date
func datepickerAction(_ sender: UIDatePicker){
let date = self.datepicker2.date
let components = Calendar.current.dateComponents([.month, .day,.year], from: date)
let hour = components.month
let minute = components.day
let yr=components.year
print(hour,minute,yr) // prints one date always
}
this is the date I get from server :
func CurrentdateAndTime(){
let url=URL(string: "\(address)date/getNewDate")
var urlrequest=URLRequest(url: url!)
print(url)
var time:String=""
urlrequest.httpMethod = "GET"
URLSession.shared.dataTask(with: urlrequest) { (data, response, error) in
if let data=data {
let json=String(data: data, encoding: String.Encoding.utf8)
let b:Double=Double(json!)!
// if !b.isZero{
self.setComperehensiveDate(longDate: b)
self.settime(longTime: b)
self.setDay(day: b)
self.setYear(year: b)
self.setmonth(month: b)
self.setHour(longTime: b)
self.setMin(longTime: b)
self.onComplete?("ok?")
}
}.resume()
}
func setComperehensiveDate(longDate:Double){
let dbl = TimeInterval(longDate)
let date = Date(timeIntervalSince1970: dbl / 1000)
//let formatter = DateFormatter()
print("long",longDate,dbl)
// formatter.calendar = Calendar(identifier: .persian)
// formatter.locale = Locale(identifier: "fa_IR")
// formatter.timeZone = TimeZone(identifier: "IRST")
//formatter.dateFormat = "yyyy-MM-dd HH:MM:ss"
//let a = formatter.string(from: date)
// resultDate = formatter.date(from: a)
resultDate = date
print("aaa",resultDate)
}
I get millisecond from server set on func that converts to date then I get it
and I get minDate data this way :
self.minDate=getcomperehensiveDate()
update : my problem is if user takes his device date to the past manually or future the picker shows the the past which I don't want this. I must show the current date thats why I'm setting date programatclly and facing this issue so what is your idea about this scenario ?
I can see issue with your line
let date = self.datepicker2.date
it must be getting the same date or something. I can see you are giving the same date
datepicker2.date=self.minDate (this is issue)
I just tried using
#IBAction func change(_ sender: Any) {
let components = Calendar.current.dateComponents([.month, .day,.year], from: datepicker.date)
let hour = components.month
let minute = components.day
let yr=components.year
print(hour,minute,yr)
}
it's same picker working fine.
please download the project from the link:
https://github.com/sanojKashyap/51799141_S
datepickerAction is called after changing the value of datepicker2 on a real device or the simulator.
The following should work normally:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
datepicker2.datePickerMode = .date
datepicker2.timeZone = TimeZone(identifier: "IRST")
datepicker2.calendar = Calendar(identifier: .persian)
datepicker2.locale = Locale(identifier: "fa_IR")
// The following line is setting the datepicker2.date to Tomorrow, because you haven't posted the code giving self.minDate
datepicker.date = Date().addingTimeInterval(24 * 3600)
}
func datepickerAction(_ sender: UIDatePicker) {
let date = self.datepicker2.date
let components = Calendar.current.dateComponents([.month, .day,.year], from: date)
let month = components.month //This is the month component, not the hour like in your code
let day = components.day //This is the day component, not the hour like in your code
let yr = components.year
print(day!,month!,yr!)
}
If you want the hour and minute components you'll just have to define components like so:
let components = Calendar.current.dateComponents([.minute, .hour, .month, .day,.year], from: date)
let hour = components.hour
let minutes = components.minute
Your problem is because you set the UIDatePicker date in viewDidAppear. viewDidAppear and viewWillApear are not reliable enough to be used to call one time setters, use viewDidLoad as this is guaranteed to only be called once.
I learned this the hard way and after putting a breakpoint in the problematic date setter I traced it back to the fact it was set in the viewDidLayoutSubviews override. Another no-no apparently which led me to your question.
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)