Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

SPM Prep - Convert "WordPress JSON date" logic from Objective-C to Swift#758

Merged
mokagio merged 13 commits intotrunkfrom
mokagio/rfc-3339
Mar 21, 2024
Merged

SPM Prep - Convert "WordPress JSON date" logic from Objective-C to Swift#758
mokagio merged 13 commits intotrunkfrom
mokagio/rfc-3339

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.

@mokagio mokagio enabled auto-merge March 20, 2024 01:51
@mokagio mokagio requested a review from crazytonyli March 20, 2024 01:51
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.

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

@mokagio mokagio requested a review from crazytonyli March 21, 2024 07:00
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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants