[ios] Swift - iOS - Dates and times in different format

I am working for an application written in swift and i want to manipulate dates and times

let timestamp = NSDateFormatter.localizedStringFromDate(
    NSDate(),
    dateStyle: .ShortStyle,
    timeStyle: .ShortStyle
)

returns

2/12/15, 11:27 PM

if I want date and time in a different format, for example the date in a European format like dd/mm/yy and the hours in the 24h format without AM and PM. Is there some function that i can use or i have to use N Strings to reorder the various elements?

This question is related to ios swift timestamp nsdateformatter

The answer is


You have already found NSDateFormatter, just read the documentation on it.

NSDateFormatter Class Reference

For format character definitions
See: ICU Formatting Dates and Times
Also: Date Field SymbolTable..


If you want to use protocol oriented programming (Swift 3)

1) Create a Dateable protocol

protocol Dateable {
    func userFriendlyFullDate() -> String
    func userFriendlyHours() -> String
}

2) Extend Date class and implement the Dateable protocol

extension Date: Dateable {
    var  formatter: DateFormatter { return DateFormatter() }

    /** Return a user friendly hour */
    func userFriendlyFullDate() -> String {
        // Customize a date formatter
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
        formatter.timeZone = TimeZone(abbreviation: "UTC")

        return formatter.string(from: self)
    }

    /** Return a user friendly hour */
    func userFriendlyHours() -> String {
        // Customize a date formatter
        formatter.dateFormat = "HH:mm"
        formatter.timeZone = TimeZone(abbreviation: "UTC")

        return formatter.string(from: self)
    }
 
    // You can add many cases you need like string to date formatter

}

3) Use it

let currentDate: Date = Date()
let stringDate: String = currentDate.userFriendlyHours()
// Print 15:16

Here is a solution that works with Xcode 10.1 (FEB 23 2019) :

func getCurrentDateTime() {

    let now = Date()
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "fr_FR")
    formatter.dateFormat = "EEEE dd MMMM YYYY"
    labelDate.text = formatter.string(from: now)
    labelDate.font = UIFont(name: "HelveticaNeue-Bold", size: 12)
    labelDate.textColor = UIColor.lightGray

    let text = formatter.string(from: now)
    labelDate.text = text.uppercased()
}

The "Accueil" Label is not connected to the code.


As Zaph stated, you need to follow the documentation. Admittedly it may not be the most straightforward when compared to other class references. The short answer is, you use Date Field Symbol Table to figure out what format you want. Once you do:

let dateFormatter = NSDateFormatter()
//the "M/d/yy, H:mm" is put together from the Symbol Table
dateFormatter.dateFormat = "M/d/yy, H:mm"
dateFormatter.stringFromDate(NSDate())

You'll also need to be able to use the table if you need to convert a date that is a string into an NSDate.

let dateAsString = "02/12/15, 16:48"
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/d/yyyy, H:mm"
let date = dateFormatter.dateFromString(dateAsString)

func convertDateFormater(date: String) -> String {   
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    dateFormatter.timeZone = NSTimeZone(name: "UTC")

    guard let date = dateFormatter.dateFromString(date) else {
        assert(false, "no date from string")
        return ""
    }

    dateFormatter.dateFormat = "yyyy MMM EEEE HH:mm"
    dateFormatter.timeZone = NSTimeZone(name: "UTC")
    let timeStamp = dateFormatter.stringFromDate(date)

    return timeStamp
}

Edit for Swift 4

func convertDateFormatter(date: String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"//this your string date format
    dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
    dateFormatter.locale = Locale(identifier: "your_loc_id")
    let convertedDate = dateFormatter.date(from: date)

    guard dateFormatter.date(from: date) != nil else {
        assert(false, "no date from string")
        return ""
    } 

    dateFormatter.dateFormat = "yyyy MMM HH:mm EEEE"///this is what you want to convert format
    dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
    let timeStamp = dateFormatter.string(from: convertedDate!)

    return timeStamp
}

Current date time to formated string:

let currentDate = Date()
let dateFormatter = DateFormatter()

dateFormatter.dateFormat = "dd/MM/yyyy hh:mm:ss a"
let convertedDate: String = dateFormatter.string(from: currentDate) //08/10/2016 01:42:22 AM

More Date Time Formats


