Convert String to Date with phones with differents date formats [duplicate] - ios

This question already has an answer here:
DateFormatter doesn't return date for "HH:mm:ss"
(1 answer)
Closed 2 years ago.
I have some troubles parsing string date to Date format.
I recibe from one API the date string with this format 2020-08-27 12:39:32 (the date come in 24 hour format) and I have an extension of String to convert it to Date. So I do the convertion like this:
apiTime.toDate(format: "yyyy-MM-dd HH:mm:ss")
All works fine if the phone is configured with 24 hour. The problem came when the app runs in a AM/PM date format because the date return nil.
This is my extension to convert String to Date.
extension String {
func toDate(format: String) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.amSymbol = "AM"
dateFormatter.pmSymbol = "PM"
dateFormatter.dateFormat = format
return dateFormatter.date(from: self) //here return nil with AM/PM format
}
}

As suggested by #LeoDabus it's better not to create DateFormatter every time (this is very resource-consuming). You can extract it, eg. as a static property.
Here is a simple demo:
class Test {
static let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
return dateFormatter
}()
func parseDateExample() {
let apiTime = "2020-08-27 12:39:32"
if let date = apiTime.toDate(formatter: Self.dateFormatter, format: "yyyy-MM-dd HH:mm:ss") {
print(date)
} else {
print("error")
}
}
}
You can reuse the formatter in your String extension instead of creating a new one every time you call toDate:
extension String {
func toDate(formatter: DateFormatter, format: String) -> Date? {
formatter.dateFormat = format
return formatter.date(from: self)
}
}

Related

Convert Date from one format to another

I trying to convert date from one format to another. But the date in the below code is coming as nil. Can you guys help me out below is the code.
func eventTimeDate() -> Date {
let dtf = DateFormatter()
dtf.timeZone = TimeZone.current
dtf.dateFormat = "yyyy-MM-dd HH:mm:ss z"
/// "2020-05-28 00:20:00 GMT+5:30"
let stringDate = dtf.string(from: self)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss z"
/// nil
let date = dateFormatter.date(from: stringDate)
return date!
}
If you need to convert from one formatted date string to another formatted date string, you can use two DateFormatters: one - an input formatter to convert a String to an intermediary Date object, and then - using an output formatter - convert from Date to String.
func reFormat(from dateStr: String) -> String? {
let fromFormatter = DateFormatter()
fromFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss z"
let toFormatter = DateFormatter()
toFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss z"
guard let date = fromFormatter.date(from: dateStr) else { return nil }
return toFormatter.string(from: date)
}
If you just need to return a Date object, then it's a simpler function using just one DateFormatter:
func toDate(from dateStr: String) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss z"
return formatter.date(from: dateStr)
}
Date object itself has no formatting - it's a pure representation of a date & time, which you can convert to/from using different formatters.
A swift class Date has no format.
In your code your stringDate is in "yyyy-MM-dd HH:mm:ss z" format. If you need to convert String to Date you must use the same format otherwise it will return nil.
If you want to change a format of a string then first convert it to a Swift 'Date' then again convert it to a string with the use of new Formatter.
func eventTimeDate(dateString : String, currentFormat : String, newFormat : String) -> String? {
let currentDateFormatter = DateFormatter()
currentDateFormatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
currentDateFormatter.locale = Locale(identifier: "en_IN")
currentDateFormatter.dateFormat = currentFormat
let date = currentDateFormatter.date(from: dateString)
let newDateFormatter = DateFormatter()
newDateFormatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
newDateFormatter.locale = Locale(identifier: "en_IN")
newDateFormatter.dateFormat = newFormat
if let date = date {
let newDateString = newDateFormatter.string(from: date)
return newDateString
}
return nil
}
You have three problems in your code. First when parsing a fixed date format you should always set the date formatter's locale to "en_US_POSIX". Second you need to escape the GMT of your date string. Last but not least important you need to fix your timezone string which it is missing the leading zero for your timezone hour:
let dateStr = "2020-05-28 00:20:00 GMT+5:30"
let formatter = DateFormatter()
// set the date formatter's locale to "en_US_POSIX"
formatter.locale = .init(identifier: "en_US_POSIX")
// escape the GMT of your date string
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss 'GMT'Z"
// add the leading zero for your timezone hour
let string = dateStr.replacingOccurrences(of: "(GMT[+-])(\\d:)", with: "$10$2", options: .regularExpression)
if let date = formatter.date(from: string) {
print(date) // "2020-05-27 18:50:00 +0000\n"
}

Swift how to convert date format [duplicate]

This question already has answers here:
Date Format in Swift
(24 answers)
Closed 2 years ago.
I have a date of type date and has a format "yyyy-MM-dd HH:mm:ss" and I would like to convert it to "yyyy-MM-dd". I am not sure how to achieve this since the date is of type Date.
Example :
let dateComponents: Date? = dateFormatterGet.date(from: "2019-03-11 17:01:26")
Required output :
Date object of format type "yyyy-MM-dd"
It is important to note that I have only date objects and no string.
You have a date of type String, not Date.
You use one DateFormatter to convert it to Date (check that the DateFormatter doesn't return nil).
Then you use another DateFormatter to convert the Date to a string.
Please don't use "dateComponents" as a variable name. You never, ever touch date components in your code. And you don't need to specify the type, just "let date = ..." or better "if let date = ..." checking for nil.
you can use like this:
let now = Date().UTCToLocalDateConvrt(format: "yyyy-MM-dd HH:mm:ss",convertedFormat : "yyyy-MM-dd")
put below function in Date extension class:
extension Date {
func UTCToLocalDateConvrt(format: String,convertedFormat: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let timeStamp = dateFormatter.string(from: self)
dateFormatter.dateFormat = convertedFormat
guard let date = dateFormatter.date(from: timeStamp)else{
return Date()
}
return date
}
}
func formatDate(yourDate: String) -> String { // "yyyy-MM-dd HH:mm:ss"
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss" // here you can change the format that enters the func
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "yyyy-MM-dd" // here you can change the format that exits the func
if let date = dateFormatterGet.date(from: yourDate) {
return dateFormatterPrint.string(from: date)
} else {
return nil
}
}
use it like this:
formatDate(yourDate: "2019-03-11 17:01:26")
it will return an optional string, that can be nil, make sure you are safety unwrap it (if let , guard let)
answer based on link

Converting a 24 hour format date string to Date and it does not match

I am converting this 24 hour format string "2019-01-10 21:00:40" to a Date object but what I am getting is this 2019-01-10 13:00:40. I am using the format yyyy-MM-dd HH:mm:ss to convert the string to date object. What seems to be the problem here?
I am using this String Extension to convert string to date:
func toDateWithFormat(_ format:String) -> Date{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
guard let date = dateFormatter.date(from: self) else {
fatalError("ERROR: Date conversion failed due to mismatched format.")
}
return date
}
This is happening due to different time zone. you have to add the time zone into the date.
Use this method to converting your timestamp to date
class func timeStampToDate(_timestamp : String, _dateFormat : String) -> String{
var LOCAL_TIME_ZONE: Int { return TimeZone.current.secondsFromGMT() }
var date = Date(timeIntervalSince1970: TimeInterval(_timestamp)!)
date += TimeInterval(truncating: LOCAL_TIME_ZONE as NSNumber)
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "GMT") //Set timezone that you want
dateFormatter.locale = NSLocale.current
dateFormatter.dateFormat = _dateFormat //Specify your format that you want
let strDate = dateFormatter.string(from: date)
return strDate
}
And when you get the strDate from this method. convert to a date object. you will get the currect date object

Getting wrong time from dateformatter [duplicate]

This question already has answers here:
Dateformatter gives wrong time on conversation [duplicate]
(4 answers)
Closed 5 years ago.
I'm converting date fields from a XML file and these dates are stored in "yyyyMMddHHmmss" format. When I use date function of DateFormmater, I'm not getting the correct time. So for dateString "20150909093700", it returns "2015-09-09 13:37:00 UTC" instead of "2015-09-09 09:37:00". I'm doing this conversion before storing inside Core Data NSDate fields.
This is my code :
static func stringToDate(DateString dateString: String) -> NSDate? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMddHHmmss"
dateFormatter.locale = Locale.init(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "EST")
if let date = dateFormatter.date(from: dateString) {
return date as NSDate?
}
return nil
}
#user30646 -- see if this makes sense. Using your exact function:
func stringToDate(DateString dateString: String) -> NSDate? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMddHHmmss"
dateFormatter.locale = Locale.init(identifier: "en_US_POSIX")
dateFormatter.timeZone = TimeZone(abbreviation: "EST")
if let date = dateFormatter.date(from: dateString) {
return date as NSDate?
}
return nil
}
let dateString = "20150909093700"
let returnedDate = stringToDate(DateString: dateString)
print("Date without formatting or Time Zone: [", returnedDate ?? "return was nil", "]")
let dFormatter = DateFormatter()
dFormatter.timeZone = TimeZone(abbreviation: "EST")
dFormatter.dateStyle = .full
dFormatter.timeStyle = .full
print("Result with formatting and Time Zone: [", dFormatter.string(from: returnedDate as! Date), "]")
You are getting the "correct time" ... you just think you're not because you're looking at the wrong string representation of that date/time.

UIDatePicker - DateFormatter is returning the day after the one selected in the picker

I have a function that returns the day selected in the
I have this function that is supposed to return the date in the picker as a string but it returns the day after the one selected.. I did a test and the NSDate object seems to be ok. Not sure what I'm doing wrong here.
func dateformatterDate(date: NSDate) -> NSString
{
var dateFormatter: NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy"
dateFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
return dateFormatter.stringFromDate(date)
}
Xcode 8.3.1 • Swift 3.1
The problem is that the date picker uses localtime and you are converting it to string using UTC time. Try like this:
extension Formatter {
static let date = DateFormatter()
}
extension Date {
var customDate: String {
Formatter.date.dateFormat = "MM-dd-yyyy"
return Formatter.date.string(from: self)
}
}
Date().customDate // "04-14-2017"

Resources