Dravidian Dravidian - 3 months ago 22
Swift Question

How long ago did the User create a post, NSDate(), Manipulating the format of the "time of post" created

I am making a social app that saves its posts in user specific nodes , with that i am also saving the time of post in this format :-

Wednesday, July 20, 2016, 00:14

which i display with the post in the global feed of friends of the user.


  • Before 24 hours of that post , i want to display time of post on the feed as this :- "5 Hours Ago"

  • After 24 hours of that post time of post becomes something like this :- "Yesterday"...

  • After 48 hours of that post time of post becomes something like this :- "On 5 Aug"...



So far i have come up with these two options:-

1.) Change the time of the feed in the database, which i think would be much better option.

2.) Retrieve the time of post , iterate through MULTIPLE
if
conditions and set the time of post accordingly.

I would be able to implement the second option but i have no clue to how to go forward with option one

Given that my JSON tree is something like this

appname:{

users : {....
.....

user1 : {....
.....

postsCreated : {
post1 : {
..
timeofPost : ""Wednesday, Aug 5, 2016, 00:14""

}
}
}
}
}


I did stumble upon http://momentjs.com/ but thats for Javascript

Also any suggestion on my JSON tree or is it fine the way it is?

Rob Rob
Answer

You propose:

  1. Change the time of the feed in the database, which i think would be much better option.

No, the date in the database, as well as that which is communicated with web service, should not be a formatted string. The database and the web service should be capturing the raw dates (or, more accurately, RFC3339/ISO8601 format or seconds from some reference date). The formatting of the elapsed time in a string for the UI is the responsibility of the app.

  1. Retrieve the time of post, iterate through MULTIPLE if conditions and set the time of post accordingly.

Yes, that's what you should do.

By the way, if you're going to omit the year, you probably have a fourth permutation which includes year if the date is more than one year in the past, e.g.:

func formattedPostDateString(date: NSDate) -> String {
    let now = NSDate()
    let elapsed = NSCalendar.currentCalendar().components([.Day, .Year], fromDate: date, toDate: now, options: [])

    switch (elapsed.year, elapsed.day) {
    case (0, 0):
        return "\(elapsedFormatter.stringFromDate(date, toDate: now)!) \(agoDateString)"
    case (0, 1):
        return yesterdayString
    case (0, _):
        return "\(onDateString) \(lessThanOneYearFormatter.stringFromDate(date))"
    default:
        return "\(onDateString) \(moreThanOneYearFormatter.stringFromDate(date))"
    }
}

Where

let onDateString = NSLocalizedString("On", comment: "prefix used in 'On 5 Aug'")
let agoDateString = NSLocalizedString("ago", comment: "suffix use in '4 hours ago'")
let yesterdayString = NSLocalizedString("Yesterday", comment: "showing 'date' where it's between 24 and 48 hours ago")

let elapsedFormatter: NSDateComponentsFormatter = {
    let formatter = NSDateComponentsFormatter()
    formatter.allowedUnits = [.Year, .Month, .Day, .Hour, .Minute, .Second]
    formatter.unitsStyle = .Full
    formatter.maximumUnitCount = 1
    return formatter
}()

let lessThanOneYearFormatter: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.dateFormat = NSDateFormatter.dateFormatFromTemplate("MMM d", options: 0, locale: nil)
    return formatter
}()

let moreThanOneYearFormatter: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.dateStyle = .MediumStyle
    return formatter
}()

The only thing you need to do is to convert the string returned by the web service into NSDate object. To that end, the web service should probably return the post date in ISO 8601/RFC 3339 format (e.g. 2016-08-26T15:01:23Z format).


To create ISO8601/RFC3339 dates in Swift 2:

let isoDateFormatter: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
    return formatter
}()

And then:

let string = isoDateFormatter.stringFromDate(date)

Or

let date = isoDateFormatter.dateFromString(string)

Or in iOS 10+ using Swift 3, you can use the new ISO8601DateFormatter:

let isoDateFormatter = ISO8601DateFormatter()
Comments