I used the a similar approach as @iod07, but as an extension. Also, I added some explanations in the comments to understand how it works.

Basically, just add this at the top or bottom of your view controller.

extension NSString {

class func convertFormatOfDate(date: String, originalFormat: String, destinationFormat: String) -> String! {

    // Orginal format :
    let dateOriginalFormat = NSDateFormatter()
    dateOriginalFormat.dateFormat = originalFormat      // in the example it'll take "yy MM dd" (from our call)

    // Destination format :
    let dateDestinationFormat = NSDateFormatter()
    dateDestinationFormat.dateFormat = destinationFormat // in the example it'll take "EEEE dd MMMM yyyy" (from our call)

    // Convert current String Date to NSDate
    let dateFromString = dateOriginalFormat.dateFromString(date)

    // Convert new NSDate created above to String with the good format
    let dateFormated = dateDestinationFormat.stringFromDate(dateFromString!)

    return dateFormated

}
}

Example

Let's say you want to convert "16 05 05" to "Thursday 05 May 2016" and your date is declared as follow let date = "16 06 05"

Then simply call call it with :

let newDate = NSString.convertFormatOfDate(date, originalFormat: "yy MM dd", destinationFormat: "EEEE dd MMMM yyyy")

Hope it helps !


extension String {

    func convertDatetring_TopreferredFormat(currentFormat: String, toFormat : String) ->  String {
        let dateFormator = DateFormatter()
        dateFormator.dateFormat = currentFormat
        let resultDate = dateFormator.date(from: self)
        dateFormator.dateFormat = toFormat
        return dateFormator.string(from: resultDate!)
    }

}

Call from your view controller file as below.

"your_date_string".convertDatetring_TopreferredFormat(currentFormat: "yyyy-MM-dd HH:mm:ss.s", toFormat: "dd-MMM-yyyy h:mm a")

let usDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "en-US"))
            //usDateFormat now contains an optional string "MM/dd/yyyy"

let gbDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "en-GB"))
            //gbDateFormat now contains an optional string "dd/MM/yyyy"

let geDateFormat = DateFormatter.dateFormat(FromTemplate: "MMddyyyy", options: 0, locale: Locale(identifier: "de-DE"))
            //geDateFormat now contains an optional string "dd.MM.yyyy"

You can use it in following way to get the current format from device:

let currentDateFormat = DateFormatter.dateFormat(fromTemplate: "MMddyyyy", options: 0, locale: Locale.current)

As already mentioned you have to use DateFormatter to format your Date objects. The easiest way to do it is creating a read-only computed property Date extension.


Read-Only Computed Properties

A computed property with a getter but no setter is known as a read-only computed property. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value.

Note:

You must declare computed properties—including read-only computed properties—as variable properties with the var keyword, because their value is not fixed. The let keyword is only used for constant properties, to indicate that their values cannot be changed once they are set as part of instance initialization.

You can simplify the declaration of a read-only computed property by removing the get keyword and its braces:


extension Formatter {
    static let date = DateFormatter()
}

extension Date {
    var europeanFormattedEn_US : String {
        Formatter.date.calendar = Calendar(identifier: .iso8601)
        Formatter.date.locale   = Locale(identifier: "en_US_POSIX")
        Formatter.date.timeZone = .current
        Formatter.date.dateFormat = "dd/M/yyyy, H:mm"
        return Formatter.date.string(from: self)
    }
}

To convert it back you can create another read-only computed property but as a string extension:

 extension String {
    var date: Date? {
        return Formatter.date.date(from: self)
    }
    func dateFormatted(with dateFormat: String = "dd/M/yyyy, H:mm", calendar: Calendar = Calendar(identifier: .iso8601), defaultDate: Date? = nil, locale: Locale = Locale(identifier: "en_US_POSIX"), timeZone: TimeZone = .current) -> Date? {
        Formatter.date.calendar = calendar
        Formatter.date.defaultDate = defaultDate ?? calendar.date(bySettingHour: 12, minute: 0, second: 0, of: Date())
        Formatter.date.locale = locale
        Formatter.date.timeZone = timeZone
        Formatter.date.dateFormat = dateFormat
        return Formatter.date.date(from: self)
    }
}

Usage:

let dateFormatted = Date().europeanFormattedEn_US         //"29/9/2018, 16:16"
if let date = dateFormatted.date {
    print(date.description(with:.current)) // Saturday, September 29, 2018 at 4:16:00 PM Brasilia Standard Time\n"\
    date.europeanFormattedEn_US                         // "29/9/2018, 16:27"
}

let dateString = "14/7/2016"
if let date = dateString.toDateFormatted(with: "dd/M/yyyy") {
    print(date.description(with: .current))
 // Thursday, July 14, 2016 at 12:00:00 PM Brasilia Standard Time\n"
}

let dateString = "1970-01-01T13:30:00.000Z"
let formatter = DateFormatter()

formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let date = formatter.date(from: String(dateString.dropLast(5)))!
formatter.dateFormat = "hh.mma"
print(formatter.string(from: date))

if You notice I have set .dateFormat = "hh.mma"by this you will get time only. Result:01.30PM


iOS 8+

It is cumbersome and difficult to specify locale explicitly. You never know where your app will be used. So I think, it is better to set locale to Calender.current.locale and use DateFormatter's setLocalizedDateFormatFromTemplate method.

setLocalizedDateFormatFromTemplate(_:)

Sets the date format from a template using the specified locale for the receiver. - developer.apple.com

extension Date {
    func convertToLocaleDate(template: String) -> String {
        let dateFormatter = DateFormatter()

        let calender = Calendar.current

        dateFormatter.timeZone = calender.timeZone
        dateFormatter.locale = calender.locale
        dateFormatter.setLocalizedDateFormatFromTemplate(template)

        return dateFormatter.string(from: self)
    }
}



Date().convertToLocaleDate(template: "dd MMMM YYYY")

Added some formats in one place. Hope someone get help.

Xcode 12 - Swift 5.3

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
var dateFromStr = dateFormatter.date(from: "12:16:45")!

dateFormatter.dateFormat = "hh:mm:ss a 'on' MMMM dd, yyyy"
//Output: 12:16:45 PM on January 01, 2000

dateFormatter.dateFormat = "E, d MMM yyyy HH:mm:ss Z"
//Output: Sat, 1 Jan 2000 12:16:45 +0600

dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
//Output: 2000-01-01T12:16:45+0600

dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
//Output: Saturday, Jan 1, 2000

dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
//Output: 01-01-2000 12:16

dateFormatter.dateFormat = "MMM d, h:mm a"
//Output: Jan 1, 12:16 PM

dateFormatter.dateFormat = "HH:mm:ss.SSS"
//Output: 12:16:45.000

dateFormatter.dateFormat = "MMM d, yyyy"
//Output: Jan 1, 2000

dateFormatter.dateFormat = "MM/dd/yyyy"
//Output: 01/01/2000

dateFormatter.dateFormat = "hh:mm:ss a"
//Output: 12:16:45 PM

dateFormatter.dateFormat = "MMMM yyyy"
//Output: January 2000

dateFormatter.dateFormat = "dd.MM.yy"
//Output: 01.01.00

//Output: Customisable AP/PM symbols
dateFormatter.amSymbol = "am"
dateFormatter.pmSymbol = "Pm"
dateFormatter.dateFormat = "a"
//Output: Pm

// Usage
var timeFromDate = dateFormatter.string(from: dateFromStr)
print(timeFromDate)

This is possibly an old thread but I was working on datetimes recently and was stuck with similar issue so I ended up creating a utility of mine which looks like this,

This utility would take a string date and would return an optional date object

        func toDate(dateFormat: DateFormatType) -> Date? {
        let formatter = DateFormatter()
        formatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?
        formatter.dateFormat = dateFormat.rawValue
        let temp = formatter.date(from: self)
        return formatter.date(from: self)
        }

the DateFormatType enum looks like this

        enum DateFormatType : String {
        case type1 = "yyyy-MM-dd - HH:mm:ss"
        case type2 = "dd/MM/yyyy"
        case type3 = "yyyy/MM/dd"
    }

One important thing I would like to mention here is the line

formatter.timeZone = NSTimeZone(name: "UTC") as TimeZone?

it's very important that you add this line because without this the DateFormatter would use it's default conversions to convert the date and you might end up seeing different dates if you are working with a remote team and get all sorts of issues with data depending on dates.

Hope this helps


Swift 3:

//This gives month as three letters (Jun, Dec, etc)
let justMonth = DateFormatter()
justMonth.dateFormat = "MMM"
myFirstLabel.text = justMonth.string(from: myDate)

