Sydney Loteria
Sydney Loteria

Reputation: 10451

How do I convert a date/time string into a different date string?

How will I convert this datetime from the date?

From this: 2016-02-29 12:24:26
to: Feb 29, 2016

So far, this is my code and it returns a nil value:

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let date: NSDate? = dateFormatter.dateFromString("2016-02-29 12:24:26")
print(date)

Upvotes: 314

Views: 566289

Answers (25)

yoAlex5
yoAlex5

Reputation: 34225

Swift Date

Date <-> Formatter <-> String

Date

Date:

  • single point in time (UTC). It means that it doesn't contain any TimeZone or other metadata
  • Is a kind of wrapper of Double - seconds from 2001-01-01 00:00:00 +0000
Date(timeIntervalSinceReferenceDate: .zero)
  • print output of Date in UTC(+0000) is in ISO 8601(ISO8601DateFormatter yyyy-MM-dd'T'HH:mm:ssZ)

Create Date:

  • current time in UTC Date()
  • from String using Formatter and TimeZone
func strToDateWithLocalTimeZone(_ str: String, format: String) -> Date {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = format
    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
//        dateFormatter.timeZone = .current //by default
//        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    
    return dateFormatter.date(from: str)!
}

Formatter

It is responsible for formatting date and have two main functions:

  • Date -> String: .string(from: Date)
  • String -> Date: .date(from: String)

Main parts:

  • Formatter.dateFormat

    • Custom: yyyy-MM-dd, dd.MM.yyyy HH:mm:ss...
    • ISO8601DateFormatter: yyyy-MM-dd'T'HH:mm:ssZ
  • Formatter.TimeZone

    • Formatter.TimeZone = .current is set by default. It means if you don't setup it explicitly local TimeZone will be used by default
    • Local aka Current TimeZone is defined by System and your settings. Also it is different for specific Date. It means that when you use Formatter.TimeZone.current for Date with different time shift in time - value will be different(for current TimeZone). Fir example In my country we have two time shifts in a year, and TimeZone for specific date will reflect it
    //TimeZone in Settings
    Settings -> General -> Date & Time -> Time Zone
    
    //Date -> String
    2022-12-31T22:59:59+02:00
    2023-04-04T21:01:34+03:00
    
    • Specific. TimeZone(abbreviation: "CET") == TimeZone(secondsFromGMT: 3600) (3600 seconds == 1 hour). UTC. TimeZone(abbreviation: "UTC")...

String

  • If String doesn't contain TimeZone you are able to set TimeZone in Formatter
  • When String contains TimeZone - it means that it is a single variant of interpret the String in Date UTC that is why Formatter.TimeZone will not have any effect
String <date_with_time_zone> -> Format <any_time_zome> -> single Date
String: 09.04.2023T18:58:32+0300 -> Format <any_time_zome> -> Date: 2023-04-09 15:58:32 +0000

Experiments:

My Local time:

let dateFormatStr = "dd.MM.yyyy'T'HH:mm:ssZ"

//Current TimeZone
let currentTimeZone = TimeZone.current
let seconds = currentTimeZone.secondsFromGMT()
let hours = seconds/3600
let minutes = abs(seconds/60) % 60
print("current TimeZone: \(String(format: "%+.2d:%.2d", hours, minutes)) for:\(currentTimeZone)")
//        current TimeZone: +03:00 for:Europe/Kiev (fixed (equal to current))

//Current Date
let currentDate = Date()
print("current Date UTC: \(currentDate)")
//        current Date UTC: 2023-04-09 15:58:32 +0000

//Date -> String
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = dateFormatStr
dateFormatter.timeZone = .current //by default. Adds +0300 in my case at the end of string
let currentDateStr = dateFormatter.string(from: currentDate)
print("current DateString Local: \(currentDateStr)")
//        current DateString Local: 09.04.2023T18:58:32+0300

