brennobemoura/request-dl

View on GitHub
Sources/RequestDL/Properties/Sources/URL/Query/Models/Strategies/URLEncoder.DateEncodingStrategy.swift

Summary

Maintainability
A
1 hr
Test Coverage
/*
 See LICENSE for this package's licensing information.
*/

#if canImport(Darwin)
import Foundation
#else
@preconcurrency import Foundation
#endif

extension URLEncoder {

    /// Defines strategies for encoding dates in a url encoded format
    public enum DateEncodingStrategy: URLSingleEncodingStrategy {

        /// Encodes the date as the number of seconds since January 1, 1970, as a `Double`.
        case secondsSince1970

        /// Encodes the date as the number of milliseconds since January 1, 1970, as a `Int`.
        case millisecondsSince1970

        /// Encodes the date as an ISO8601-formatted string. This is the default.
        case iso8601

        /// Encodes the date using a given `DateFormatter` instance.
        case formatter(DateFormatter)

        /// Encodes the date using a custom closure that takes a `Date` and an `Encoder`
        /// as input parameters and throws an error.
        case custom(@Sendable (Date, Encoder) throws -> Void)

        // MARK: - Internal methods

        func encode(_ date: Date, in encoder: URLEncoder.Encoder) throws {
            switch self {
            case .secondsSince1970:
                try encodeSecondsSince1970(date, in: encoder)
            case .millisecondsSince1970:
                try encodeMillisecondsSince1970(date, in: encoder)
            case .iso8601:
                try encodeISO8601(date, in: encoder)
            case .formatter(let dateFormatter):
                try encodeDateFormatter(date, in: encoder, with: dateFormatter)
            case .custom(let closure):
                try closure(date, encoder)
            }
        }

        // MARK: - Private methods

        private func encodeSecondsSince1970(_ date: Date, in encoder: URLEncoder.Encoder) throws {
            var container = encoder.valueContainer()
            try container.encode("\(Int64(date.timeIntervalSince1970))")
        }

        private func encodeMillisecondsSince1970(_ date: Date, in encoder: URLEncoder.Encoder) throws {
            var container = encoder.valueContainer()
            try container.encode("\(Int64(date.timeIntervalSince1970) * 1_000)")
        }

        private func encodeISO8601(_ date: Date, in encoder: URLEncoder.Encoder) throws {
            let dateFormatter = ISO8601DateFormatter()

            var container = encoder.valueContainer()
            try container.encode(dateFormatter.string(from: date))
        }

        private func encodeDateFormatter(
            _ date: Date,
            in encoder: URLEncoder.Encoder,
            with dateFormatter: DateFormatter
        ) throws {
            var container = encoder.valueContainer()
            try container.encode(dateFormatter.string(from: date))
        }
    }
}