Home > Blockchain >  How can I format a date string in Swift like I can in php?
How can I format a date string in Swift like I can in php?

Time:01-14

I am trying to format a date string that comes from an API that provides a timestamp in the following format (for example): 1970-01-01T12:30:00.000000Z.

I want to display the date in this format: 1st January 1970.

In php I could write it like this:

dateString = date( 'jS F Y', strtotime( $myUnformattedTimestamp ) );

How can I achieve this in Swift?

I did some obligatory Google searching and found this answer from another SO question but it doesn't help because it doesn't apply to my (arguably, more broader) situation.

This is the code in that answer:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy"
let date = dateFormatter.date(from: date)
dateFormatter.dateFormat = "yyyy-MM-dd"
let resultString = dateFormatter.string(from: date!)
print(resultString)

Which doesn't work. I tried replacing the date variable with mine and I'm getting all kinds of errors and confused with what Xcode is telling me.

I've only been working with Swift for 2 months so how it handles date and time is still not quite clear to me. How can I format my timestamp into various formats as easy as php?

Edit

I've taken some of the code from @udi answer to at least make a first pass at a simple implementation without the st, nd, rd, th suffix and have got this:

        let dateFormatterGet = DateFormatter()
        dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"

        let dateFormatterPrint = DateFormatter()
        dateFormatterPrint.dateFormat = "d MMM yyyy"

        if let date = dateFormatterPrint.date(from: created_at) {
            return dateFormatterPrint.string(from: date)
        } else {
           return "FAILED"
        }

This is the value that I have in my model (as shown above):

created_at: 1970-01-01T12:30:00.000000Z

The above code keeps returning FAILED. Is this because the timestamp has to match exactly the format of the timestamp? Is this a requirement for Swift to convert it properly? Either way, I've no idea why it's still not working.

Edit 2

Here is my model which contains my timestamps.

struct Message: Codable, Identifiable {
    var id:Int = 0
    var user_id:Int = 0
    var author_id:Int = 0
    var message:String = ""
    var unread:Int = 1
    var created_at:String = ""
    var updated_at:String = ""
}

The API returns the created_at and updated_at timestamps as a string in the format of YYYY-MM-DD HH:ii:ss, so basically 1970-01-01 12:30:00.

In my API request, it gets the data back and formats it like so:

let myMessage = try! JSONDecoder().decode(Message.self, from: data!)

So perhaps the JSONDecoder is changing my timestamp?

CodePudding user response:

let dateString = "1970-01-01 12:30:00"

//convert your date string to a Date object
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = dateFormatter.date(from: dateString)

//create a separate formatter for month and year
let dateFormatter_month_year = DateFormatter()
dateFormatter_month_year.dateFormat = "MMMM yyyy"
let month_year = dateFormatter_month_year.string(from: date!)

//create a separate formatter for day
let dateFormatter_day = DateFormatter()
dateFormatter_day.dateFormat = "d"
let day = dateFormatter_day.string(from: date!)

//create a number formatter to get suffix (st, nd, rd, th)
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .ordinal

let dayWithSuffix = numberFormatter.string(for: Int(day))!

print("\(dayWithSuffix) \(month_year)" )

I used two date formatters because it is difficult to get day suffix (st, nd, th) with out using a number formatter.

CodePudding user response:

It looks to me like the date you get is in the format of an internet date so we can use an ISO8601DateFormatter to convert the string date into a Date object.

let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]

Then I would suggest that instead of creating your own output format you should use one of the predefined ones and let the user's setting determine how it is formatted, assuming you want to show this date in the UI.

let outputFormatter = DateFormatter()
outputFormatter.dateStyle = .long
outputFormatter.locale = .current

Example

let input = "1970-01-01T12:30:00.000000Z"

if let date = formatter.date(from: input) {
    print(outputFormatter.string(from: date))
}
  • Related