Search code examples
swiftdatensdateformatter

In swift, failing converting date format, but cannot use ISO8601DateFormatter


I fail getting 'start' value, tested many variants and formatters. For production reasons cannot use ISO8601DateFormatter.

this code is part of creating appointment on the calendar, so I need start as start date/hour of the appointment.

Above all, I need to understand why this last line of code fails after I tried to convert date:

event.startDate is my 'start' but cannot set it since fails converting date

   guard let url = URL(string: "calshow:\(event.startDate.timeIntervalSinceReferenceDate)") else { return }
            DispatchQueue.main.async {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
      

my code:

date0

is a Date I get from API, with value 2021-07-28 00:00:00 +0000

my updated code for creating event on calendar

let dateFormatter: DateFormatter = DateFormatter()

            dateFormatter.dateFormat = "dd-MM-yyyy HH:mm:ss"
            let date = dateFormatter.string(from: date0)
            
            
            if let startTime = hours.from,
               let startDate = date.concats(startTime),
               let start = self.shortTimeFormatter.date(from: startDate) {
                event.startDate = start
                event.addAlarm(EKAlarm(absoluteDate: start.dayBefore))
                event.addAlarm(EKAlarm(absoluteDate: start.halfHourBefore))
                event.endDate = start.hourAfter
            }
            
            if let endTime = hours.to,
               let endDate = date.concats(endTime),
               let end = self.shortTimeFormatter.date(from: endDate) {
                event.endDate = end
            }

concats code

  func concats(_ string: String, withSeparator separator: String? = "") -> String? {
        return [self, string].compactMap{ $0 }.joined(separator: separator! + " ")
    }

ShortDateTimeFormatter

public class ShortDateTimeFormatter: DateFormatter {
    
    override public init() {
        super.init()
        self.dateFormat = "dd/MM/yyyy HH:mm"
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

Solution

  • If I understand the code you get a Date without the time portion and you want to add the time in string format "HH:mm:ss".

    Calendar can do that. You don't need to convert the Date to String and back to Date.

    First create a function which converts the time string to Int components

    func timeComponents(from string: String) -> (Int, Int, Int)? {
        let comps = string.components(separatedBy: ":")
        guard comps.count == 3,
              let hr = Int(comps[0]),
              let mn = Int(comps[1]),
              let sc = Int(comps[2])
              else { return nil }
        return (hr, mn, sc)
    }
    

    Then add the time to date0 with date(bySettingHour:minute:second:of:)

    if let (hr, mn, sc) = timeComponents(from: "08:30:00") {
        let startDate = Calendar.current.date(bySettingHour: hr, minute: mn, second: sc, of: date0)
    }
    

    Or with DateComponents

    func timeComponents(from string: String) -> DateComponents? {
        let comps = string.components(separatedBy: ":")
        guard comps.count == 3,
              let hr = Int(comps[0]),
              let mn = Int(comps[1]),
              let sc = Int(comps[2])
              else { return nil }
        return DateComponents(hour: hr, minute: mn, second: sc)
    }
    
    if let components = timeComponents(from: "08:30:00") {
        let startDate = Calendar.current.date(byAdding: components, to: date0, wrappingComponents: false)
    }