Reputation: 4578
I am trying to parse a string I return from a MySQL Date
datatype as a date locally. However everytime I try to parse it with a DateFormatter()
in Swift 3, the result date is two days off.
Here is an example of the date string returned from the server:
"Sat Dec 31 2016 00:00:00 GMT-0800 (PST)"
I try to use the DateFormatter()
to capture that information in the following format string:
let DatFormatServerTwo = "EEE MMM dd yyyy HH':'mm':'ss zzzZ '('zzz')'"
Then I use it like this:
static func stringDateToDateTwo(dateString: String, timeZone: TimeZone = TimeZone.current) -> Date {
dateFormatter.dateFormat = DateFormatServerTwo
dateFormatter.timeZone = timeZone
return dateFormatter.date(from: dateString) ?? Date()
}
where dateFormatter
is assigned to a DateFormatter()
I think the problem is that there is an offset with the timezone and I am not capturing that information properly. I get the desired date by chopping off parts of the date string namely as soon as the TimeZone stuff enters into the picture. I don't want to do that everytime though because it is messy.
Here is how I chop the string to get the date that I want from the server:
var holidayDateArray = holidayDate.characters.split{$0 == " "}.map(String.init)
var count = 0
var newString = ""
for substring in holidayDateArray {
if count < 5 {
newString.append(substring)
} else {
break
}
count += 1
}
And then I format like this:
static let DateFormatServerTwo = "EEEMMMddyyyyHH':'mm':'ss"
Upvotes: 1
Views: 634
Reputation: 318884
One issue is there is no format specifier for a timezone in the format GMT-XXXX
. There is one for GMT-XX:XX
but you don't have that format. So this solution is to treat the GMT
as a literal and just parse the -XXXX
part using the Z
specifier. The end result is the same.
Also note there is no need to quote punctuation, just letters that are to be treated literally. There is also no need to set the formatter's timezone since you will be getting timezone info from the date string.
There is no need to process the string at all. Just use the correct format:
let str = "Sat Dec 31 2016 00:00:00 GMT-0800 (PST)"
let fmt = DateFormatter()
fmt.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z (z)"
let dt = fmt.date(from:str)
This gives the correct result for dt
for the given string.
Upvotes: 2
Reputation: 3556
Try the following in a Playground:
let str = "Sat Dec 31 2016 00:00:00 GMT-0800 (PST)"
let fmt = DateFormatter()
fmt.dateFormat = "EEE MMM dd yyyy HH':'mm':'ss zzzZ '('zzz')'"
let dt = fmt.date(from:str)
You will notice that the date is nil
.
If you remove the extra timezone information from the date string, and format the date formatter string accordingly:
let str = "Sat Dec 31 2016 00:00:00 -0800"
let fmt = DateFormatter()
fmt.dateFormat = "EEE MMM dd yyyy HH':'mm':'ss ZZZZ"
let dt = fmt.date(from:str)
You'll get: Dec 31, 2016, 1:30 PM
Incidentally, you don't need the quotes around the colons in the date format. So you can actually have the date format as:
fmt.dateFormat = "EEE MMM dd yyyy HH:mm:ss ZZZZ"
If the date string is consistent in how the date is laid out, you can easily remove the GMT and time zone within the quotes by doing something like:
let str = "Sat Dec 31 2016 00:00:00 GMT-0800 (PST)"
let newStr = str.replacingOccurrences(of:"GMT", with:"").replacingOccurrences(of:"\\(.*?\\)", with:"", options: String.CompareOptions.regularExpression)
let fmt = DateFormatter()
fmt.dateFormat = "EEE MMM dd yyyy HH:mm:ss ZZZZ"
let dt = fmt.date(from:newStr)
When done this way, the date does appear to come through correctly. Let me know if your results are different when you try this in a Playground.
Upvotes: 0