add open iso8601 date formatter

This commit is contained in:
Ethan Pippin 2022-08-17 14:13:15 -06:00
parent fc7adb746a
commit c675c0de5c
5 changed files with 78 additions and 8 deletions

View File

@ -29,6 +29,10 @@ public struct SessionInfo: Codable, Identifiable {
public var id: String?
/// Gets a value indicating whether this instance is active.
public var isActive: Bool?
/// Gets or sets the last activity date.
public var lastActivityDate: Date?
/// Gets or sets the last playback check in.
public var lastPlaybackCheckIn: Date?
/// This is strictly used as a data transfer object from the api layer.
///
/// This holds information about a BaseItem in a format that is convenient for the client.
@ -57,7 +61,7 @@ public struct SessionInfo: Codable, Identifiable {
public var userName: String?
public var userPrimaryImageTag: String?
public init(additionalUsers: [SessionUserInfo]? = nil, applicationVersion: String? = nil, capabilities: ClientCapabilities? = nil, client: String? = nil, deviceID: String? = nil, deviceName: String? = nil, deviceType: String? = nil, fullNowPlayingItem: BaseItem? = nil, hasCustomDeviceName: Bool? = nil, id: String? = nil, isActive: Bool? = nil, nowPlayingItem: BaseItemDto? = nil, nowPlayingQueue: [QueueItem]? = nil, nowPlayingQueueFullItems: [BaseItemDto]? = nil, nowViewingItem: BaseItemDto? = nil, playState: PlayerStateInfo? = nil, playableMediaTypes: [String]? = nil, playlistItemID: String? = nil, remoteEndPoint: String? = nil, serverID: String? = nil, supportedCommands: [GeneralCommandType]? = nil, isSupportsMediaControl: Bool? = nil, isSupportsRemoteControl: Bool? = nil, transcodingInfo: TranscodingInfo? = nil, userID: String? = nil, userName: String? = nil, userPrimaryImageTag: String? = nil) {
public init(additionalUsers: [SessionUserInfo]? = nil, applicationVersion: String? = nil, capabilities: ClientCapabilities? = nil, client: String? = nil, deviceID: String? = nil, deviceName: String? = nil, deviceType: String? = nil, fullNowPlayingItem: BaseItem? = nil, hasCustomDeviceName: Bool? = nil, id: String? = nil, isActive: Bool? = nil, lastActivityDate: Date? = nil, lastPlaybackCheckIn: Date? = nil, nowPlayingItem: BaseItemDto? = nil, nowPlayingQueue: [QueueItem]? = nil, nowPlayingQueueFullItems: [BaseItemDto]? = nil, nowViewingItem: BaseItemDto? = nil, playState: PlayerStateInfo? = nil, playableMediaTypes: [String]? = nil, playlistItemID: String? = nil, remoteEndPoint: String? = nil, serverID: String? = nil, supportedCommands: [GeneralCommandType]? = nil, isSupportsMediaControl: Bool? = nil, isSupportsRemoteControl: Bool? = nil, transcodingInfo: TranscodingInfo? = nil, userID: String? = nil, userName: String? = nil, userPrimaryImageTag: String? = nil) {
self.additionalUsers = additionalUsers
self.applicationVersion = applicationVersion
self.capabilities = capabilities
@ -69,6 +73,8 @@ public struct SessionInfo: Codable, Identifiable {
self.hasCustomDeviceName = hasCustomDeviceName
self.id = id
self.isActive = isActive
self.lastActivityDate = lastActivityDate
self.lastPlaybackCheckIn = lastPlaybackCheckIn
self.nowPlayingItem = nowPlayingItem
self.nowPlayingQueue = nowPlayingQueue
self.nowPlayingQueueFullItems = nowPlayingQueueFullItems
@ -100,6 +106,8 @@ public struct SessionInfo: Codable, Identifiable {
self.hasCustomDeviceName = try values.decodeIfPresent(Bool.self, forKey: "HasCustomDeviceName")
self.id = try values.decodeIfPresent(String.self, forKey: "Id")
self.isActive = try values.decodeIfPresent(Bool.self, forKey: "IsActive")
self.lastActivityDate = try values.decodeIfPresent(Date.self, forKey: "LastActivityDate")
self.lastPlaybackCheckIn = try values.decodeIfPresent(Date.self, forKey: "LastPlaybackCheckIn")
self.nowPlayingItem = try values.decodeIfPresent(BaseItemDto.self, forKey: "NowPlayingItem")
self.nowPlayingQueue = try values.decodeIfPresent([QueueItem].self, forKey: "NowPlayingQueue")
self.nowPlayingQueueFullItems = try values.decodeIfPresent([BaseItemDto].self, forKey: "NowPlayingQueueFullItems")
@ -131,6 +139,8 @@ public struct SessionInfo: Codable, Identifiable {
try values.encodeIfPresent(hasCustomDeviceName, forKey: "HasCustomDeviceName")
try values.encodeIfPresent(id, forKey: "Id")
try values.encodeIfPresent(isActive, forKey: "IsActive")
try values.encodeIfPresent(lastActivityDate, forKey: "LastActivityDate")
try values.encodeIfPresent(lastPlaybackCheckIn, forKey: "LastPlaybackCheckIn")
try values.encodeIfPresent(nowPlayingItem, forKey: "NowPlayingItem")
try values.encodeIfPresent(nowPlayingQueue, forKey: "NowPlayingQueue")
try values.encodeIfPresent(nowPlayingQueueFullItems, forKey: "NowPlayingQueueFullItems")

View File

@ -22,6 +22,10 @@ public struct UserDto: Codable, Identifiable {
public var hasPassword: Bool?
/// Gets or sets the id.
public var id: String?
/// Gets or sets the last activity date.
public var lastActivityDate: Date?
/// Gets or sets the last login date.
public var lastLoginDate: Date?
/// Gets or sets the name.
public var name: String?
/// Gets or sets the policy.
@ -37,13 +41,15 @@ public struct UserDto: Codable, Identifiable {
/// This is not used by the server and is for client-side usage only.
public var serverName: String?
public init(configuration: UserConfiguration? = nil, enableAutoLogin: Bool? = nil, hasConfiguredEasyPassword: Bool? = nil, hasConfiguredPassword: Bool? = nil, hasPassword: Bool? = nil, id: String? = nil, name: String? = nil, policy: UserPolicy? = nil, primaryImageAspectRatio: Double? = nil, primaryImageTag: String? = nil, serverID: String? = nil, serverName: String? = nil) {
public init(configuration: UserConfiguration? = nil, enableAutoLogin: Bool? = nil, hasConfiguredEasyPassword: Bool? = nil, hasConfiguredPassword: Bool? = nil, hasPassword: Bool? = nil, id: String? = nil, lastActivityDate: Date? = nil, lastLoginDate: Date? = nil, name: String? = nil, policy: UserPolicy? = nil, primaryImageAspectRatio: Double? = nil, primaryImageTag: String? = nil, serverID: String? = nil, serverName: String? = nil) {
self.configuration = configuration
self.enableAutoLogin = enableAutoLogin
self.hasConfiguredEasyPassword = hasConfiguredEasyPassword
self.hasConfiguredPassword = hasConfiguredPassword
self.hasPassword = hasPassword
self.id = id
self.lastActivityDate = lastActivityDate
self.lastLoginDate = lastLoginDate
self.name = name
self.policy = policy
self.primaryImageAspectRatio = primaryImageAspectRatio
@ -60,6 +66,8 @@ public struct UserDto: Codable, Identifiable {
self.hasConfiguredPassword = try values.decodeIfPresent(Bool.self, forKey: "HasConfiguredPassword")
self.hasPassword = try values.decodeIfPresent(Bool.self, forKey: "HasPassword")
self.id = try values.decodeIfPresent(String.self, forKey: "Id")
self.lastActivityDate = try values.decodeIfPresent(Date.self, forKey: "LastActivityDate")
self.lastLoginDate = try values.decodeIfPresent(Date.self, forKey: "LastLoginDate")
self.name = try values.decodeIfPresent(String.self, forKey: "Name")
self.policy = try values.decodeIfPresent(UserPolicy.self, forKey: "Policy")
self.primaryImageAspectRatio = try values.decodeIfPresent(Double.self, forKey: "PrimaryImageAspectRatio")
@ -76,6 +84,8 @@ public struct UserDto: Codable, Identifiable {
try values.encodeIfPresent(hasConfiguredPassword, forKey: "HasConfiguredPassword")
try values.encodeIfPresent(hasPassword, forKey: "HasPassword")
try values.encodeIfPresent(id, forKey: "Id")
try values.encodeIfPresent(lastActivityDate, forKey: "LastActivityDate")
try values.encodeIfPresent(lastLoginDate, forKey: "LastLoginDate")
try values.encodeIfPresent(name, forKey: "Name")
try values.encodeIfPresent(policy, forKey: "Policy")
try values.encodeIfPresent(primaryImageAspectRatio, forKey: "PrimaryImageAspectRatio")

View File

@ -35,9 +35,18 @@ public final class JellyfinClient {
self._apiClient = APIClient(baseURL: configuration.url) { configuration in
configuration.sessionConfiguration = sessionConfiguration
configuration.decoder = JSONDecoder()
configuration.encoder = JSONEncoder()
configuration.delegate = self
let isoDateFormatter: DateFormatter = OpenISO8601DateFormatter()
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(isoDateFormatter)
configuration.decoder = decoder
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .formatted(isoDateFormatter)
encoder.outputFormatting = .prettyPrinted
configuration.encoder = encoder
}
}

View File

@ -0,0 +1,45 @@
//
// jellyfin-sdk-swift is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2022 Jellyfin & Jellyfin Contributors
//
import Foundation
// https://stackoverflow.com/a/50281094/976628
public class OpenISO8601DateFormatter: DateFormatter {
static let withoutSeconds: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
return formatter
}()
private func setup() {
calendar = Calendar(identifier: .iso8601)
locale = Locale(identifier: "en_US_POSIX")
timeZone = TimeZone(secondsFromGMT: 0)
dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
}
override init() {
super.init()
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override public func date(from string: String) -> Date? {
if let result = super.date(from: string) {
return result
}
return OpenISO8601DateFormatter.withoutSeconds.date(from: string)
}
}

View File

@ -19,10 +19,6 @@ entities:
sortPropertiesAlphabetically: true
exclude:
- BaseItemDto.CurrentProgram # removed due to circular references for struct conformance
- SessionInfo.LastActivityDate # removed due to ISO 8601 incompliance
- SessionInfo.LastPlaybackCheckIn # removed due to ISO 8601 incompliance
- UserDto.LastActivityDate # removed due to ISO 8601 incompliance
- UserDto.LastLoginDate # removed due to ISO 8601 incompliance
paths:
style: operations
filenameTemplate: "%0API.swift"