stumped stumped - 15 days ago 13
Swift Question

Getting time difference in Swift 3

I was trying to get the time difference of two dates from this guide. I'm not sure what to put in for the

dateComponents
argument. When I directly pass in
[.hour, .minute]
, I get an error:

Playground execution failed: error: MyPlayground.playground:10:46: error: type of expression is ambiguous without more context
let timeDifference = calendar.dateComponents([.hour, .minute], from: stopTime!, to: date!)
^~~~~~~~~~~~~~~~


```

I tried to declare it as a constant first but am unsure what the type is. The argument is of type
Set<Calendar.Component>
, but I'm getting an error when I try to say it's of up
Component
,
DateComponent
, or
CalendarComponent
.

````

let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "hh:mm a "
let time = "12:03 pm"
let stopTime = timeFormatter.date(from: time)

let date = Date()
let calendar = Calendar.current

let components:[DateComponent] = [.hour, .minute]
let timeDifference = calendar.dateComponents(components, from: stopTime!, to: date!)

Answer

The dateComponents(_:from:to:) method is declared as follows:

public func dateComponents(_ components: Set<Calendar.Component>, 
    from start: Date, to end: Date) -> DateComponents

The first parameter is of type Set<Calendar.Components> but you seem to provide a [DateComponents]. That's why you see the error.

Therefore, it should be done this way:

let components:[Calendar.Component] = [.hour, .minute]
let timeDifference = calendar.dateComponents(Set<Calendar.Component>(components), 
    from: stopTime!, to: date)

First, I changed the array's type to be [Calendar.Component]. Second, I created a Set<Calendar.Component> before passing components to the method. Another thing is that you wrote date!. The ! is redundant because date already is a non-optional. No need to unwrap!

Alternatively, you can remove the components variable entirely!

let timeDifference = calendar.dateComponents([.hour, .minute], 
    from: stopTime!, to: date)

Now it compiles fine!

However, this might not produce your expected result because timeFormatter.date(from: time) produces a date in the year 2000. I got this quite dirty solution, but it works anyway:

let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "hh:mm a"
let time = "08:00 pm"
var stopTime = timeFormatter.date(from: time)

let date = Date()
let calendar = Calendar.current

let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let day = calendar.component(.day, from: date)
let hour = calendar.component(.hour, from: stopTime!)
let minute = calendar.component(.minute, from: stopTime!)

stopTime = calendar.date(bySetting: .year, value: year, of: stopTime!)
stopTime = calendar.date(bySetting: .month, value: month, of: stopTime!)
stopTime = calendar.date(bySetting: .day, value: day, of: stopTime!)
stopTime = calendar.date(bySetting: .hour, value: hour, of: stopTime!)
stopTime = calendar.date(bySetting: .minute, value: minute, of: stopTime!)

let timeDifference = calendar.dateComponents([.hour, .minute], from: stopTime!, to: date)