I need to parse javascript dates in swift. Since dates are already stored in some database I cannot change the format of them. I just need to parse them into correct Dates in swift.
Below are examples results of javascript's toString() function. It depends on Locale/Language
// js
new Date().toString()
'Tue Jun 01 2021 14:11:27 GMT+0900 (JST)'
'Tue Jun 01 2021 14:03:45 GMT+0900 (Japan Standard Time)'
'Mon May 31 2021 17:38:31 GMT+0800 (中国標準時)'
'Mon May 31 2021 19:25:37 GMT+0930 (オーストラリア中部標準時)'
How can I parse this in Swift DateFormatter?
I have tried this:
// swift
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z (zzz)"
Date-> String conversion looks correct but String -> Date does not work
// swift
dateFormatter.string(from: Date())
> "Tue Jun 01 2021 14:11:27 GMT+0900 (JST)"
dateFormatter.date(from: "Tue Jun 01 2021 14:11:27 GMT+0900 (JST)")
> nil
Any help is highly appreciated.
As mentioned in the comments by #Sweeper - The timezone name part is implementation dependent - which can be confirmed from the docs
Optionally, a timezone name consisting of:
space
Left bracket, i.e. "("
An implementation dependent string representation of the timezone, which might be an abbreviation or full name (there is no standard for names or abbreviations of timezones), e.g. "Line Islands Time" or "LINT"
Right bracket, i.e. ")"
So we need to - remove the part within parentheses at the end and parse the rest - as mentioned by #Joakim Danielson
Taking this into account, we can do it like this -
extension String {
static private var jsDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
return formatter
}()
func parsedDate() -> Date? {
let input = self.replacingOccurrences(of: #"\(.*\)$"#, with: "", options: .regularExpression)
return String.jsDateFormatter.date(from: input)
}
}
Tests
func testJSDateParsing() {
[
"Tue Jun 01 2021 14:11:27 GMT+0900 (JST)",
"Tue Jun 01 2021 14:03:45 GMT+0900 (Japan Standard Time)",
"Mon May 31 2021 17:38:31 GMT+0800 (中国標準時)",
"Mon May 31 2021 19:25:37 GMT+0930 (オーストラリア中部標準時)",
].forEach({
if let date = $0.parsedDate() {
print("Parsed Date : \(date) for input : \($0)")
}
else {
print("Failed to parse date for : \($0)")
}
})
}
Output
Parsed Date : 2021-06-01 05:11:27 +0000 for input : Tue Jun 01 2021 14:11:27 GMT+0900 (JST)
Parsed Date : 2021-06-01 05:03:45 +0000 for input : Tue Jun 01 2021 14:03:45 GMT+0900 (Japan Standard Time)
Parsed Date : 2021-05-31 09:38:31 +0000 for input : Mon May 31 2021 17:38:31 GMT+0800 (中国標準時)
Parsed Date : 2021-05-31 09:55:37 +0000 for input : Mon May 31 2021 19:25:37 GMT+0930 (オーストラリア中部標準時)
Related
I am working with a series of string representations of timestamps returned by time.asctime() in Python. The documentation states:
Convert a tuple or struct_time representing a time as returned by gmtime() or localtime() to a string of the following form: 'Sun Jun 20 23:21:05 1993'. The day field is two characters long and is space padded if the day is a single digit, e.g.: 'Wed Jun 9 04:26:40 1993'.
I've referenced Unicode Technical Standards to determine how I can instruct an instance of Swift's DateFormatter how to interpret the string and create a Date.
The UTS is very clear, but my Date object still unwraps to nil:
let dateAsString = measurement[2]
print("Date as string: \(dateAsString)")
let df = DateFormatter()
df.dateFormat = "E MMM dd HH:mm:ss y"
let date = df.date(from: dateAsString)
print("Date: \(String(describing: date))")
Output:
Date as string: Thu Oct 20 17:53:06 2022
Date: nil
Date as string: Thu Oct 20 17:53:06 2022
Date: nil
Date as string: Thu Oct 20 17:53:16 2022
Date: nil
When printing dateAsString to console output, I did not notice that there is a single trailing whitespace after the year. Adjusting the Unicode format string to the following solved the problem:
df.dateFormat = "EEE MMM d HH:mm:ss y " // <- observe the extra space
I'm trying to convert time strings that look like the following into Swift Dates:
Sun 11:00a PDT
Sun 7:00p PDT
Mon 11:00a PDT
Mon 7:00p PDT
Tue 11:00a PDT
Tue 7:00p PDT
Wed 10:00a PDT
Wed 7:00p PDT
etc
These represent opening and closing times for various businesses.
While the Date object conversion does succeed (meaning the returned optional is not nil,) the times are incorrect. Here is my code:
let dateFormatter = DateFormatter()
let shortDays = ["Sun-","Mon-","Tue-","Wed-","Thu-","Fri-","Sat-"]
dateFormatter.dateFormat = "E HH:mmaaaaa zzz"
var daysCounter = 0
for hours in hoursArray {
let dayHours = shortDays[daysCounter]+hours
//split hours
let splitHours = dayHours.split(separator: "-")
//print(String(splitHours[0]+" "+splitHours[1]+" "+timezone))
//print(String(splitHours[0]+" "+splitHours[2]+" "+timezone))
//create an opening time date optional
let openingOpt = dateFormatter.date(from: String(splitHours[0]+" "+splitHours[1]+" "+timezone))
//create a closing time date optional
let closingOpt = dateFormatter.date(from: String(splitHours[0]+" "+splitHours[2]+" "+timezone))
//unwrap those optionals
guard let opening = openingOpt else{
//deal with "closed"
print("Something happened with unwrapping opening time optional: \(String(describing: openingOpt))")
return
}
guard let closing = closingOpt else{
//deal with "closed"
print("Something happened with unwrapping closing time optional: \(String(describing: closingOpt))")
return
}
self.fullHours.append(opening)
self.fullHours.append(closing)
daysCounter += 1
}
for hours in fullHours{
print(hours)
}
However, when I print the converted dates using the for loop above, I get incorrect results. Some of the results are fine; for example, the closing times of 7pm seem to convert properly. To the left are the printed Date objects, to the right are the original inputs in parenthesis:
2000-01-02 07:00:00 +0000 (Sun 11:00a PDT)
2000-01-02 19:00:00 +0000 (Sun 7:00p PDT)
2000-01-03 07:00:00 +0000 (Mon 11:00a PDT)
2000-01-03 19:00:00 +0000 (Mon 7:00p PDT)
2000-01-04 07:00:00 +0000 (Tue 11:00a PDT)
2000-01-04 19:00:00 +0000 (Tue 7:00p PDT)
2000-01-05 07:00:00 +0000 (Wed 10:00a PDT)
2000-01-05 19:00:00 +0000 (Wed 7:00p PDT)
2000-01-06 07:00:00 +0000 (Thu 11:00a PDT)
2000-01-06 19:00:00 +0000 (Thu 7:00p PDT)
2000-01-07 07:00:00 +0000 (Fri 11:00a PDT)
2000-01-07 19:00:00 +0000 (Fri 7:00p PDT)
12000-01-01 07:00:00 +0000 (Sat 11:00a PDT)
2000-01-01 19:00:00 +0000 (Sat 7:00p PDT)
In particular, why is Saturday being converted to the year 12000? Why does Wednesday at 10am still show at 7am UTC? I'm confused and lost, and could not find a similar question via search. Any help would be appreciated, thank you!
Note: I am using Xcode 13.0 Beta 5, developing for iOS 15 beta 5.
Edit: here is the source for the date-time formatting: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
Edit2: Also, I discovered that any time appended with "a" converts to 7am, and any time appended with "p" converts to 7pm. So... ??
The answer was that my format was off. It should have been h:mm, not HH:mm. Thanks to Sweeper for the detail-oriented answer!
This question already has an answer here:
How to format DateFormatter(NSDateFormattter) for Date String
(1 answer)
Closed 5 years ago.
I having a date string:
Wed Mar 25 2017 05:30:00 GMT+0530 (IST)
I want to convert this string to the Date object in Swift 3.
I have referred to Link1, Link 2 and Link 3 for generating the format for this date string but could not get the correct format.
1) If you have string which contains timezone names like IST or GMT differences, then you can use NSDateDetector as explained in this SO post answer:
extension String {
var nsString: NSString { return self as NSString }
var length: Int { return nsString.length }
var nsRange: NSRange { return NSRange(location: 0, length: length) }
var detectDates: [Date]? {
return try? NSDataDetector(types: NSTextCheckingResult.CheckingType.date.rawValue)
.matches(in: self, range: nsRange)
.flatMap{$0.date}
}
}
//your example here
let dateString = "Wed Mar 25 2017 05:30:00 GMT+0530 (IST)"
if let dateDetected = dateString.detectDates?.first {
let date = dateDetected//Mar 25, 2017, 5:30 AM
print(dateDetected)//2017-03-25 00:00:00 +0000 - this is GMT time
}
Mar 25, 2017, 5:30 AM //date converted to local time zone
2017-03-25 00:00:00 +0000 //printed value of GMT time
2) Or if you some how able to remove GMT and IST reference from your string then try this:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEE, MMM d yyyy HH:mm:ss Z"
let date = dateFormatter.date(from: "Wed Mar 25 2017 05:30:00 +0530")!
print(date)
It will give you
Mar 25, 2017, 5:30 AM //date converted to local time zone
2017-03-25 00:00:00 +0000 //printed value of GMT time
var dateString = "Wed, 25 Mar 2017 05:30:00 +0000"
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "E, d MMM yyyy HH:mm:ss Z"
var dateFromString = dateFormatter.date(from: dateString)
print(dateFromString)
I'm trying to format a string from internet time to something more readable.
The input I have is something like: Mon, 27 Apr 2015 20:00:00 +0000
And I'd like to format it into just: Mon, 27 Apr
I'm fairly new to Swift so I don't know the best way to do this.
something like:
let unformattedDateString = "Mon, 27 Apr 2015 20:00:00 +0000"
let dateFormatter = NSDateFormatter()
// input format
dateFormatter.dateFormat = "E, dd MMM yyyy HH:mm:ss Z"
// create NSDate from String
let date = dateFormatter.dateFromString(unformattedDateString)!
// output format
dateFormatter.dateFormat = "E, dd MMM"
// create String from NSDate
let formattedDateString = dateFormatter.stringFromDate(date)
I having a problem when convert String to Date in Blackberry SDK. Please support for me.
This is my code:
String date = "Mon May 09 09:00:00 GMT 2011";
Date formatter = new Date();
formatter.setTime(HttpDateParser.parse(date));
SimpleDateFormat dateFormat = new SimpleDateFormat(formatStr);
string dateString = dateFormat.format(formatter);
purpsoe of the function is format date MMM dd, YYYY.
But after i run the function, it will return result that I unexpected.
Expected: May 09, 2011
UnExpected : Jan,01,1970.
I suspect the "Mon May 09 09:00:00 GMT 2011" is not a supported by HttpDateParser date format. Since the HttpDateParser.parse() does not throw an exception, I guess it simply return 0 in case of an unsupported format.