//String to Date
let dateFormatterLocal = DateFormatter()
dateFormatterLocal.locale = Locale(identifier: "en_US_POSIX")
dateFormatterLocal.dateFormat = dateFormatStr
dateFormatterLocal.timeZone = .current //by default. Doesn't have effect when String contains TimeZone

let dateLocal = dateFormatterLocal.date(from: currentDateStr)!
print("current Date Local: \(dateLocal)")
//        current Date Local: 2023-04-09 15:58:32 +0000

Output in a single place

current TimeZone: +03:00 for:Europe/Kiev (fixed (equal to current))
current Date UTC: 2023-04-09 15:58:32 +0000
current DateString Local: 09.04.2023T18:58:32+0300
current Date Local: 2023-04-09 15:58:32 +0000

Some real use case:

  1. Client make a transaction
  2. Send Date to Server as String
  3. Get Date from Server as String
  4. Show Date as String in:
  • UTC
  • Local TimeZone
  • Transaction TimeZone
1. Client make a transaction
Date()
Formatter.timeZone = .current
String: 09.04.2023 18:58:32+0300

2. Send Date to Server as String
09.04.2023 18:58:32+0300

3. Get Date from Server as String 
09.04.2023 18:58:32+0300

4. Show Date

- UTC TimeZone
String -> Date -> Formatter.timeZone = UTC -> String
UTC: 09.04.2023 15:58:32+0000

- Local TimeZone(Depends where you are)
String -> Date -> Formatter.timeZone = .current -> String
For example Local timezone will be different: 
    if you now at +0100 TimeZone 09.04.2023 16:58:32+0100
    if you now at +0200 TimeZone 09.04.2023 17:58:32+0200

- Transaction TimeZone
remove +0300 from String. It is a workaround, and not a clear solution but as is: 09.04.2023 18:58:32 

String -> Formatter.timeZone = UTC -> Date: 09.04.2023 18:58:32+0000
Date -> Formatter.timeZone = UTC -> String: 09.04.2023 18:58:32+0000

to skip timezone

dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)

Notes:

  • If you just create DateFormatter() and convert to String the output will be empty. In this case you are able to use styles(dateStyle and timeStyle) to get predefined format

Upvotes: 0

BatyrCan
BatyrCan

Reputation: 6983

This may be useful for who want to use dateformatter.dateformat;

if you want 12.09.18 you use dateformatter.dateformat = "dd.MM.yy"

Wednesday, Sep 12, 2018           --> EEEE, MMM d, yyyy
09/12/2018                        --> MM/dd/yyyy
09-12-2018 14:11                  --> MM-dd-yyyy HH:mm
Sep 12, 2:11 PM                   --> MMM d, h:mm a
September 2018                    --> MMMM yyyy
Sep 12, 2018                      --> MMM d, yyyy
Wed, 12 Sep 2018 14:11:54 +0000   --> E, d MMM yyyy HH:mm:ss Z
2018-09-12T14:11:54+0000          --> yyyy-MM-dd'T'HH:mm:ssZ
12.09.18                          --> dd.MM.yy
10:41:02.112                      --> HH:mm:ss.SSS

Here are alternatives:

  • Era: G (AD), GGGG (Anno Domini)
  • Year: y (2018), yy (18), yyyy (2018)
  • Month: M, MM, MMM, MMMM, MMMMM
  • Day of month: d, dd
  • Day name of week: E, EEEE, EEEEE, EEEEEE

Upvotes: 605

mahan
mahan

Reputation: 14935

iOS 15.0+

iPadOS 15.0+,

macOS 12.0+,

Mac Catalyst 15.0+,

tvOS 15.0+,

watchOS 8.0+,

Xcode 13.0+

Use formatted(date:time:)

let now = Date.now
let date = now.formatted(date: .abbreviated, time: .omitted)

Instead of .abbreviated, you may use another DateStyle such as .long, .numeric or define a custom format.


