-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SPM Prep - Convert "WordPress JSON date" logic from Objective-C to Swift #758
Changes from 6 commits
360a0a2
50916f6
51f0616
71fa951
b0e6dcf
b0ed585
5686c93
31292ae
f3bc0a0
ca4b342
e4f8fba
2a90451
4ab30ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import Foundation | ||
|
||
extension NSDate { | ||
|
||
@objc | ||
static let rfc3339DateFormatter = DateFormatter.rfc3339Formatter | ||
|
||
/// Parses a date string | ||
/// | ||
/// Dates in the format specified in http://www.w3.org/TR/NOTE-datetime should be OK. | ||
/// The kind of dates returned by the REST API should match that format, even if the doc promises ISO 8601. | ||
/// | ||
/// Parsing the full ISO 8601, or even RFC 3339 is more complex than this, and makes no sense right now. | ||
/// | ||
/// - Warning: This method doesn't support fractional seconds or dates with leap seconds (23:59:60 turns into 23:59:00) | ||
// | ||
// Needs to be `public` because of the usages in the Objective-C code. | ||
@objc(dateWithWordPressComJSONString:) | ||
public static func with(wordPressComJSONString jsonString: String) -> Date? { | ||
self.rfc3339DateFormatter.date(from: jsonString) | ||
} | ||
|
||
@objc(WordPressComJSONString) | ||
public func wordPressComJSONString() -> String { | ||
NSDate.rfc3339DateFormatter.string(from: self as Date) | ||
} | ||
} | ||
|
||
extension DateFormatter { | ||
|
||
static let rfc3339Formatter: DateFormatter = { | ||
let formatter = DateFormatter() | ||
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" | ||
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone | ||
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale | ||
return formatter | ||
}() | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seemed neater to define this pre-configured |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ private func decodePost(from object: AnyObject) async throws -> RemotePost { | |
|
||
private func makeParameters<T: Encodable>(from value: T) throws -> [String: AnyObject] { | ||
let encoder = JSONEncoder() | ||
encoder.dateEncodingStrategy = .formatted(NSDate.rfc3339DateFormatter()) | ||
encoder.dateEncodingStrategy = .formatted(NSDate.rfc3339DateFormatter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forgot about the API breakage concerns when making this a Turns out there is one use of this outside the library, in the WordPress iOS tests. I'll update the code reintroducing the |
||
let data = try encoder.encode(value) | ||
let object = try JSONSerialization.jsonObject(with: data) | ||
guard let dictionary = object as? [String: AnyObject] else { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,7 @@ final class CommentServiceRemoteRESTTests: RemoteTestCase, RESTTestable { | |
XCTAssertEqual(comment.authorEmail, "[email protected]") | ||
XCTAssertEqual(comment.authorUrl, "author URL") | ||
XCTAssertEqual(comment.authorIP, "000.0.00.000") | ||
XCTAssertEqual(comment.date, NSDate(wordPressComJSONString: "2021-08-04T07:58:49+00:00") as Date) | ||
XCTAssertEqual(comment.date, NSDate.with(wordPressComJSONString: "2021-08-04T07:58:49+00:00")) | ||
XCTAssertEqual(comment.link, "comment URL") | ||
XCTAssertEqual(comment.parentID, nil) | ||
XCTAssertEqual(comment.postID, NSNumber(value: 1)) | ||
|
@@ -91,7 +91,7 @@ final class CommentServiceRemoteRESTTests: RemoteTestCase, RESTTestable { | |
XCTAssertEqual(comment.authorEmail, "[email protected]") | ||
XCTAssertEqual(comment.authorUrl, "author URL") | ||
XCTAssertEqual(comment.authorIP, "000.0.00.000") | ||
XCTAssertEqual(comment.date, NSDate(wordPressComJSONString: "2021-08-04T07:58:49+00:00") as Date) | ||
XCTAssertEqual(comment.date, NSDate.with(wordPressComJSONString: "2021-08-04T07:58:49+00:00")) | ||
XCTAssertEqual(comment.link, "comment URL") | ||
XCTAssertEqual(comment.parentID, nil) | ||
XCTAssertEqual(comment.postID, NSNumber(value: 1)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
@testable import WordPressKit | ||
import XCTest | ||
|
||
// This is an incomplete test for implementing RFC 3339. | ||
// It's purpose is to ensure our code "works". | ||
// | ||
// See also: | ||
// | ||
// - https://datatracker.ietf.org/doc/html/rfc3339 | ||
class NSDateRFC3339Tests: XCTestCase { | ||
|
||
func testDateFormatterConfiguration() throws { | ||
let rfc3339Formatter = try XCTUnwrap(NSDate.rfc3339DateFormatter) | ||
|
||
XCTAssertEqual(rfc3339Formatter.timeZone, TimeZone(secondsFromGMT: 0)) | ||
XCTAssertEqual(rfc3339Formatter.locale, Locale(identifier: "en_US_POSIX")) | ||
XCTAssertEqual(rfc3339Formatter.dateFormat, "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ") | ||
} | ||
|
||
func testValidRFC3339DateFromString() { | ||
XCTAssertEqual( | ||
NSDate.with(wordPressComJSONString: "2023-03-19T15:00:00Z"), | ||
Date(timeIntervalSince1970: 1_679_238_000) | ||
) | ||
} | ||
|
||
func testInvalidRFC3339DateFromString() { | ||
XCTAssertNil(NSDate.with(wordPressComJSONString: "2024-01-01")) | ||
} | ||
|
||
func testInvalidDateFromString() { | ||
XCTAssertNil(NSDate.with(wordPressComJSONString: "not a date")) | ||
} | ||
|
||
func testValidRFC3339StringFromDate() { | ||
XCTAssertEqual( | ||
NSDate(timeIntervalSince1970: 1_679_238_000).wordPressComJSONString(), | ||
// Apparently, NSDateFormatter doesn't offer a way to specify Z vs +0000. | ||
// This might go all the way back to the ISO 8601 and RFC 3339 specs overlap. | ||
"2023-03-19T15:00:00+0000" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you tried to put a single quote There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW, this is one of the reasons I think we should avoid using standard names in function names. It's pretty difficult to ensure conformance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are being really strict here, this test case should fail, because the output is not in RFC3339 time format. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @crazytonyli ! I didn't noticed that 🤦♂️ I tried locally and it does the job at returning But ☝️ other tests that deal with API and dates fail. I think maybe we should leave it like this for the moment, and update / investigate later on. After all, the format the code uses right now is the "original" one. What do you think? |
||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are going to make breaking changes, I guess we have an option of getting rid of the
NSDate
extension above and renaming thisrfc3339Formatter
to be something likewordPressComDateFormatter
.