TimeDifference between minimum date and maximum date - swift

i am completely new in iPhone app development. i am trying to find difference between min_date and max_date in hours. and wants save its value in textfield. Kindly Provide me complete code to find out difference between both of dates. e.g. if min_date: 12/07/1989, 12:00 am and max_date: 13/07/1989,12:00 am , then total hours will be 24 hours. Please provide me code in swift 3.0.

First, use timeIntervalSince to get the difference in seconds:
let timeInterval = max_date.timeIntervalSince(min_date)
Then you can do some maths to calculate the number of hours
let hours = timeInterval / 60 / 60
You can choose to floor or ceiling this number, depending on your requirements.

let previousDate = ...
let now = Date()
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.month, .day, .hour, .minute, .second]
formatter.maximumUnitCount = 2 // often, you don't care about seconds
if the elapsed time is in months, so you'll set max unit to whatever is
appropriate in your case
let string = formatter.string(from: previousDate, to: now)

let minDate = Date() // your min date
let maxDate = Date() // your max date
let components = Calendar.current.dateComponents([.hour], from: minDate, to: maxDate)
It's the most flexible method for search difference between two dates. You can use other components to search for months, days, years etc.

Related

Convert hours form 12 hour time to 24 hour time Swift and save as an integer

I want to convert my variable for hours which is an integer into a 24 hour time system (for example, if it is 01:05:13 PM, hours will be saved as 13, minutes will be saved as 5, and seconds will be saved as 13) so that I can use it for some math later in my code to fid some differences on a scheduling app I am working on. This is my first app and I couldn't find an answer to this anywhere else so thanks for your help! Another way this code could work is getting the amount in seconds since the day has begun, if anyone knows how to do that, it would be greatly appreciated!
This is my function for getting the time and saving it as three different integers for hours, seconds, and minutes:
#IBAction func setTime() {
var date = NSDate()
//pickTimes()
var calendar = NSCalendar.current
calendar.timeZone = TimeZone(identifier: "UTC")!
var currentHour = calendar.component(.hour, from: date as Date) + 5
let currentMinutes = calendar.component(.minute, from: date as Date)
let currentSeconds = calendar.component(.second, from: date as Date)
timeText.text = ("\(currentHour):\(currentMinutes):\(currentSeconds)")
}
calendar.component(.hour, from: someDate) already gives you the time of day in 24 hour time so there's nothing else to do to solve your question.
Not sure why you are adding 5 to the hour. You set the timezone to UTC so the date will be treated as the UTC timezone. Then you add 5 to that result. That's kind of strange. If you just want the current hour in the user's locale timezone, don't change the calendar's timezone and don't add 5 to the hour.
Don't use NSDate or NSCalendar. This is Swift. Use Date and Calendar.
Updated code:
#IBAction func setTime() {
var date = Date()
//pickTimes()
var calendar = Calendar.current
var currentHour = calendar.component(.hour, from: date)
let currentMinutes = calendar.component(.minute, from: date)
let currentSeconds = calendar.component(.second, from: date)
timeText.text = ("\(currentHour):\(currentMinutes):\(currentSeconds)")
}
But it would be simpler to use a DateFormatter and set the timeStyle to .medium or maybe .long and format Date() into a string. This will give a properly localized time string.

Test whether current time of day is between two TimeIntervals

I have 2 TimeIntervals, which just represent date-agnostic times of day (e.g. 8:00 AM and 5:00 PM). So 0 represents exactly midnight, in this case, and 29,040 represents 8:04 AM. I want to check if the phone's time of day is between the two TimeIntervals.
I found a few similar Stack Overflow questions, but none of them really dealt with TimeIntervals. It seems like just using start <= Date().timeIntervalSinceReferenceDate <= end or something wouldn't work, because it would return a huge value.
What's the best way to handle this type of situation in Swift 3?
Edit: To clarify, I don't need to worry about things like daylight savings. As an example, assume that the user only wants certain things in the app to happen between the hours of X and Y, where X and Y are given to me as TimeInterval values since midnight. So it should be sufficient to check if the phone's TimeInterval since midnight on a typical day is between X and Y before completing the action.
Date().timeIntervalSinceReferenceDate returns the number of seconds since Jan 1, 2000 so no doubt it's a huge number.
It's inadvisable to store time as seconds since midnight due to this naggy little thing called Daylight Saving Time. Every year, different countries do it on different days and on different hours. For example, even though Britain and France change their clock on the same day (March 26, 2017), one makes the shift from 1AM to 2AM, the other goes from 2AM to 3AM. That's very easy to make for a mess!
Use DateComponents instead:
let calendar = Calendar.current
let startTimeComponent = DateComponents(calendar: calendar, hour: 8)
let endTimeComponent = DateComponents(calendar: calendar, hour: 17, minute: 30)
let now = Date()
let startOfToday = calendar.startOfDay(for: now)
let startTime = calendar.date(byAdding: startTimeComponent, to: startOfToday)!
let endTime = calendar.date(byAdding: endTimeComponent, to: startOfToday)!
if startTime <= now && now <= endTime {
print("between 8 AM and 5:30 PM")
} else {
print("not between 8 AM and 5:30 PM")
}
I ended up using DateComponents to calculate a TimeInterval.
let components = Calendar.current.dateComponents(
[.hour, .minute, .second], from: Date())
guard let seconds = components.second,
let minutes = components.minute,
let hours = components.hour else
{
return false
}
let currentTime = Double(seconds + minutes * 60 + hours * 60 * 60)
return startTime <= currentTime && currentTime <= endTime