SwiftUI

 Text(myDate, format: Date.FormatStyle(date: .numeric, time: .omitted))

or simply use:

 Text(myDate, style: .date)

Reference

formatted(date:time:)

init(_:format:)

Text.DateStyle

Upvotes: 21

Muhammad Asad Chattha
Muhammad Asad Chattha

Reputation: 1171

Swift Version: 5.6 + Above

DateFormatter’s dateFormatter property is used to format Date with a custom String Pattern.

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy"
    
let date = dateFormatter.string(from: datePicker.date)
print(date)
//Feb 28, 2022

If you want anything that shouldn’t be formatted and printed, then use single quotes around that word. Like; ‘at’

dateFormatter.dateFormat = "MMM dd, yyyy 'at' hh:MM a"
// May 29, 2022 at 12:05 PM

These are all possible Patterns to Format Date, Time & Time Zone.

enter image description here

Upvotes: 18

Abdullah
Abdullah

Reputation: 393

Here is a full date format extension for swift

extension Date {
   func getFormattedDate(format: String) -> String {
        let dateformat = DateFormatter()
        dateformat.dateFormat = format
        return dateformat.string(from: self)
    }
    
    func getFormattedDate(style: DateFormatter.Style) -> String {
         let dateformat = DateFormatter()
         dateformat.dateStyle = style
         return dateformat.string(from: self)
     }
}

Usage

myDate.getFormattedDate(style: .medium) //medium, short, full, long

OR

myDate.getFormattedDate(format: "yyyy/MM/dd HH:mm:ss")

Upvotes: 1

Vishal Vaghasiya
Vishal Vaghasiya

Reputation: 4901

Swift - 5.0

let date = Date()
let format = date.getFormattedDate(format: "yyyy-MM-dd HH:mm:ss") // Set output format

extension Date {
   func getFormattedDate(format: String) -> String {
        let dateformat = DateFormatter()
        dateformat.dateFormat = format
        return dateformat.string(from: self)
    }
}

Swift - 4.0

2018-02-01T19:10:04+00:00 Convert Feb 01,2018

extension Date {
    static func getFormattedDate(string: String , formatter:String) -> String{
        let dateFormatterGet = DateFormatter()
        dateFormatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
        
        let dateFormatterPrint = DateFormatter()
        dateFormatterPrint.dateFormat = "MMM dd,yyyy"
        
        let date: Date? = dateFormatterGet.date(from: "2018-02-01T19:10:04+00:00")
        print("Date",dateFormatterPrint.string(from: date!)) // Feb 01,2018
        return dateFormatterPrint.string(from: date!);
    }
}

Upvotes: 106

Karan Vakharia
Karan Vakharia

Reputation: 87

class Utils {
  class func dateFormatter(_ date: Date, _ format: String) -> String {
    let dateformat = DateFormatter()
    dateformat.dateFormat = format
    return dateformat.string(from: date)
  }
}
print(Utils.dateFormatter(Date(), "EEEE, MMM d, yyyy"))

Create class name Utils import same function and you can use globally accesss any where with your date and formate

Upvotes: -1

Martin
Martin

Reputation: 4765

From iOS 15 use something like this:

extension Date {
    var string: String {
        if #available(iOS 15.0, *) {
            return self.formatted(date: .complete, time: .complete)
        } else {
            return self.description
        }
    }
}

Upvotes: 2

Atikul Gazi
Atikul Gazi

Reputation: 1245

Convert @BatyrCan answer to Swift 5.3 with extra formats. Tested in Xcode 12.

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

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

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

Upvotes: 34

Sunil aruru
Sunil aruru

Reputation: 497

Place it in extension and call it like below. It's easy to use throughout the application.

self.getFormattedDate(strDate: "20-March-2019", currentFomat: "dd-MMM-yyyy", expectedFromat: "yyyy-MM-dd")

Implementation

