1

I am trying to create a function which will convert date into text format like "Just now, 2mins, 1hour, 1day, oct 10". Here is my sample code where I am getting an error at:

let components = cal.components([.Day,.Hour,.Minute], fromDate: date, toDate: NSDate(), options:[])

Here is my full code:

func getTextToDisplayFormattingDate(date: NSDate) -> String {
    var textToDisplay = ""
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM-dd-yyyy hh:mm:ss a"
    dateFormatter.timeZone = TimeZone(identifier: "UTC")

    let cal = NSCalendar.current

    let components = cal.components([.Day,.Hour,.Minute], fromDate: date, toDate: NSDate(), options:[])

    switch components.day {
    case 0:
        if components.hour == 0 {
            if components.minute <= 0 {
                textToDisplay = "just now "
            } else {
                textToDisplay = "\(components.minute) min"
            }
        } else {
            textToDisplay = "\(components.hours) hrs"
        }
    case 1...6:
        textToDisplay = "\(components.day) d"
    default:
        dateFormatter.dateFormat = "MMM dd"
        textToDisplay = dateFormatter.string(from: date as Date)
    }

    return textToDisplay
}

error

rmaddy
  • 314,917
  • 42
  • 532
  • 579
When Key
  • 87
  • 3
  • 7

2 Answers2

2

Use like this :

Changes in my code :

  1. In place of NSDate, I used Date.
  2. In place of NSCalendar I used Calendar
  3. components(_:from:to:options:) has been renamed to dateComponents(_:from:to:)
  4. components values like day, minute, hour are optional. Thats why i added check before switch.

    func getTextToDisplayFormattingDate(date: Date) -> String {
        var textToDisplay = ""
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy hh:mm:ss a"
        dateFormatter.timeZone = TimeZone(identifier: "UTC")
    
        let cal = Calendar.current
        let components = cal.dateComponents([.day, .hour , .minute], from: date, to: Date())
    
        if let day = components.day, let minute = components.minute, let hour = components.hour {
            switch day {
            case 0:
                if hour == 0 {
                    if minute <= 0 {
                        textToDisplay = "just now "
                    } else {
                        textToDisplay = "\(minute) min"
                    }
                } else {
                    textToDisplay = "\(hour) hrs"
                }
            case 1...6:
                textToDisplay = "\(day) d"
            default:
                dateFormatter.dateFormat = "MMM dd"
                textToDisplay = dateFormatter.string(from: date)
            }
        }
        return textToDisplay
    }
    
Vini App
  • 7,339
  • 2
  • 26
  • 43
  • You don't need to cast `date as Date`, it's already a `Date`. – rmaddy Oct 15 '17 at 02:52
  • Given the nature of the question, it would probably be helpful if you added a description to your answer that points out all of the fixes you needed to make and why. – rmaddy Oct 15 '17 at 02:56
  • @ViniApp thanks very much !! it really working awesome. appreciated – When Key Oct 15 '17 at 07:53
0

Actually, it's hard to calculate the days, hours, minutes between 2 dates by NSCalendar.components, your procedure will cause an unexpected result. Usually, we calculate it by the TimeInterval between them. Try this in swift 3.2 or swift 4.0:

func getTextToDisplayFormattingDate(date: Date) -> String {
    var textToDisplay = ""

    let now = Date()
    let timeInterval = now.timeIntervalSince(date)
    if timeInterval < 60 {
        textToDisplay = "just now "
    }
    else if timeInterval < 60 * 60 {
        textToDisplay = "\(Int(timeInterval / 60)) min"
    }
    else if timeInterval < 60 * 60 * 24 {
        textToDisplay = "\(Int(timeInterval / 60 / 60)) hrs"
    }
    else {
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = TimeZone(identifier: "UTC")

        if timeInterval < 60 * 60 * 24 * 6 { //less than 6 days
            // For getting days
            // textToDisplay = "\(Int(timeInterval / 60 / 60 / 24)) d"

            // For getting weekday name
            dateFormatter.dateFormat = "EEEE"
            textToDisplay = dateFormatter.string(from: date) //weekday name
        }
        else{
            dateFormatter.dateFormat = "MMM dd"
            textToDisplay = dateFormatter.string(from: date as Date)
        }
    }

    return textToDisplay
}

And remember use constants to replace expresses like 60 * 60 * 24 to improve performance.

Yun CHEN
  • 6,450
  • 3
  • 30
  • 33
  • how can I show weekday name if less than 6 days. ex: just now, hours, Thursday, Wednesday, Tuesday, oct'10, oct'9 @yun chen – When Key Oct 20 '17 at 20:03
  • @WhenKey, I updated the answer for getting weekday name if less than 6 days. Try it. – Yun CHEN Oct 21 '17 at 03:34