//This gives the day of month, with no preceding 0s (6,14,29)
let justDay = DateFormatter()
justDay.dateFormat = "d"
mySecondLabel.text = justDay.string(from: myDate)

//This gives year as two digits, preceded by an apostrophe ('09, '16, etc)
let justYear = DateFormatter()
justYear.dateFormat = "yy"
myThirdLabel.text = "'\(justYear.string(from: lastCompDate))"

For more formats, check out this link to a codingExplorer table with all the available formats. Each date component has several options, for example:

Year:

  • "y" - 2016 (early dates like year 1 would be: "1")
  • "yy" - 16 (year 1: "01"
  • "yyy" - 2016 (year 1: "001")
  • "yyyy" - 2016 (year 1: "0001")

Pretty much every component has 2-4 options, using the first letter to express the format (day is "d", hour is "h", etc). However, month is a capital "M", because the lower case "m" is reserved for minute. There are some other exceptions though, so check out the link!


new Date(year,month,day,0,0,0,0) is local time (as input) new Date(year,month,day) is UTC

I was using a function to attain YYYY-MM-DD format to be compatible on iOS web, but that is also UTC when used in comparisons (not chained by getFullYear or similar) I've found it is best to use only the above with strong (hours,minutes,seconds,milliseconds) building a calendar, calculating with a Date objects and local references

export const zeroPad = (num) => {
  var res = "0";
  if (String(num).length === 1) {
    res = `0${num}`;
  } else {
    res = num;
  }
  return res;
};

Time Picker In swift

class ViewController: UIViewController {
    
    //timePicker
    @IBOutlet weak var lblTime: UILabel!
    @IBOutlet weak var timePicker: UIDatePicker!
    @IBOutlet weak var cancelTime_Btn: UIBarButtonItem!
    @IBOutlet weak var donetime_Btn: UIBarButtonItem!
    @IBOutlet weak var toolBar: UIToolbar!
    
    //Date picker
//    @IBOutlet weak var datePicker: UIDatePicker!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        ishidden(bool: true)
        let dateFormatter2 = DateFormatter()
        dateFormatter2.dateFormat = "HH:mm a" //"hh:mm a"
        lblTime.text = dateFormatter2.string(from: timePicker.date)
        
    }
    
    @IBAction func selectTime_Action(_ sender: Any) {
        timePicker.datePickerMode = .time
        ishidden(bool: false)
    }
    
    @IBAction func timeCancel_Action(_ sender: Any) {
        ishidden(bool: true)
    }
    
    @IBAction func timeDoneBtn(_ sender: Any) {
        let dateFormatter1 = DateFormatter()
        dateFormatter1.dateFormat =  "HH:mm a"//"hh:mm"
        
        let str = dateFormatter1.string(from: timePicker.date)
        lblTime.text = str
        
        ishidden(bool: true)
        
    }
    
    func ishidden(bool:Bool){
           timePicker.isHidden = bool
           toolBar.isHidden = bool
       }
}

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to swift

Make a VStack fill the width of the screen in SwiftUI Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Command CompileSwift failed with a nonzero exit code in Xcode 10 Convert Json string to Json object in Swift 4 iOS Swift - Get the Current Local Time and Date Timestamp Xcode 9 Swift Language Version (SWIFT_VERSION) How do I use Safe Area Layout programmatically? How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator Safe Area of Xcode 9 The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Examples related to timestamp

concat yesterdays date with a specific time How do I format {{$timestamp}} as MM/DD/YYYY in Postman? iOS Swift - Get the Current Local Time and Date Timestamp Pandas: Convert Timestamp to datetime.date Spark DataFrame TimestampType - how to get Year, Month, Day values from field? What exactly does the T and Z mean in timestamp? What does this format means T00:00:00.000Z? Swift - iOS - Dates and times in different format Convert timestamp to string Timestamp with a millisecond precision: How to save them in MySQL

Examples related to nsdateformatter

Convert NSDate to String in iOS Swift Convert string to date in Swift Date Format in Swift How to convert string to date to string in Swift iOS? Xcode swift am/pm time to 24 hour format Swift - iOS - Dates and times in different format Get current NSDate in timestamp format Formatting NSDate into particular styles for both year, month, day, and hour, minute, seconds