func getFormattedDate(strDate: String , currentFomat:String, expectedFromat: String) -> String{
    let dateFormatterGet = DateFormatter()
    dateFormatterGet.dateFormat = currentFomat

    let date : Date = dateFormatterGet.date(from: strDate) ?? Date()

    dateFormatterGet.dateFormat = expectedFromat
    return dateFormatterGet.string(from: date)
}

Upvotes: 2

Jonas Deichelmann
Jonas Deichelmann

Reputation: 3743

Swift 3 and higher

let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
dateFormatter.locale = Locale.current
print(dateFormatter.string(from: date)) // Jan 2, 2001

This is also helpful when you want to localize your App. The Locale(identifier: ) uses the ISO 639-1 Code. See also the Apple Documentation

Upvotes: 70

Zgpeace
Zgpeace

Reputation: 4467

I recommend to add timezone by default. I will show an example for swift 5
1. new an extension file Date+Formatter.swift

import Foundation

extension Date {
    func getFormattedDateString(format: String) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: self)
    }
}
  1. Usage example
    let date = Date()
    let dateString = date.getFormattedDateString(format: "yyyy-MM-dd HH:mm:ss")
    print("dateString > \(dateString)")
    // print
    // dateString > 2020-04-30 15:15:21

Upvotes: 0

Rajdeo Das
Rajdeo Das

Reputation: 126

    import UIKit
    // Example iso date time
    let isoDateArray = [
        "2020-03-18T07:32:39.88Z",
        "2020-03-18T07:32:39Z",
        "2020-03-18T07:32:39.8Z",
        "2020-03-18T07:32:39.88Z",
        "2020-03-18T07:32:39.8834Z"
    ]


    let dateFormatterGetWithMs = DateFormatter()
    let dateFormatterGetNoMs = DateFormatter()

// Formater with and without millisecond 
    dateFormatterGetWithMs.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    dateFormatterGetNoMs.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"

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

    for dateString in isoDateArray {
        var date: Date? = dateFormatterGetWithMs.date(from: dateString)
        if (date == nil){
            date = dateFormatterGetNoMs.date(from: dateString)
        }
        print("===========>",date!)
    }

Upvotes: 5

Abdul Karim Khan
Abdul Karim Khan

Reputation: 4935

For Swift 4.2, 5

Pass date and format as whatever way you want. To choose format you can visit, NSDATEFORMATTER website:

static func dateFormatter(date: Date,dateFormat:String) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = dateFormat
    return dateFormatter.string(from: date)
}

Upvotes: 2

Akbar Khan
Akbar Khan

Reputation: 2417

Swift 4, 4.2 and 5

func getFormattedDate(date: Date, format: String) -> String {
        let dateformat = DateFormatter()
        dateformat.dateFormat = format
        return dateformat.string(from: date)
}

let formatingDate = getFormattedDate(date: Date(), format: "dd-MMM-yyyy")
        print(formatingDate)

Upvotes: 13

LorenzOliveto
LorenzOliveto

Reputation: 7936

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")
}

Upvotes: 400

Amit Tyagi
Amit Tyagi

Reputation: 320

If you want to parse date from "1996-12-19T16:39:57-08:00", use the following format "yyyy-MM-dd'T'HH:mm:ssZZZZZ":

let RFC3339DateFormatter = DateFormatter()
RFC3339DateFormatter.locale = Locale(identifier: "en_US_POSIX")
RFC3339DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
RFC3339DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)

/* 39 minutes and 57 seconds after the 16th hour of December 19th, 1996 with an offset of -08:00 from UTC (Pacific Standard Time) */
let string = "1996-12-19T16:39:57-08:00"
let date = RFC3339DateFormatter.date(from: string)

from Apple https://developer.apple.com/documentation/foundation/dateformatter

Upvotes: 8

&#194;ngelo Polotto
&#194;ngelo Polotto

Reputation: 9531

