From d76825deb58fb8f4eefc08a2fdff531922ab8a45 Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Fri, 9 Jun 2017 09:41:01 +0300 Subject: [PATCH] Date formatting service --- LeadKit.xcodeproj/project.pbxproj | 48 ++++++++++++- .../Services/DateFormattingService.swift | 72 +++++++++++++++++++ ...ateFormattingArguments+DateFormatter.swift | 44 ++++++++++++ .../DateFormattingArguments.swift | 57 +++++++++++++++ 4 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 Sources/Classes/Services/DateFormattingService.swift create mode 100644 Sources/Extensions/DateFormattingArguments/DateFormattingArguments+DateFormatter.swift create mode 100644 Sources/Structures/DateFormatting/DateFormattingArguments.swift diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 6ba7d0e8..0235f925 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -348,6 +348,18 @@ 674AF55C1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 674AF55B1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift */; }; 674AF55D1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 674AF55B1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift */; }; 674AF55E1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 674AF55B1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift */; }; + 6771DFD81EE99EBA002DCDAE /* DateFormattingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */; }; + 6771DFD91EE99EBA002DCDAE /* DateFormattingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */; }; + 6771DFDA1EE99EBA002DCDAE /* DateFormattingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */; }; + 6771DFDB1EE99EBA002DCDAE /* DateFormattingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */; }; + 6771DFDE1EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */; }; + 6771DFDF1EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */; }; + 6771DFE01EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */; }; + 6771DFE11EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */; }; + 6771DFE41EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */; }; + 6771DFE51EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */; }; + 6771DFE61EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */; }; + 6771DFE71EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */; }; 6782BBA91EB31D5A0086E0B8 /* LeadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6782BBA01EB31D590086E0B8 /* LeadKit.framework */; }; 67952C3C1EB3266100B3BA1A /* LeadKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 67186B201EB247A200CFAFFB /* LeadKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 67952C3D1EB3266200B3BA1A /* LeadKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 67186B201EB247A200CFAFFB /* LeadKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -527,6 +539,9 @@ 67186B411EB24AA000CFAFFB /* iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = iOS.playground; sourceTree = ""; }; 67186C1A1EB24B7800CFAFFB /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; 674AF55B1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+LoadingIndicator.swift"; sourceTree = ""; }; + 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormattingService.swift; sourceTree = ""; }; + 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormattingArguments.swift; sourceTree = ""; }; + 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormattingArguments+DateFormatter.swift"; sourceTree = ""; }; 6782BB911EB31CFE0086E0B8 /* LeadKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6782BBA01EB31D590086E0B8 /* LeadKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6782BBA81EB31D5A0086E0B8 /* LeadKit tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "LeadKit tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -679,6 +694,7 @@ isa = PBXGroup; children = ( 671461D31EB3396E00EAB194 /* NetworkService.swift */, + 6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */, ); path = Services; sourceTree = ""; @@ -713,6 +729,7 @@ 671461E21EB3396E00EAB194 /* CGImage */, 671461E51EB3396E00EAB194 /* CGSize */, 671461E81EB3396E00EAB194 /* CursorType */, + 6771DFE21EE99FF3002DCDAE /* DateFormattingArguments */, 671461EA1EB3396E00EAB194 /* Double */, 671461EC1EB3396E00EAB194 /* IndexPath */, 6714639C1EB33AC200EAB194 /* NetworkService */, @@ -1004,8 +1021,9 @@ isa = PBXGroup; children = ( 671462361EB3396E00EAB194 /* Api */, - 671462421EB3396E00EAB194 /* Views */, + 6771DFDC1EE99F52002DCDAE /* DateFormatting */, 671462381EB3396E00EAB194 /* DrawingOperations */, + 671462421EB3396E00EAB194 /* Views */, ); path = Structures; sourceTree = ""; @@ -1118,6 +1136,22 @@ path = UIActivityIndicatorView; sourceTree = ""; }; + 6771DFDC1EE99F52002DCDAE /* DateFormatting */ = { + isa = PBXGroup; + children = ( + 6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */, + ); + path = DateFormatting; + sourceTree = ""; + }; + 6771DFE21EE99FF3002DCDAE /* DateFormattingArguments */ = { + isa = PBXGroup; + children = ( + 6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */, + ); + path = DateFormattingArguments; + sourceTree = ""; + }; 67A1FF921EBCA64A00D6C89F /* CABasicAnimation */ = { isa = PBXGroup; children = ( @@ -1930,6 +1964,7 @@ 6714639E1EB33AEB00EAB194 /* NetworkService+ActivityIndicator.swift in Sources */, 6714634C1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift in Sources */, 671462F01EB3396E00EAB194 /* UIImage+SupportExtensions.swift in Sources */, + 6771DFDE1EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */, 671462681EB3396E00EAB194 /* NetworkService.swift in Sources */, 671463101EB3396E00EAB194 /* UIViewController+DefaultXibName.swift in Sources */, 671462441EB3396E00EAB194 /* Mutex.swift in Sources */, @@ -1940,6 +1975,7 @@ 671462901EB3396E00EAB194 /* CGImage+Crop.swift in Sources */, 671462FC1EB3396E00EAB194 /* UIView+DefaultXibName.swift in Sources */, 671463841EB3396E00EAB194 /* ResizeDrawingOperation.swift in Sources */, + 6771DFD81EE99EBA002DCDAE /* DateFormattingService.swift in Sources */, 671462D01EB3396E00EAB194 /* UIScrollView+Support.swift in Sources */, 671463901EB3396E00EAB194 /* TemplateDrawingOperation.swift in Sources */, 6714630C1EB3396E00EAB194 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */, @@ -2011,6 +2047,7 @@ 6714629C1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */, 671463681EB3396E00EAB194 /* ViewModelProtocol.swift in Sources */, 671462E81EB3396E00EAB194 /* UIDevice+Extensions.swift in Sources */, + 6771DFE41EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2040,6 +2077,7 @@ 671462C61EB3396E00EAB194 /* String+Extensions.swift in Sources */, 67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */, 671463561EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */, + 6771DFE01EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */, 671462AA1EB3396E00EAB194 /* ImmutableMappable+ObservableMappable.swift in Sources */, 671463621EB3396E00EAB194 /* SupportProtocol.swift in Sources */, 671462861EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */, @@ -2064,6 +2102,7 @@ 671462AE1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 6714627E1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, 671463461EB3396E00EAB194 /* ObservableMappable.swift in Sources */, + 6771DFDA1EE99EBA002DCDAE /* DateFormattingService.swift in Sources */, 6714625A1EB3396E00EAB194 /* Log.swift in Sources */, 6714627A1EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, 671463A41EB33FF600EAB194 /* Animatable.swift in Sources */, @@ -2080,6 +2119,7 @@ 671463521EB3396E00EAB194 /* StaticEstimatedViewHeightProtocol.swift in Sources */, 671462961EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, 671463661EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, + 6771DFE61EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */, 6714624A1EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, 671462CA1EB3396E00EAB194 /* String+Localization.swift in Sources */, 671462BA1EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */, @@ -2114,6 +2154,7 @@ 671463231EB3396E00EAB194 /* Any+Cast.swift in Sources */, 6714634F1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift in Sources */, 671462F31EB3396E00EAB194 /* UIImage+SupportExtensions.swift in Sources */, + 6771DFE71EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */, 6714626B1EB3396E00EAB194 /* NetworkService.swift in Sources */, 671463131EB3396E00EAB194 /* UIViewController+DefaultXibName.swift in Sources */, 671462471EB3396E00EAB194 /* Mutex.swift in Sources */, @@ -2140,6 +2181,7 @@ 671462AF1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 671463031EB3396E00EAB194 /* UIView+LoadFromNib.swift in Sources */, 6714627F1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, + 6771DFDB1EE99EBA002DCDAE /* DateFormattingService.swift in Sources */, 671463471EB3396E00EAB194 /* ObservableMappable.swift in Sources */, 6714625B1EB3396E00EAB194 /* Log.swift in Sources */, 6714627B1EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, @@ -2164,6 +2206,7 @@ 671462731EB3396E00EAB194 /* CursorError.swift in Sources */, 6714639B1EB3396E00EAB194 /* AnyLoadingIndicator.swift in Sources */, 671463531EB3396E00EAB194 /* StaticEstimatedViewHeightProtocol.swift in Sources */, + 6771DFE11EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */, 671463171EB3396E00EAB194 /* UIViewController+TopVisibleViewController.swift in Sources */, 6714628B1EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */, 671462971EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, @@ -2215,6 +2258,7 @@ 671463491EB3396E00EAB194 /* ResettableType.swift in Sources */, 671462E51EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CD1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, + 6771DFDF1EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */, 67A1FF951EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */, 671462811EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */, 671462C51EB3396E00EAB194 /* String+Extensions.swift in Sources */, @@ -2275,6 +2319,7 @@ 671463151EB3396E00EAB194 /* UIViewController+TopVisibleViewController.swift in Sources */, 671462891EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */, 674AF55D1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift in Sources */, + 6771DFD91EE99EBA002DCDAE /* DateFormattingService.swift in Sources */, 671462951EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, 671463651EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, 671462491EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, @@ -2299,6 +2344,7 @@ 671462D91EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */, 6714638D1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */, 671463A31EB33FF600EAB194 /* Animatable.swift in Sources */, + 6771DFE51EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift in Sources */, 671462511EB3396E00EAB194 /* StaticCursor.swift in Sources */, 6714629D1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */, 671463691EB3396E00EAB194 /* ViewModelProtocol.swift in Sources */, diff --git a/Sources/Classes/Services/DateFormattingService.swift b/Sources/Classes/Services/DateFormattingService.swift new file mode 100644 index 00000000..dceafd99 --- /dev/null +++ b/Sources/Classes/Services/DateFormattingService.swift @@ -0,0 +1,72 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// 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 + +/// Date formatting service. Used for date to string and string to date formatting. +/// Takes into account locale and timezone. +open class DateFormattingService { + + private var dateFormatters: [DateFormattingArguments: DateFormatter] = [:] + + public init(formattingArguments: [DateFormattingArguments] = []) { + for argument in formattingArguments { + register(arguments: argument) + } + } + + /// DateFormatter registration method. + /// + /// - Parameter arguments: A formatting arguments structure. + public func register(arguments: DateFormattingArguments) { + dateFormatters[arguments] = arguments.dateFormatter + } + + /// String to date convertion method. + /// + /// - Parameters: + /// - dateString: The string to parse. + /// - arguments: A formatting arguments structure. + /// - Returns: A date representation of a given string interpreted using given arguments. + public func date(from dateString: String, arguments: DateFormattingArguments) -> Date? { + guard let dateFormatter = dateFormatters[arguments] else { + fatalError("No date formatter registered for given arguments: \(arguments)") + } + + return dateFormatter.date(from: dateString) + } + + /// Date to string convertion method. + /// + /// - Parameters: + /// - date: The date to format. + /// - arguments: A formatting arguments structure. + /// - Returns: A string representation of a given date formatted using given arguments. + public func string(from date: Date, arguments: DateFormattingArguments) -> String? { + guard let dateFormatter = dateFormatters[arguments] else { + fatalError("No date formatter registered for given arguments: \(arguments)") + } + + return dateFormatter.string(from: date) + } + +} diff --git a/Sources/Extensions/DateFormattingArguments/DateFormattingArguments+DateFormatter.swift b/Sources/Extensions/DateFormattingArguments/DateFormattingArguments+DateFormatter.swift new file mode 100644 index 00000000..1adbcb83 --- /dev/null +++ b/Sources/Extensions/DateFormattingArguments/DateFormattingArguments+DateFormatter.swift @@ -0,0 +1,44 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// 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 + +public extension DateFormattingArguments { + + /// Date formatter for formatting arguments. + var dateFormatter: DateFormatter { + return DateFormatter(dateFormat: dateFormat, locale: locale, timeZone: timeZone) + } + +} + +private extension DateFormatter { + + convenience init(dateFormat: String, locale: Locale, timeZone: TimeZone) { + self.init() + + self.dateFormat = dateFormat + self.locale = locale + self.timeZone = timeZone + } + +} diff --git a/Sources/Structures/DateFormatting/DateFormattingArguments.swift b/Sources/Structures/DateFormatting/DateFormattingArguments.swift new file mode 100644 index 00000000..7ffc3532 --- /dev/null +++ b/Sources/Structures/DateFormatting/DateFormattingArguments.swift @@ -0,0 +1,57 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// 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 + +/// Structure describes "context" for date formatting. +public struct DateFormattingArguments: Hashable { + + let dateFormat: String + let locale: Locale + let timeZone: TimeZone + + /// Default initializer + /// + /// - Parameters: + /// - dateFormat: Date format to be used for formatting. + /// - locale: Locale to be used for formatting. + /// - timeZone: Time zone to be used for formatting. + public init(dateFormat: String, + locale: Locale = Locale.current, + timeZone: TimeZone = TimeZone.current) { + + self.dateFormat = dateFormat + self.locale = locale + self.timeZone = timeZone + } + + public var hashValue: Int { + return dateFormat.hashValue ^ locale.hashValue ^ timeZone.hashValue + } + + public static func == (lhs: DateFormattingArguments, rhs: DateFormattingArguments) -> Bool { + return lhs.dateFormat == rhs.dateFormat && + lhs.locale.identifier == rhs.locale.identifier && + lhs.timeZone.identifier == rhs.timeZone.identifier + } + +}