How to Get the Current Date in Short Format in Swift

How to get the current time as datetime

Update for Swift 3:

let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date)
let minutes = calendar.component(.minute, from: date)

I do this:

let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
let hour = components.hour
let minutes = components.minute

See the same question in objective-c How do I get hour and minutes from NSDate?

Compared to Nate’s answer, you’ll get numbers with this one, not strings… pick your choice!

Date Format in Swift

You have to declare 2 different NSDateFormatters, the first to convert the string to a NSDate and the second to print the date in your format.

Try this code:

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

let dateFormatterPrint = NSDateFormatter()
dateFormatterPrint.dateFormat = "MMM dd,yyyy"

let date: NSDate? = dateFormatterGet.dateFromString("2016-02-29 12:24:26")
print(dateFormatterPrint.stringFromDate(date!))

Swift 3 and higher:

From Swift 3 NSDate class has been changed to Date and NSDateFormatter to DateFormatter.

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

let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "MMM dd,yyyy"

if let date = dateFormatterGet.date(from: "2016-02-29 12:24:26") {
print(dateFormatterPrint.string(from: date))
} else {
print("There was an error decoding the string")
}

How to take just the current time (hh:mm:ss format) from Date() in Swift?

You are printing the Date object directly, which uses a predetermined description algorithm to display the date.

But one should not try to parse strings out of that. Instead use DateFormatter to build your date/time strings. So, you might have a date formatter for the date and another for the time:

let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
return formatter
}()

let timeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.timeStyle = .medium
return formatter
}()

Note, I would advise not using hard-coded date format strings and setting the formatter’s dateFormat string, but rather use these “style” properties to dictate the type of string you want, while still honoring the preferences of the user (e.g. 01-02-21 will be interpreted as January 2nd in the US, but February 1st in many other locales).

Anyway, now that you have those formatter properties, you can use them in your code. E.g., given that you tagged this as swiftui, you might use Text with formatter:

var body: some View {
VStack {
Text("Date: \(date, formatter: dateFormatter)")
Text("Time: \(date, formatter: timeFormatter)")
}
}

Or, you can use the DateFormatter method string(from:) to manually get the string:

let string = dateFormatter.string(from: date)
print(string) // 5/30/21 in the US; 30/5/21 in many other locales

On the other hand, if this string was not for display in the UI and you really wanted a fixed string format (e.g. you were writing the date string to persistent storage or including it in some web request), you would instead use ISO8601DateFormatter (which produces ISO8601/RFC3339 date strings, which are fixed format and, by default, in GMT/Zulu), e.g.:

let formatter = ISO8601DateFormatter()
let string = formatter.string(from: date)
print(string) // 2021-05-30T17:27:45Z

Date format in Swift TODAY TOMORROW YESTERDAY

The DateFormatter doesn't behave well when setting doesRelativeDateFormatting = true and trying to apply a custom format at the same time. So the easiest solution is to use the format given by a Style and a Locale

let relativeDateFormatter = DateFormatter()
relativeDateFormatter.timeStyle = .none
relativeDateFormatter.dateStyle = .medium
relativeDateFormatter.locale = Locale(identifier: "en_GB")
relativeDateFormatter.doesRelativeDateFormatting = true

Example

let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yyyy-MM-dd"

let dates = ["2020-09-01", "2020-09-15", "2020-09-16", "2020-09-30"].compactMap { inputFormatter.date(from: $0)}

for date in dates {
print(relativeDateFormatter.string(from: date))
}

1 Sep 2020

Yesterday

Today

30 Sep 2020

Now if you want to apply a custom format I have not found a solution for this when using the same DateFormatter instance so we need to create a new one for the custom format and use it together with a check so we apply the custom format only when it is not Today etc

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE, MMM dd"

for date in dates {
let string = relativeDateFormatter.string(from: date)
if let _ = string.rangeOfCharacter(from: .decimalDigits) {
print(dateFormatter.string(from: date))
} else {
print(string)
}
}

Tuesday, Sep 01

Yesterday

Today

Wednesday, Sep 30

How to do a proper Date formatter in Swift

You don't need two date formatters to convert one date string to another.

My suggestion is to create one persistent date formatter with a fixed locale

let dateFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()

This could be also an extension

extension DateFormatter {
static let posixFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
}

And secondly a function with parameters for input format with a default value and output format

func formatDate(dateString: String, inFormat: String = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", outFormat: String) -> String? {

// let dateFormatter = DateFormatter.posixFormatter

//this is format I get from my response
dateFormatter.dateFormat = inFormat
guard let date = dateFormatter.date(from: dateString) else { return nil }

dateFormatter.dateFormat = outFormat
return dateFormatter.string(from: date)
}

You have to check if a date could be created from the string so the return value is an optional.

Side note:

The Z in an ISO8601 string is the time zone specifier. It must not be wrapped in single quotes. And the year specifier is always lowercase yyyy.

How to format date string if the given date format changes

You can create two date formatters, one with time and another without it and use nil coalescing operator to provide a fallback in case the first one fails. Regarding the date format when returning your final string you should respect the user's device locale and settings. Just use dateStyle and timeStyle when displaying a date to the user:

extension Formatter {
static let date: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
static let dateAndTime: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter
}()
static let localizedDate: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter
}()
}


extension Date {
var localizedDate: String { Formatter.localizedDate.string(from: self) }
}


func formatted(from string: String?) -> String {
guard
let string = string,
let date = Formatter.dateAndTime.date(from: string) ??
Formatter.date.date(from: string)
else { return "" }

return date.localizedDate
}

let strFromApi = "2020-12-22 00:00:00" // "2020-12-22" //
formatted(from: strFromApi) // "Dec 22, 2020"


Related Topics



Leave a reply



Submit