Getting date from string with HH:mm time format is not working for Japanese language and region in swift - ios

I am trying to get date from string using DateFormatter(). My phone is set to Japan region, Language to Japanese and time to 12 hour format. My app is set to 24 hour format so that user can select time from custom picker in 24 hour format. The Date string is "11 3月, 2019 15:35". The date formatter is "MMM dd, yyyy HH:mm". But it is not working and returns nil always.
According to iOS 10 bug? NSDate hour description with Japan region and 24-Hour Time off
If i use "MMM dd, yyyy KK:mm" as date format then it works only if the time in string is bellow 12:00. Here is my code below.
static func dateFrom(string: String, timeString: String) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.short
dateFormatter.timeZone = NSTimeZone.local
dateFormatter.locale = NSLocale.current
/// Check time format
var timeFormat = "KK:mm"
if timeString.containsIgnoringCase(find: AppConstants.am.localizedStringWith()) || timeString.containsIgnoringCase(find: AppConstants.pm.localizedStringWith()) {
timeFormat = "h:mm a"
}
/// Check date for MMDD format
dateFormatter.dateFormat = "MMM dd, yyyy \(timeFormat)"
if let date = dateFormatter.date(from: string) {
return date
}
/// Check date for DDMM format
dateFormatter.dateFormat = "dd MMM, yyyy \(timeFormat)"
if let date = dateFormatter.date(from: string) {
return date
}
return dateFormatter.date(from: string)
}
Please let me know if you found solution for it.

Try setting the calendar on your date formatter:
dateFormatter.calendar = .gregorian

Related

I can't convert iso8601 to string swift

I have a string coming from API and its format will be like this
"2021-03-01T15:00:00+07:00"
so i try to convert this string to date using this code
// string to date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let date = dateFormatter.date(from: isoDate)!
print("date from date Formatter = \(date)")
// convert date back to string
dateFormatter.dateFormat = "EEEE HH:mm"
let dateString = dateFormatter.string(from: date)
print("date string \(dateString)")
return dateString
The result that I expect is -> "2021-03-01 08:00:00 +0000", "Monday 15:00"
When I try this on playground the result is what I want, but when I try this on my project the result is
-> "1478-03-01 08:00:00 +0000", "Sunday 14:42"
How can I change the result to the same as i expect? Thanks
It looks like you are using a different calendar than you expect in your project (buddhist maybe?) and I guess this is because you haven't set one explicitly so it's the one set in System Preferences.
So if you for some reason do not want to use the users current calendar (and locale and time zone) you need to set those properties on your date formatter instance
//Gregorian calendar
dateFormatter.calendar = Calendar.init(identifier: .gregorian)
//UTC time zone
dateFormatter.timeZone = TimeZone(identifier: "UTC")
//English locale
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
This will give you the expected output.
Note that the playground is a bit inconsequent in what it uses and it seems to be a mix of what we have set in our System preferences and hardcoded values.

DateFormater error only when running on iOS 13

I have a function to convert string to date format. This function works as expected on iOS 12 but on iOS 13. I get this error:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
Here is my code:
func ConvertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var dateObj:Date!
dateObj = dateFormatter.date(from: timeDate)
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +zzzz"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
var timeObj:Date!
timeObj = timeFormatter.date(from: timeDate)
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00")
let timef = "\(timeFormatter.string(from: timeObj!))"
let Date = "\(dateFormatter.string(from: dateObj!))"
}
Please change your dateformat and use "yyyy-MM-dd HH:mm:ss Z" and try.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
For more details please visit https://nsdateformatter.com/
If you are trying to convert string time which in 24 hours format (Ex 15:25:00 / HH:mm:ss) then enable your device 24-Hour Time option. It might solve the issue in IOS 13.3
You may find the option here
Settings -> General -> Date & Time
There are many issues with your code. There is no reason to create two Date objects from one string. Just parse the original string once. Then you can create your date string and time string with the desired formats from that one date.
You should also use the special locale of en_US_POSIX when parsing fixed format date strings. There is also no need to set a timezone when parsing the original date string. The string provides its own timezone. The +0000 means it is UTC time.
You may not want to provide a timezone when converting the date to your final strings either. Most likely you want strings in the user's locale timezone, not some hardcoded timezone.
Here's your code cleaned up a lot:
func convertDateAndTimeFormat2() {
let timeDate = "2019-09-24 15:00:00 +0000"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
if let dateObj = dateFormatter.date(from: timeDate) {
dateFormatter.dateFormat = "EEEE, MMM d, yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HH:mm"
timeFormatter.timeZone = TimeZone(abbreviation: "GMT+3:00") // Probably not needed
let timef = timeFormatter.string(from: dateObj)
let datef = dateFormatter.string(from: dateObj)
print("Date: \(datef), time: \(timef)")
}
}
convertDateAndTimeFormat2()
Output:
Date: Tuesday, Sep 24, 2019, time: 18:00

Swift date from string always returns nil

