diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d73eccb..6402b8a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,9 +13,9 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Set Xcode 14.2 + - name: Set Xcode 15 run: | - sudo xcode-select -switch /Applications/Xcode_14.2.app + sudo xcode-select -switch /Applications/Xcode_15.1.app - name: Carthage Bootstrap run: carthage bootstrap --use-xcframeworks diff --git a/Sources/Experiment/ExperimentUser.swift b/Sources/Experiment/ExperimentUser.swift index eebc9ea..6981b28 100644 --- a/Sources/Experiment/ExperimentUser.swift +++ b/Sources/Experiment/ExperimentUser.swift @@ -526,7 +526,7 @@ import Foundation } internal extension ExperimentUser { - + func toDictionary() -> [String:Any] { var data = [String:Any]() data["device_id"] = self.deviceId @@ -543,9 +543,41 @@ internal extension ExperimentUser { data["device_model"] = self.deviceModel data["carrier"] = self.carrier data["library"] = self.library - data["user_properties"] = self.userPropertiesAnyValue - data["groups"] = self.groups - data["group_properties"] = self.groupProperties + + // Convert NSDate objects to ISO 8601 strings in user_properties + if let userProperties = self.userPropertiesAnyValue { + var convertedUserProperties = [String:Any]() + for (key, value) in userProperties { + if let dateValue = value as? Date { + convertedUserProperties[key] = dateValue.iso8601 + } else { + convertedUserProperties[key] = value + } + } + data["user_properties"] = convertedUserProperties + } + + // Convert NSDate objects to ISO 8601 strings in group_properties + if let groupProperties = self.groupProperties { + var convertedGroupProperties = [String:Any]() + for (groupType, groups) in groupProperties { + var convertedGroups = [String:Any]() + for (groupName, properties) in groups { + var convertedProperties = [String:Any]() + for (key, value) in properties { + if let dateValue = value as? Date { + convertedProperties[key] = dateValue.iso8601 + } else { + convertedProperties[key] = value + } + } + convertedGroups[groupName] = convertedProperties + } + convertedGroupProperties[groupType] = convertedGroups + } + data["group_properties"] = convertedGroupProperties + } + return data } @@ -613,3 +645,19 @@ extension ExperimentUser { return context } } + +internal extension Date { + var iso8601: String { + return DateFormatter.iso8601.string(from: self) + } +} + +internal extension DateFormatter { + static let iso8601: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + return formatter + }() +} diff --git a/Tests/ExperimentTests/ExperimentUserTests.swift b/Tests/ExperimentTests/ExperimentUserTests.swift index 7a1f534..0dbfc65 100644 --- a/Tests/ExperimentTests/ExperimentUserTests.swift +++ b/Tests/ExperimentTests/ExperimentUserTests.swift @@ -181,4 +181,51 @@ class ExperimentUserTests: XCTestCase { let user = ExperimentUserBuilder().userProperty("test", value: "test").build() XCTAssertTrue(user != ExperimentUser()) } + + func testUserPropertiesWithDateExtension() { + let date = Date(timeIntervalSince1970: 1619821200) + + let user = ExperimentUserBuilder() + .deviceId("device_id") + .userId("user_id") + .version(nil) + .country("country") + .userProperty("dateUserProperty", value: date) + .build() + + let userData = user.toDictionary() + + if let userProperties = userData["user_properties"] as? [String: Any] { + if let dateUserProperty = userProperties["dateUserProperty"] as? String { + XCTAssertEqual(dateUserProperty, "2021-04-30T22:20:00.000Z") + } else { + XCTFail("dateUserProperty not found or not a string") + } + } else { + XCTFail("user_properties not found or not a dictionary") + } + } + + func testGroupPropertiesWithDateExtension() { + let date = Date(timeIntervalSince1970: 1619821200) + + let user = ExperimentUserBuilder() + .deviceId("device_id") + .userId("user_id") + .version(nil) + .country("country") + .groupProperty("groupType", "groupName", "dateGroupProperty", date.iso8601) + .build() + + let userData = user.toDictionary() + + if let groupProperties = userData["group_properties"] as? [String: Any], + let groupTypeDict = groupProperties["groupType"] as? [String: Any], + let groupNameDict = groupTypeDict["groupName"] as? [String: Any], + let dateGroupProperty = groupNameDict["dateGroupProperty"] as? String { + XCTAssertEqual(dateGroupProperty, "2021-04-30T22:20:00.000Z") + } else { + XCTFail("Unable to access group properties or dateGroupProperty") + } + } }