Skip to content
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

Merged
merged 13 commits into from
Mar 21, 2024

Conversation

mokagio
Copy link
Contributor

@mokagio mokagio commented Mar 20, 2024

Description

This logic will need to live in the "Core API" package and the Jetpack/WordPress specific objects. It could have been extracted into a dedicated package, but for the sake of simplicity, it's been converted to Swift so it can live in "Core API".

Notice that:

  1. I first added unit tests (smoke tests, more like) to ensure consistent behavior between implementation
  2. The Objective-C dateWithWordPressComJSONString: method was translated by the compiler into NSDate(wordPressComJSONString:). In my conversion, I made it .with(wordPressComJSONString:). I think it would have been possible to define a convenience initializer to keep the API the same, but the approach I took seemed cleaner at the time. The method is only used internally to WordPressKit (see commit details) so, while it might count as a breaking change, I'm tempted to ignore it. Let me know if you think I'm being slack, or if it sounds like a reasonable compromise to move ahead without distractions.

Testing Details

See the new unit tests.

Next up

Basically, cherry-pick the work from #738 but in a neat and reviewable order:

  • Move files into Sources/ and Tests/
  • Introduce Bundle helper that differentiates between SPM and CocoaPods installations
  • Isolate core API objects in dedicated package
  • Then, new ground, define protocol abstraction to work around the Objective-C / Swift inter-op issue

See also, #756 which is related to the SPM work but independent from this one.


  • Please check here if your pull request includes additional test coverage. — N.A.
  • I have considered if this change warrants release notes and have added them to the appropriate section in the CHANGELOG.md if necessary. — N.A.

Comment on lines 29 to 38
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
}()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed neater to define this pre-configured DateFormatter in a DateFormatter extension, rather than NSDate.

@@ -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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot about the API breakage concerns when making this a static let. 🤦‍♂️

Turns out there is one use of this outside the library, in the WordPress iOS tests.

I'll update the code reintroducing the static func but marking it as deprecated. This way, we can remove it at the next "serious" breaking change occasion.

@crazytonyli
Copy link
Contributor

Let me know if you think I'm being slack, or if it sounds like a reasonable compromise to move ahead without distractions.

My preference would be religiously following semantic versioning. There is no really difference in publishing 15.0 vs 14.2. Plus, when releasing a major version, you get to further clean up the codebase, i.e. moving extension NSDate to extension Date, removing NSDate.rfcXxxDateFormatter and using the one in DateFormatter instead, etc.


extension DateFormatter {

static let rfc3339Formatter: DateFormatter = {
Copy link
Contributor

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 this rfc3339Formatter to be something like wordPressComDateFormatter.

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried to put a single quote ' around the Z in the format: "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 2023-03-19T15:00:00Z as I originally expected.

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?

@mokagio
Copy link
Contributor Author

mokagio commented Mar 20, 2024

My preference would be religiously following semantic versioning

Good point. It also makes the decision making simpler "is this a breaking change (regardless of whether the API is public but with no consumers)" "yes?" "new major version."

Boom 🚀

@mokagio
Copy link
Contributor Author

mokagio commented Mar 20, 2024

@crazytonyli thanks again for the suggestions. I implemented them in #759

@@ -2,7 +2,7 @@

Pod::Spec.new do |s|
s.name = 'WordPressKit'
s.version = '14.1.0'
s.version = '15.0.0-beta.1'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we make version change in a dedicated PR along side with moving changelog content. Do you intend to make a release once this PR is merged?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right. I just wanted to put a line in the sand for the breaking change.

@mokagio mokagio merged commit 118fd9a into trunk Mar 21, 2024
9 checks passed
@mokagio mokagio deleted the mokagio/rfc-3339 branch March 21, 2024 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants