Date formatting service

This commit is contained in:
Ivan Smolin 2017-06-09 09:41:01 +03:00
parent f3b24792ad
commit d76825deb5
4 changed files with 220 additions and 1 deletions

View File

@ -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 = "<group>"; };
67186C1A1EB24B7800CFAFFB /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
674AF55B1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+LoadingIndicator.swift"; sourceTree = "<group>"; };
6771DFD71EE99EBA002DCDAE /* DateFormattingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormattingService.swift; sourceTree = "<group>"; };
6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateFormattingArguments.swift; sourceTree = "<group>"; };
6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormattingArguments+DateFormatter.swift"; sourceTree = "<group>"; };
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 = "<group>";
@ -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 = "<group>";
@ -1118,6 +1136,22 @@
path = UIActivityIndicatorView;
sourceTree = "<group>";
};
6771DFDC1EE99F52002DCDAE /* DateFormatting */ = {
isa = PBXGroup;
children = (
6771DFDD1EE99F6F002DCDAE /* DateFormattingArguments.swift */,
);
path = DateFormatting;
sourceTree = "<group>";
};
6771DFE21EE99FF3002DCDAE /* DateFormattingArguments */ = {
isa = PBXGroup;
children = (
6771DFE31EE9A00A002DCDAE /* DateFormattingArguments+DateFormatter.swift */,
);
path = DateFormattingArguments;
sourceTree = "<group>";
};
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 */,

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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
}
}