1

I want to convert timeUTC to "5s ago." ago label also thinking 12h / 24h changes on the phone. Because goes crash. Now below lines of code return label value what I want in the Playground. But not on my ios project. It doesn't go into If block. What I'm missing or What's the wrong with that?

    let dateStringUTC = "2016-10-22 12:37:48 +0000"
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"

    if let from = dateFormatter.date(from: dateStringUTC) {

        dateFormatter.dateFormat = "MMM d, yyyy h:mm:ss a"
        let stringFromDate = dateFormatter.string(from: from)
        let dateLast = dateFormatter.date(from: stringFromDate)

        let now = Date()
        let components: NSCalendar.Unit = [.second, .minute, .hour, .day, .weekOfMonth]
        let difference = (Calendar.current as NSCalendar).components(components, from: dateLast!, to: now, options: [])

        if difference.second! <= 0 {
            self.timeInfoLbl.text = "now"
        }
        if difference.second! > 0 && difference.minute! == 0 {
            self.timeInfoLbl.text = String(describing: difference.second!) + "s."
        }
        if difference.minute! > 0 && difference.hour! == 0 {
            self.timeInfoLbl.text = String(describing: difference.minute!) + "m."
        }
        if difference.hour! > 0 && difference.day! == 0 {
            self.timeInfoLbl.text = String(describing: difference.hour!) + "h."
        }
        if difference.day! > 0 && difference.weekOfMonth! == 0 {
            self.timeInfoLbl.text = String(describing: difference.day!) + "d."
        }
        if difference.weekOfMonth! > 0 {
            self.timeInfoLbl.text = String(describing: difference.weekOfMonth!) + "w."

            if difference.weekOfMonth! > 52 {
                let number = Float(difference.weekOfMonth!) / 52
                let strYear = String(format:"%.1f", number)
                self.timeInfoLbl.text = strYear + " year"
            }
        }
    }
iamburak
  • 3,508
  • 4
  • 34
  • 65

1 Answers1

2

To convert this string to a date, I would do:

let dateStringUTC = "2016-10-22 12:37:48 +0000"
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss X"
let date = dateFormatter.date(from: dateStringUTC)!

Then, to show the elapsed time in a nice format, consider DateComponentsFormatter, e.g.:

let now = Date()

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.maximumUnitCount = 2
let string = formatter.string(from: date, to: Date())! + " " + NSLocalizedString("ago", comment: "added after elapsed time to say how long before")
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Firstly thanks for care, I think I have a problem with UTC to Date() convert, How Can I convert "2016-10-22 12:37:48 +0000" to Date() type correctly? Then I will try this both for device time 12h and 24h, because I have a big bug with that. – iamburak Jan 06 '17 at 23:44
  • 1
    Make sure to set your `locale`, e.g. `dateFormatter.locale = Locale(identifier: "en_US_POSIX")`. Also, instead of `ZZZ`, I would have used `ZZZZZ` or `X`. – Rob Jan 06 '17 at 23:45
  • Thank you for describing again, I have already 24h UTC strings in my database, so now It looks well, working independently from device time type. Now I see `2 months, 2 weeks ago` for above date/time okay. Also ı wonder that Can I enumerate all of these parts to decide show me only weeks? For example, If there is 2 month and 2 week, I can calculate weeks in separate blocks and then append others. – iamburak Jan 07 '17 at 00:03
  • 1
    If you only want to see weeks, you can set `allowedUnits`, e.g. `formatter.allowedUnits = [.weekOfMonth, .day, .hour, .minute]`. You can write your own hairy code to build the string manually if you really want, but why would you? This date components formatter is a nice alternative. Frankly, though, it's not entirely clear if I get what you want nor why this standard format doesn't work. – Rob Jan 07 '17 at 00:10
  • Got it. I have tried and I can reach what I want in these components right now or maybe using `formatter.maximumUnitCount = 1` can be another option to be exact result needed calculation especially for months. Thank you for all description. I remember that You taught me many things via stackoverflow. Have a nice new year! – iamburak Jan 07 '17 at 00:32
  • Hi again, I noticed that DateComponentsFormatter() component doesn't display english If I changed my device language. What missing here? – iamburak Jan 10 '17 at 17:15
  • 1
    That's correct: It is a localized string showing in the user's preferred language. When showing strings to the end user, that behavior is generally preferable. So use `Locale(identifier: "en_US_POSIX")` in those cases where you need to force a particular convention (e.g. parsing and preparing strings being exchanged with some web service or stored in some database), but use the default `Locale.current` whenever showing strings to the end user. – Rob Jan 10 '17 at 17:25
  • I set like you did above to `dateFormatter.locale = Locale(identifier: "en_US_POSIX")` but DateComponentsFormatter() doesn't have `locale` property. Where should I set it? – iamburak Jan 10 '17 at 17:40
  • 1
    The `DateComponentsFormatter` has a `calendar` property, and the `Calendar` object has a `locale` property. – Rob Jan 10 '17 at 17:48
  • Thank you for all. – iamburak Jan 10 '17 at 18:04