I have a date that is a string that looks like this:
Apr 25 2018 12:00AM
What I am trying to do is convert this date format to yyyy-MM-dd and then convert it back to a string, I have a tried the following:
let formatter = DateFormatter()
formatter.dateFormat = "M dd yyyy h:mm A"
let SLAIssuedFinalGradingDate = formatter.date(from: tableDic["SLAIssuedFinalGradingDate"] as! String)
formatter.dateFormat = "yyyy-MM-dd"
let SLAIssuedFinalGradingDateString = formatter.string(from: SLAIssuedFinalGradingDate!)
But SLAIssuedFinalGradingDate always returns nil, what am I doing wrong?
Your dateFormat for Apr 25 2018 12:00AM is not right. You are using M dd yyyy h:mm A, but format would be MMM dd yyyy hh:mma.
Use this link to check date format.
Code Should be:
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "MMM dd yyyy hh:mma"
let SLAIssuedFinalGradingDate = formatter.date(from: tableDic["SLAIssuedFinalGradingDate"] as! String)
formatter.dateFormat = "yyyy-MM-dd"
let SLAIssuedFinalGradingDateString = formatter.string(from: SLAIssuedFinalGradingDate!)
Your dateFormat string is incorrect. A DateFormatter will always return nil if the dateFormat string does not match the supplied string.
"MMM dd yyyy hh:mma"
This is what you're after. I suggest you review a DateFormatter cheat sheet and familiarise yourself with the symbols.

How to get the day of the week from a date in Swift

I can print the date in this format: Mon, Mar 19, 2018, but I am not sure how to get the Day of the week in this format.
Please help
let dateFormatter = DateFormatter()
// uncomment to enforce the US locale
// dateFormatter.locale = Locale(identifier: "en-US")
dateFormatter.setLocalizedDateFormatFromTemplate("EEE MMM d yyyy")
print(dateFormatter.string(from: Date())) // "Tue, Mar 20, 2018" for en-US locale
Note that I am using a template to provide the exact format, therefore the format will be properly localized in every language.
To get the day for a particular date:
let customDateFormatter = DateFormatter()
print(customDateFormatter.weekdaySymbols[Calendar.current.component(.weekday, from: Date())])
// "Wednesday"
source
Rather than needing to spell out a date format. I would simplify it further to:
dateFormatter.dateStyle = .full
Or if you just want the day:
dateFormatter.dateFormat = "EEEE"
With swift 4
func timeStamp()->String {
let dateFormater = DateFormatter()
dateFormater.locale = Locale(identifier: "en-US")
dateFormater.setLocalizedDateFormatFromTemplate("EEE MMM d yyyy")
return dateFormatter.string(from: Date())
}
Use it.
let getTimeStamp = timeStamp()
print(getTimeStamp)
dateFormatter.dateFormat = "EEE, MMM dd, yyyy"
For dat of week in alphabets, you use EEEE or EEE similar to MMM & yyyy for month year.
The best way to change your date is follow this method.
func ChangeDateFormat(date:String,FromFormat: String, ToFormat: String) -> String {
let dateFormatter1 = DateFormatter()
dateFormatter1.dateFormat = FromFormat
let myDate = dateFormatter1.date(from: date)
dateFormatter1.dateFormat = ToFormat
if(myDate != nil){
let Date = dateFormatter1.string(from: myDate!)
return Date
}
else{
return ""
}
}
and then you can use this method like
String(ChangeDateFormat(date: StartDate, FromFormat: "yyyy-MM-dd hh:mm:ss a", ToFormat: "MMM d, yyyy"))
You can pass your date format in which format do you want in your case it should be
String(ChangeDateFormat(date: StartDate, FromFormat: "Pass your date format", ToFormat: "EEE MMM d, yyyy"))

How to parse String date to date object in ios swift?

I am parsing date from server into a custom format :-
This is the date :- "8/9/2017 3:58:00 AM" but it is not parsing into Date object using this format "MM/dd/yyyy hh:mm:ss a" because obviously the month, day and hour is single digit
As per my knowledge it should parse automatically because Android's DateFormat parses the same date.
This is the code snippet i am using :-
func getDateString(_ dateString:String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "M/dd/yyyy hh:mm:ss a"
let date = dateFormatter.date(from: dateString)
dateFormatter.dateFormat = "dd MMM yyyy"
return dateFormatter.string(from: date!)
}
This function is returning null
Your code should work, although you should also add some error-checking.
Try this (it will run in a Playground):
// returns an empty string "" if the date format is invalid
func getDateString(_ dateString:String) -> String {
var strResult = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "M/dd/yyyy hh:mm:ss a"
if let date = dateFormatter.date(from: dateString) {
dateFormatter.dateFormat = "dd MMM yyyy"
strResult = dateFormatter.string(from: date)
}
return strResult
}
let dateString = getDateString("8/9/2017 3:58:00 AM")
print(dateString) // prints "09 Aug 2017"
If you change your "source" string to an invalid date/time - such as changing the month from 8 to 18 or the hour from 3 to 13 - you will see the returned value is an empty string.

Resources