I solved my problem to the format yyyy-MM-dd'T'HH:mm:ss.SSS'Z'(e.g 2018-06-15T00:00:00.000Z) with this:

func formatDate(date: String) -> String {
   let dateFormatterGet = DateFormatter()
   dateFormatterGet.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

   let dateFormatter = DateFormatter()
   dateFormatter.dateStyle = .medium
   dateFormatter.timeStyle = .none
   //    dateFormatter.locale = Locale(identifier: "en_US") //uncomment if you don't want to get the system default format.

   let dateObj: Date? = dateFormatterGet.date(from: date)

   return dateFormatter.string(from: dateObj!)
}

Upvotes: 33

Pankaj Jangid
Pankaj Jangid

Reputation: 832

just use below function to convert date format:-

  let convertedFormat =  convertToString(dateString: "2019-02-12 11:23:12", formatIn: "yyyy-MM-dd hh:mm:ss", formatOut: "MMM dd, yyyy")    //calling function

   print(convertedFormat) // feb 12 2019


 func convertToString (dateString: String, formatIn : String, formatOut : String) -> String {

    let dateFormater = DateFormatter()
    dateFormater.timeZone = NSTimeZone(abbreviation: "UTC") as TimeZone!
    dateFormater.dateFormat = formatIn
    let date = dateFormater.date(from: dateString)

    dateFormater.timeZone = NSTimeZone.system

    dateFormater.dateFormat = formatOut
    let timeStr = dateFormater.string(from: date!)
    return timeStr
 }

Upvotes: 3

Markus
Markus

Reputation: 1177

Another interessant possibility of format date. This screenshot belongs to Apple's App "News".

App screenshot

Here is the code:

let dateFormat1 = DateFormatter()
dateFormat1.dateFormat = "EEEE"
let stringDay = dateFormat1.string(from: Date())

let dateFormat2 = DateFormatter()
dateFormat2.dateFormat = "MMMM"
let stringMonth = dateFormat2.string(from: Date())

let dateFormat3 = DateFormatter()
dateFormat3.dateFormat = "dd"
let numDay = dateFormat3.string(from: Date())

let stringDate = String(format: "%@\n%@ %@", stringDay.uppercased(), stringMonth.uppercased(), numDay)

Nothing to add to alternative proposed by lorenzoliveto. It's just perfect.

let dateFormat = DateFormatter()
dateFormat.dateFormat = "EEEE\nMMMM dd"
let stringDate = dateFormat.string(from: Date()).uppercased()

Upvotes: 5

ciccioska
ciccioska

Reputation: 1291

Swift 3 version with the new Date object instead NSDate:

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

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

let date: Date? = dateFormatterGet.date(from: "2017-02-14 17:24:26")
print(dateFormatter.string(from: date!))

EDIT: after mitul-nakum suggestion

Upvotes: 37

Jonathan Cravotta
Jonathan Cravotta

Reputation: 156

Swift 3 with a Date extension

extension Date {
    func string(with format: String) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        return dateFormatter.string(from: self)
    }
}

Then you can use it like so:

let date = Date()
date.string(with: "MMM dd, yyyy")

Upvotes: 11

M.zar
M.zar

Reputation: 9

swift 3

func dataFormat(dataJ: Double) -> String {

        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .long
        dateFormatter.timeStyle = .none
        let date = Date(timeIntervalSince1970: dataJ)
        return (dataJ != nil) ? "Today, \(dateFormatter.string(from: date))" : "Date Invalid"

    }

Upvotes: 0

iParesh
iParesh

Reputation: 2368

swift 3

let date : Date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy"
let todaysDate = dateFormatter.string(from: date)

Upvotes: 30

dasdom
dasdom

Reputation: 14063

To convert 2016-02-29 12:24:26 into a date, use this date formatter:

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"

Edit: To get the output Feb 29, 2016 use this date formatter:

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

Upvotes: 2

Related Questions