├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── Images
└── header.png
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── DateFormatterPool
│ ├── DateFormat.swift
│ ├── DateFormatterContainer.swift
│ ├── DateFormatterPropertyWrapper.swift
│ └── RecursiveLock.swift
└── Tests
└── DateFormatterPoolTests
└── DateFormatterPoolTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm/config/registries.json
8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9 | .netrc
10 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Images/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bartleby/DateFormatterPool/a8460e1887d3f0d9022c7e382caf46075512f3b6/Images/header.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Aleksei Artemev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.6
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "DateFormatterPool",
8 | products: [
9 | // Products define the executables and libraries a package produces, and make them visible to other packages.
10 | .library(
11 | name: "DateFormatterPool",
12 | targets: ["DateFormatterPool"]),
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
21 | .target(
22 | name: "DateFormatterPool",
23 | dependencies: []),
24 | .testTarget(
25 | name: "DateFormatterPoolTests",
26 | dependencies: ["DateFormatterPool"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Date Formatter Pool
6 | ========
7 |
8 | Date Formatter Pool - is a small utility that creates and stores your `Date Formatter` for simpler reuse
9 |
10 | ## Installation
11 |
12 | is available in the [Swift Package Manager](https://swift.org/package-manager/).
13 |
14 | ### Swift Package Manager
15 |
16 | ```
17 | https://github.com/bartleby/DateFormatterPool.git
18 | ```
19 |
20 |
21 | ## Basic Usage
22 |
23 | First, add a your `format` to a `Pool`, through the expansion of `DateFormat`
24 |
25 |
26 | ```swift
27 | extension DateFormat {
28 | static let shortDateAndTime = DateFormat(value: "MMM d, E 'at' HH:mm")
29 | static let shortDay = DateFormat(value: "d")
30 | static let shortMonth = DateFormat(value: "MMM")
31 | static let monthAndYear = DateFormat(value: "LLLL YYYY")
32 | static let shortWeekName = DateFormat(value: "EE")
33 | }
34 | ```
35 |
36 | On this site you can create the format you need: [nsdateformatter.com](https://nsdateformatter.com)
37 |
38 |
39 |
40 | Then get an `DateFormatter` from the pool using `PropertyWrapper`.
41 |
42 | ```swift
43 | struct ContentView: View {
44 | @DateFormatterPool(.shortDateAndTime) var shortDateAndTimeFormatter
45 |
46 | var body: some View {
47 | VStack {
48 | Text(shortDateAndTimeFormatter.string(from: Date())) // Aug 23, Tue at 12:10
49 | }
50 | }
51 | }
52 | ```
53 |
54 | or in ViewModel
55 |
56 | ```swift
57 | final class ViewModel {
58 | @Published var dateString: String
59 |
60 | @DateFormatterPool(.shortDateAndTime) var shortDateAndTimeFormatter
61 |
62 | //...
63 |
64 | func configure() {
65 | dateString = shortDateAndTimeFormatter.string(from: Date())) // Aug 23, Tue at 12:10
66 | }
67 | }
68 | ```
69 |
70 |
71 | ## Example Apps
72 |
73 | Coming soon
74 |
75 |
76 | ## License
77 |
78 | MIT license. See the [LICENSE file](LICENSE) for details.
79 |
--------------------------------------------------------------------------------
/Sources/DateFormatterPool/DateFormat.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 iDevs.io. All rights reserved.
2 |
3 | import Foundation
4 |
5 | public struct DateFormat {
6 | public var value: String
7 |
8 | public init(value: String) {
9 | self.value = value
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/DateFormatterPool/DateFormatterContainer.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 iDevs.io. All rights reserved.
2 |
3 | import Foundation
4 |
5 | final class DateFormatterContainer {
6 |
7 | // MARK: - Properties
8 | private var pool = [String: DateFormatter]()
9 | private var lock: RecursiveLock = RecursiveLock()
10 |
11 | // MARK: - Singleton
12 | public static let shared = DateFormatterContainer()
13 |
14 | // MARK: - Init/Deinit
15 | private init() {}
16 |
17 | // MARK: - Public methods
18 | public func obtain(format: DateFormat) -> DateFormatter {
19 | return lock.sync {
20 | let key = format.value
21 |
22 | if let formatter = pool[key] {
23 | return formatter
24 | }
25 |
26 | let formatter = DateFormatter()
27 | formatter.dateFormat = key
28 | pool[key] = formatter
29 |
30 | return formatter
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/DateFormatterPool/DateFormatterPropertyWrapper.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 iDevs.io. All rights reserved.
2 |
3 | import Foundation
4 |
5 | @propertyWrapper
6 | public final class DateFormatterPool {
7 |
8 | // MARK: - Properties
9 | private let format: DateFormat
10 | private var dateFormatterContainer = DateFormatterContainer.shared
11 | public var wrappedValue: DateFormatter { value }
12 |
13 | // MARK: - Lazy Properties
14 | private lazy var value: DateFormatter = {
15 | dateFormatterContainer.obtain(format: format)
16 | }()
17 |
18 |
19 | // MARK: - Init/Deinit
20 | public init(_ format: DateFormat) {
21 | self.format = format
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/DateFormatterPool/RecursiveLock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Bartleby on 23.08.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | final class RecursiveLock {
11 |
12 | // MARK: - Private methods
13 | private let lock = NSRecursiveLock()
14 |
15 | // MARK: - Public methods
16 | func sync(action: () -> T) -> T {
17 | lock.lock()
18 | defer { lock.unlock() }
19 | return action()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Tests/DateFormatterPoolTests/DateFormatterPoolTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DateFormatterPool
3 |
4 | final class DateFormatterPoolTests: XCTestCase {
5 |
6 | func testExample() throws {}
7 | }
8 |
--------------------------------------------------------------------------------