Search code examples
swiftnsdateformatteruidatepicker

Calculate Value of dates selected from two UIDatePickers Swift 4


I have two UIDatePickers and a label. I want to calculate the difference between the starting date and ending date selections of the two date pickers and have the difference displayed on the label. Here is my current code:

@IBOutlet weak var YTDDateRange: UILabel!

@IBOutlet weak var startingDateMonthInput: UITextField!

@IBOutlet weak var endingDateMonthInput: UITextField!

private var datePickerStart: UIDatePicker?

private var datePickerEnd: UIDatePicker?

override func viewDidLoad() {
    super.viewDidLoad()

    datePickerStart = UIDatePicker()

    datePickerEnd = UIDatePicker()

    datePickerStart?.datePickerMode = .date

    datePickerEnd?.datePickerMode = .date

    datePickerStart?.addTarget(self, action: #selector(YTDChartViewControllerBase.dateChangedStart(datePicker:)), for: .valueChanged)

    datePickerEnd?.addTarget(self, action: #selector(YTDChartViewControllerBase.dateChangedEnd(datePicker:)), for: .valueChanged)

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(YTDChartViewControllerBase.viewTapped(gestureRecognizer:)))

    view.addGestureRecognizer(tapGesture)

    startingDateMonthInput.inputView = datePickerStart

    endingDateMonthInput.inputView = datePickerEnd

    let dateformatter = DateFormatter()
    dateformatter.dateFormat = "MM/yyyy"

    dateformatter.dateStyle = DateFormatter.Style.long
    dateformatter.timeStyle = DateFormatter.Style.none

    var calendar = Calendar(identifier: .gregorian)
    calendar.timeZone = TimeZone(identifier: "PST")!
    var startDateComponents: DateComponents = DateComponents()
    startDateComponents.year = 1928
    startDateComponents.month = 1
    let defaultDate: Date = calendar.date(from: startDateComponents as DateComponents)!

    self.datePickerEnd!.date = Date()

    self.datePickerStart!.date = defaultDate as Date
    startingDateMonthInput.text = dateformatter.string(from: datePickerStart!.date)
    endingDateMonthInput.text = dateformatter.string(from: datePickerEnd!.date)
}

@objc func viewTapped(gestureRecognizer: UITapGestureRecognizer) {

    view.endEditing(true)

}

@objc func dateChangedStart(datePicker: UIDatePicker) {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM/yyyy"
    dateFormatter.dateStyle = DateFormatter.Style.long
    startingDateMonthInput.text = dateFormatter.string(from: datePicker.date)
    view.endEditing(true)

}

@objc func dateChangedEnd(datePicker: UIDatePicker) {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM/yyyy"
    dateFormatter.dateStyle = DateFormatter.Style.long
    endingDateMonthInput.text = dateFormatter.string(from: datePicker.date)
    view.endEditing(true)

}

This is what I have tried to find the difference between the two datepickers.

func YTDMarketClose(from datePickerStart: Date, to datePickerEnd: Date) -> Date {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM/yyyy"
    dateFormatter.dateStyle = DateFormatter.Style.long
    let YTDBegin = datePickerEnd.timeIntervalSince(datePickerStart)
    let today = Date()
    if YTDBegin < 0 {
        return today
    } else {
        return today.addingTimeInterval(YTDBegin)
        print(YTDBegin)
    }
}

But when I try to set it to the text label I get the error "Cannot assign type value of 'Date' to type 'String?'.

 YTDDateRange.text = YTDMarketClose(from: datePickerStart!.date, to: datePickerEnd!.date)

Am I doing this correct or am I missing something. Any help is much appreciated.


Solution

  • The difference between two dates is not another date, it's a time interval. Your YTDBegin variable is of type TimerInterval. This is a number of seconds. Don't attempt to convert that back into a date. Convert it into a string in some desired format.

    Your YTDMarketClose method needs to return String, not Date. Then you can assign the result to the label.

    You should use DateComponentsFormatter to get a string from the difference between the two dates.

    func ytdMarketClose(from datePickerStart: Date, to datePickerEnd: Date) -> String {
        let formatter = DateComponentsFormatter()
        // configure the formatter to suit your needs
        let result = formatter.string(from: datePickerStart, to: datePickerEnd)
    
        return result ?? "Unknown"
    }
    

    As a side note, it is standard that class, struct, and enum names start with uppercase letters. Variable, method, and case names start with lowercase letters.