Get percentage between two dates as a float in Swift

So I'm currently trying to add a feature that given two dates, will tell me how far through I am.
TLDR:
So, let's say I have a date that is July 1st, 2017 20:00:00 and another that is July 2nd, 2017 22:00:00 and today is July 2nd, 08:00:00, then I will get that I am 46.17% of the way through.
The way I tried to do this is using a simple formula:
progress = (current time - start time) / (end time - start time)
but when put into code, I can subtract two dates, and get the DateComponent difference, but I cannot divide two DateComponent's. Here is my code set up, with an extension t
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startDate = formatter.date(from: "2017-07-01 20:00:00")
let endDate = formatter.date(from: "2017-07-02 22:00:00")
let currentDate = formatter.date(from: "2017-07-01 08:00:00")
let progress = (currentDate - startDate) / (endDate - startDate)
extension Date {
static func - (date1: Date, date2: Date) -> DateComponents {
let calender:Calendar = Calendar.current
return calender.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date1, to: date2)
}
}
There has to be a way around dividing two dates. I can't think of it though, everything I find online (using different languages) has required division between two dates.
I tried to convert everything to seconds and just divide that, but I didn't know what to do with the seconds to convert them back to a DateComponent because there might be a 5000 second difference. Any help appreciated!
You just need to turn the dates into numbers, because then you can add and subtract them.
You can use the timeIntervalSince1970 to turn the date into numbers, then you can use your formula:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startDate = formatter.date(from: "2017-07-01 20:00:00")!.timeIntervalSince1970
let endDate = formatter.date(from: "2017-07-02 22:00:00")!.timeIntervalSince1970
let currentDate = formatter.date(from: "2017-07-02 08:00:00")!.timeIntervalSince1970
let percentage = (currentDate - startDate) / (endDate - startDate)
Alternatively, use timeIntervalSince(_:):
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startDate = formatter.date(from: "2017-07-01 20:00:00")!
let duration = formatter.date(from: "2017-07-02 22:00:00")!.timeIntervalSince(startDate)
let elapsed = formatter.date(from: "2017-07-02 08:00:00")!.timeIntervalSince(startDate)
let percentage = elapsed / duration
I think this way is better because you get less maths :).
What you are looking for is Date().timeIntervalSinceReferenceDate:
let currentInterval = currentDate.timeIntervalSinceReferenceDate
let startInterval = startDate.timeIntervalSinceReferenceDate
let endInterval = endDate.timeIntervalSinceReferenceDate
let progress = ((currentInterval - startInterval) / (endInterval - startInterval)) * 100
Here is apples documentation on it. Basically it returns the amount of seconds that have passed since the reference date of January 1, 2001 UTC.
Do the exact same calculation, just convert startdate, enddate, and currentdate into milliseconds using yourDate.timeIntervalSince1970
That should give you a decimal between 0 and 1, and just multiply by 100 for the percentage

Difference between two dateTimes in seconds vary due to different time zones - Swift 3

I need to find difference between current time (in seconds) and future start time (fetched from my web service in seconds).
I have coded the following :
let currentTime = Int64(Date().timeIntervalSince1970)
var time = Int64(timeArr[indexPath.row])
print("\(currentTime) vs \(time)")
time = time - currentTime
print("difference in time : \(time)")
let seconds = time % 60
let minutes = (time / 60) % 60
let hours = (time / 3600)
My console shows me this output:
1480400929 vs 1480552620
difference in time : 151691
The problem is that my current time is Tue Nov 29 2016 11:58:49 and the start time is 2016-11-30 17:37:00 so the difference in hours should come to around 30 hours whereas it takes the times in different time zones due to which it comes to around 42 hours. How do I fix this? I have gone through many questions for the same but nothing works. Any help would be appreciated.
If you want the difference between two date in Hours, Minutes and seconds you can use DateComponent like this.
let component = Calendar.current.dateComponents([.hour, .minute, .second], from: Date(), to: startDate)
let hours = component.hour ?? 0
let minutes = component.minute ?? 0
let seconds = component.second ?? 0
Edit: To get date from miliseconds use Date(timeIntervalSince1970:) like this.
let startDate = Date(timeIntervalSince1970: miliSeconds / 1000)
Also you can convert string to Date using DateFormatter like this.
let stringDate = "2016-11-30 17:37:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
if let startDate = dateFormatter.date(from: stringDate) {
print(startDate)
}

Find minutes remaining between two times

I have two times in the format HH:MM how would I compare the second from the first one finding how many minutes left until I reach to the first time:
example:
timeOne = 12:01
timeTwo = 11:32
output = 29 minutes
Any help writing this in Swift?
NSCalendar can diff dates easily (assuming start and end are NSDate instances
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.Minute, fromDate: start, toDate: end, options: [])
components.minute
If you are interested in getting just the formatted string, and not the actual value, then checkout NSDateComponentsFormatter:
let formatter = NSDateComponentsFormatter()
formatter.allowedUnits = .Minute
formatter.unitsStyle = .SpellOut
// includesTimeRemainingPhrase gives strings like "T minutes remaining"
formatter.stringFromDate(start, toDate: end)
By changing the unitsStyle, you could get different representations, such as:
"54m"
"54 minutes"
"54 min"
"fifty-four minutes"
You should operate with 2 NSDate instances, then you may use next API:
let interval = laterDate.timeIntervalSinceDate(earlierDate)
It returns the number of seconds, as an NSTimeInterval value.
Divide it by 60 will give you minutes.