Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
pawello2222 committed Jul 23, 2023
1 parent b38addd commit 3958126
Show file tree
Hide file tree
Showing 10 changed files with 789 additions and 0 deletions.
65 changes: 65 additions & 0 deletions Sources/XFormatter/XDateFormatter/XDateFormatter+Convenience.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation

// MARK: - Date

extension XDateFormatter {
public static func date(
locale: Locale = .current,
format: String
) -> XDateFormatter {
.init().apply {
$0.dateFormatter.locale = locale
$0.dateFormatter.dateFormat = format
}
}

public static func date(
locale: Locale = .current,
localizedFormat: String = "yyyyMMdd"
) -> XDateFormatter {
.init().apply {
$0.dateFormatter.locale = locale
$0.dateFormatter.setLocalizedDateFormatFromTemplate(localizedFormat)
}
}
}

// MARK: - Date Components

extension XDateFormatter {
public static func dateComponents(
locale: Locale = .current,
allowedUnits: NSCalendar.Unit = [.hour, .minute, .second],
unitsStyle: DateComponentsFormatter.UnitsStyle = .full
) -> XDateFormatter {
.init().apply {
$0.dateComponentsFormatter.calendar = Calendar.current.applying {
$0.locale = locale
}
$0.dateComponentsFormatter.allowedUnits = allowedUnits
$0.dateComponentsFormatter.unitsStyle = unitsStyle
}
}
}
67 changes: 67 additions & 0 deletions Sources/XFormatter/XDateFormatter/XDateFormatter+Date.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation

// MARK: - Read

extension XDateFormatter {
public func date(from string: String, timeZone: TimeZone? = nil) -> Date? {
with(timeZone: timeZone) {
dateFormatter.date(from: string)
}
}
}

// MARK: - Write

extension XDateFormatter {
public func string(from date: Date) -> String {
dateFormatter.string(from: date)
}
}

extension XDateFormatter {
public func string(from dateComponents: DateComponents) -> String {
dateComponentsFormatter.string(from: dateComponents) ?? invalidValueString
}

public func string(fromTimeInterval timeInterval: TimeInterval) -> String {
dateComponentsFormatter.string(from: timeInterval) ?? invalidValueString
}

public func string(from startDate: Date, to endDate: Date) -> String {
dateComponentsFormatter.string(from: startDate, to: endDate) ?? invalidValueString
}
}

// MARK: - Helpers

extension XDateFormatter {
private func with<T>(timeZone: TimeZone?, _ block: () -> T) -> T {
let existingTimeZone = dateFormatter.timeZone
dateFormatter.timeZone = timeZone
let result = block()
dateFormatter.timeZone = existingTimeZone
return result
}
}
60 changes: 60 additions & 0 deletions Sources/XFormatter/XDateFormatter/XDateFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Appliable
import Foundation

/// A formatter that converts between numeric values and their textual representations.
public class XDateFormatter: ObjectAppliable {
public var invalidValueString = "--"

// MARK: Formatters

internal lazy var dateFormatter = DateFormatter()
internal lazy var dateComponentsFormatter = DateComponentsFormatter()

// MARK: Initialization

public init() {}
}

// MARK: - Defaults

extension XDateFormatter {
public static var date = date(localizedFormat: "yyyyMMdd")

public static var time = date(localizedFormat: "jjmmss")

public static var datetime = date(localizedFormat: "yyyyMMddjjmmss")

public static var dateComponents = dateComponents(
allowedUnits: [.year, .month, .day]
)

public static var timeComponents = dateComponents(
allowedUnits: [.hour, .minute, .second]
)

public static var datetimeComponents = dateComponents(
allowedUnits: [.year, .month, .day, .hour, .minute, .second]
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation

extension XFormatter.Abbreviation {
public struct Threshold {
public let suffix: String
public let value: NSDecimalNumber

public init(suffix: String, value: NSDecimalNumber) {
self.suffix = suffix
self.value = value
}
}
}
64 changes: 64 additions & 0 deletions Sources/XFormatter/XFormatter/Components/Abbreviation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import PhantomKit

extension XFormatter {
public struct Abbreviation {
public let thresholds: [Threshold]

public init(_ thresholds: [Threshold] = []) {
self.thresholds = thresholds
.sorted {
$0.value > $1.value
}
}
}
}

// MARK: - Helpers

extension XFormatter.Abbreviation {
public var capitalized: Self {
.init(
thresholds.map {
.init(suffix: $0.suffix.capitalized, value: $0.value)
}
)
}
}

// MARK: - Convenience

extension XFormatter.Abbreviation {
public static var `default`: Self = .init(
[
.init(suffix: "m", value: 1_000_000),
.init(suffix: "k", value: 1000)
]
)

public static var none: Self = .init()

public static var capitalized = Self.default.capitalized
}
75 changes: 75 additions & 0 deletions Sources/XFormatter/XFormatter/Components/Precision.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// The MIT License (MIT)
//
// Copyright (c) 2023-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import PhantomKit

extension XFormatter {
public struct Precision {
public let minimum: Int?
public let maximum: Int?
}
}

// MARK: - Initialization

extension XFormatter.Precision {
public init() {
minimum = nil
maximum = nil
}

public init(_ range: PartialRangeFrom<Int>) {
minimum = Self.clamp(range.lowerBound)
maximum = nil
}

public init(_ range: PartialRangeThrough<Int>) {
minimum = nil
maximum = Self.clamp(range.upperBound)
}

public init(_ range: ClosedRange<Int>) {
minimum = Self.clamp(range.lowerBound)
maximum = Self.clamp(range.upperBound)
}

private static func clamp(_ value: Int) -> Int {
value.clamped(to: .zero ... .max)
}
}

// MARK: - Convenience

extension XFormatter.Precision {
public static var `default`: Self {
.init(...2)
}

public static var maximum: Self {
.init(...16)
}

public static func constant(_ value: Int) -> Self {
.init(value ... value)
}
}
Loading

0 comments on commit 3958126

Please sign in to comment.