add all api to sort by month

This commit is contained in:
Michael Simard
2020-06-14 21:46:44 -05:00
parent 6b9e9a4c35
commit 842abb0895
162 changed files with 34480 additions and 71 deletions

View File

@@ -0,0 +1,74 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
#if os(Linux)
#else
import Foundation
import ObjectiveC.runtime
internal func getAssociatedValue<T>(key: String, object: AnyObject) -> T? {
return (objc_getAssociatedObject(object, key.address) as? AssociatedValue)?.value as? T
}
internal func getAssociatedValue<T>(key: String, object: AnyObject, initialValue: @autoclosure () -> T) -> T {
return getAssociatedValue(key: key, object: object) ?? setAndReturn(initialValue: initialValue(), key: key, object: object)
}
internal func getAssociatedValue<T>(key: String, object: AnyObject, initialValue: () -> T) -> T {
return getAssociatedValue(key: key, object: object) ?? setAndReturn(initialValue: initialValue(), key: key, object: object)
}
private func setAndReturn<T>(initialValue: T, key: String, object: AnyObject) -> T {
set(associatedValue: initialValue, key: key, object: object)
return initialValue
}
internal func set<T>(associatedValue: T?, key: String, object: AnyObject) {
set(associatedValue: AssociatedValue(associatedValue), key: key, object: object)
}
internal func set<T: AnyObject>(weakAssociatedValue: T?, key: String, object: AnyObject) {
set(associatedValue: AssociatedValue(weak: weakAssociatedValue), key: key, object: object)
}
extension String {
fileprivate var address: UnsafeRawPointer {
return UnsafeRawPointer(bitPattern: abs(hashValue))!
}
}
private func set(associatedValue: AssociatedValue, key: String, object: AnyObject) {
objc_setAssociatedObject(object, key.address, associatedValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
private class AssociatedValue {
weak var _weakValue: AnyObject?
var _value: Any?
var value: Any? {
return _weakValue ?? _value
}
init(_ value: Any?) {
_value = value
}
init(weak: AnyObject?) {
_weakValue = weak
}
}
#endif

View File

@@ -0,0 +1,96 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
import Foundation
public typealias Calendars = Calendar.Identifier
public protocol CalendarConvertible {
func toCalendar() -> Calendar
}
extension Calendar: CalendarConvertible {
public func toCalendar() -> Calendar {
return self
}
internal static func newCalendar(_ calendar: CalendarConvertible, configure: ((inout Calendar) -> Void)? = nil) -> Calendar {
var cal = calendar.toCalendar()
configure?(&cal)
return cal
}
}
extension Calendar.Identifier: CalendarConvertible {
public func toCalendar() -> Calendar {
return Calendar(identifier: self)
}
}
// MARK: - Support for Calendar.Identifier encoding with Codable
extension Calendar.Identifier: CustomStringConvertible {
public var description: String {
switch self {
case .gregorian: return "gregorian"
case .buddhist: return "buddhist"
case .chinese: return "chinese"
case .coptic: return "coptic"
case .ethiopicAmeteMihret: return "ethiopicAmeteMihret"
case .ethiopicAmeteAlem: return "ethiopicAmeteAlem"
case .hebrew: return "hebrew"
case .iso8601: return "iso8601"
case .indian: return "indian"
case .islamic: return "islamic"
case .islamicCivil: return "islamicCivil"
case .japanese: return "japanese"
case .persian: return "persian"
case .republicOfChina: return "republicOfChina"
case .islamicTabular: return "islamicTabular"
case .islamicUmmAlQura: return "islamicUmmAlQura"
@unknown default:
fatalError("Unsupported calendar \(self)")
}
}
public init(_ rawValue: String) {
switch rawValue {
case Calendar.Identifier.gregorian.description: self = .gregorian
case Calendar.Identifier.buddhist.description: self = .buddhist
case Calendar.Identifier.chinese.description: self = .chinese
case Calendar.Identifier.coptic.description: self = .coptic
case Calendar.Identifier.ethiopicAmeteMihret.description: self = .ethiopicAmeteMihret
case Calendar.Identifier.ethiopicAmeteAlem.description: self = .ethiopicAmeteAlem
case Calendar.Identifier.hebrew.description: self = .hebrew
case Calendar.Identifier.iso8601.description: self = .iso8601
case Calendar.Identifier.indian.description: self = .indian
case Calendar.Identifier.islamic.description: self = .islamic
case Calendar.Identifier.islamicCivil.description: self = .islamicCivil
case Calendar.Identifier.japanese.description: self = .japanese
case Calendar.Identifier.persian.description: self = .persian
case Calendar.Identifier.republicOfChina.description: self = .republicOfChina
case Calendar.Identifier.islamicTabular.description: self = .islamicTabular
case Calendar.Identifier.islamicTabular.description: self = .islamicTabular
case Calendar.Identifier.islamicUmmAlQura.description: self = .islamicUmmAlQura
default:
let defaultCalendar = SwiftDate.defaultRegion.calendar.identifier
debugPrint("Calendar Identifier '\(rawValue)' not recognized. Using default (\(defaultCalendar))")
self = defaultCalendar
}
}
}

View File

@@ -0,0 +1,286 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
import Foundation
public extension DateFormatter {
/// Return the local thread shared formatter initialized with the configuration of the region passed.
///
/// - Parameters:
/// - region: region used to pre-configure the cell.
/// - format: optional format used to set the `dateFormat` property.
/// - Returns: date formatter instance
static func sharedFormatter(forRegion region: Region?, format: String? = nil) -> DateFormatter {
let name = "SwiftDate_\(NSStringFromClass(DateFormatter.self))"
let formatter: DateFormatter = threadSharedObject(key: name, create: { return DateFormatter() })
if let region = region {
formatter.timeZone = region.timeZone
formatter.calendar = region.calendar
formatter.locale = region.locale
}
formatter.dateFormat = (format ?? DateFormats.iso8601)
return formatter
}
/// Returned number formatter instance shared along calling thread to format ordinal numbers.
///
/// - Parameter locale: locale to set
/// - Returns: number formatter instance
@available(iOS 9.0, macOS 10.11, *)
static func sharedOrdinalNumberFormatter(locale: LocaleConvertible) -> NumberFormatter {
var formatter: NumberFormatter?
let name = "SwiftDate_\(NSStringFromClass(NumberFormatter.self))"
formatter = threadSharedObject(key: name, create: { return NumberFormatter() })
formatter!.numberStyle = .ordinal
formatter!.locale = locale.toLocale()
return formatter!
}
}
/// This function create (if necessary) and return a thread singleton instance of the
/// object you want.
///
/// - Parameters:
/// - key: identifier of the object.
/// - create: create routine used the first time you are about to create the object in thread.
/// - Returns: instance of the object for caller's thread.
internal func threadSharedObject<T: AnyObject>(key: String, create: () -> T) -> T {
if let cachedObj = Thread.current.threadDictionary[key] as? T {
return cachedObj
} else {
let newObject = create()
Thread.current.threadDictionary[key] = newObject
return newObject
}
}
/// Style used to format month, weekday, quarter symbols.
/// Stand-alone properties are for use in places like calendar headers.
/// Non-stand-alone properties are for use in context (for example, Saturday, November 12th).
///
/// - `default`: Default formatter (ie. `4th quarter` for quarter, `April` for months and `Wednesday` for weekdays)
/// - defaultStandalone: See `default`; See `short`; stand-alone properties are for use in places like calendar headers.
/// - short: Short symbols (ie. `Jun` for months, `Fri` for weekdays, `Q1` for quarters).
/// - veryShort: Very short symbols (ie. `J` for months, `F` for weekdays, for quarter it just return `short` variant).
/// - standaloneShort: See `short`; stand-alone properties are for use in places like calendar headers.
/// - standaloneVeryShort: See `veryShort`; stand-alone properties are for use in places like calendar headers.
public enum SymbolFormatStyle {
case `default`
case defaultStandalone
case short
case veryShort
case standaloneShort
case standaloneVeryShort
}
/// Encapsulate the logic to use date format strings
public struct DateFormats {
/// This is the built-in list of all supported formats for auto-parsing of a string to a date.
internal static let builtInAutoFormat: [String] = [
DateFormats.iso8601,
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'",
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd",
"h:mm:ss A",
"h:mm A",
"MM/dd/yyyy",
"MMMM d, yyyy",
"MMMM d, yyyy LT",
"dddd, MMMM D, yyyy LT",
"yyyyyy-MM-dd",
"yyyy-MM-dd",
"yyyy-'W'ww-E",
"GGGG-'['W']'ww-E",
"yyyy-'W'ww",
"GGGG-'['W']'ww",
"yyyy'W'ww",
"yyyy-ddd",
"HH:mm:ss.SSSS",
"HH:mm:ss",
"HH:mm",
"HH"
]
/// This is the ordered list of all formats SwiftDate can use in order to attempt parsing a passaed
/// date expressed as string. Evaluation is made in order; you can add or remove new formats as you wish.
/// In order to reset the list call `resetAutoFormats()` function.
public static var autoFormats: [String] = DateFormats.builtInAutoFormat
/// Default ISO8601 format string
public static let iso8601: String = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
/// Extended format
public static let extended: String = "eee dd-MMM-yyyy GG HH:mm:ss.SSS zzz"
/// The Alternative RSS formatted date "d MMM yyyy HH:mm:ss ZZZ" i.e. "09 Sep 2011 15:26:08 +0200"
public static let altRSS: String = "d MMM yyyy HH:mm:ss ZZZ"
/// The RSS formatted date "EEE, d MMM yyyy HH:mm:ss ZZZ" i.e. "Fri, 09 Sep 2011 15:26:08 +0200"
public static let rss: String = "EEE, d MMM yyyy HH:mm:ss ZZZ"
/// The http header formatted date "EEE, dd MMM yyyy HH:mm:ss zzz" i.e. "Tue, 15 Nov 1994 12:45:26 GMT"
public static let httpHeader: String = "EEE, dd MMM yyyy HH:mm:ss zzz"
/// A generic standard format date i.e. "EEE MMM dd HH:mm:ss Z yyyy"
public static let standard: String = "EEE MMM dd HH:mm:ss Z yyyy"
/// SQL date format
public static let sql: String = "yyyy-MM-dd'T'HH:mm:ss.SSSX"
/// Reset the list of auto formats to the initial settings.
public static func resetAutoFormats() {
autoFormats = DateFormats.builtInAutoFormat
}
/// Parse a new string optionally passing the format in which is encoded. If no format is passed
/// an attempt is made by cycling all the formats set in `autoFormats` property.
///
/// - Parameters:
/// - string: date expressed as string.
/// - suggestedFormat: optional format of the date expressed by the string (set it if you can in order to optimize the parse task).
/// - region: region in which the date is expressed.
/// - Returns: parsed absolute `Date`, `nil` if parse fails.
public static func parse(string: String, format: String?, region: Region) -> Date? {
let formats = (format != nil ? [format!] : DateFormats.autoFormats)
return DateFormats.parse(string: string, formats: formats, region: region)
}
public static func parse(string: String, formats: [String], region: Region) -> Date? {
let formatter = DateFormatter.sharedFormatter(forRegion: region)
var parsedDate: Date?
for format in formats {
formatter.dateFormat = format
formatter.locale = region.locale
if let date = formatter.date(from: string) {
parsedDate = date
break
}
}
return parsedDate
}
}
// MARK: - Calendar Extension
public extension Calendar.Component {
internal static func toSet(_ src: [Calendar.Component]) -> Set<Calendar.Component> {
var l: Set<Calendar.Component> = []
src.forEach { l.insert($0) }
return l
}
internal var nsCalendarUnit: NSCalendar.Unit {
switch self {
case .era: return NSCalendar.Unit.era
case .year: return NSCalendar.Unit.year
case .month: return NSCalendar.Unit.month
case .day: return NSCalendar.Unit.day
case .hour: return NSCalendar.Unit.hour
case .minute: return NSCalendar.Unit.minute
case .second: return NSCalendar.Unit.second
case .weekday: return NSCalendar.Unit.weekday
case .weekdayOrdinal: return NSCalendar.Unit.weekdayOrdinal
case .quarter: return NSCalendar.Unit.quarter
case .weekOfMonth: return NSCalendar.Unit.weekOfMonth
case .weekOfYear: return NSCalendar.Unit.weekOfYear
case .yearForWeekOfYear: return NSCalendar.Unit.yearForWeekOfYear
case .nanosecond: return NSCalendar.Unit.nanosecond
case .calendar: return NSCalendar.Unit.calendar
case .timeZone: return NSCalendar.Unit.timeZone
@unknown default:
fatalError("Unsupported type \(self)")
}
}
}
/// Rounding mode for dates.
/// Round off/up (ceil) or down (floor) target date.
public enum RoundDateMode {
case to5Mins
case to10Mins
case to30Mins
case toMins(_: Int)
case toCeil5Mins
case toCeil10Mins
case toCeil30Mins
case toCeilMins(_: Int)
case toFloor5Mins
case toFloor10Mins
case toFloor30Mins
case toFloorMins(_: Int)
}
/// Related type enum to get derivated date from a receiver date.
public enum DateRelatedType {
case startOfDay
case endOfDay
case startOfWeek
case endOfWeek
case startOfMonth
case endOfMonth
case tomorrow
case tomorrowAtStart
case yesterday
case yesterdayAtStart
case nearestMinute(minute:Int)
case nearestHour(hour:Int)
case nextWeekday(_: WeekDay)
case nextDSTDate
case prevMonth
case nextMonth
case prevWeek
case nextWeek
case nextYear
case prevYear
case nextDSTTransition
}
public struct TimeCalculationOptions {
/// Specifies the technique the search algorithm uses to find result
public var matchingPolicy: Calendar.MatchingPolicy
/// Specifies the behavior when multiple matches are found
public var repeatedTimePolicy: Calendar.RepeatedTimePolicy
/// Specifies the direction in time to search
public var direction: Calendar.SearchDirection
public init(matching: Calendar.MatchingPolicy = .nextTime,
timePolicy: Calendar.RepeatedTimePolicy = .first,
direction: Calendar.SearchDirection = .forward) {
self.matchingPolicy = matching
self.repeatedTimePolicy = timePolicy
self.direction = direction
}
}
// MARK: - compactMap for Swift 4.0 (not necessary > 4.0)
#if swift(>=4.1)
#else
extension Collection {
func compactMap<ElementOfResult>(
_ transform: (Element) throws -> ElementOfResult?
) rethrows -> [ElementOfResult] {
return try flatMap(transform)
}
}
#endif

View File

@@ -0,0 +1,757 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
// swiftlint:disable file_length
import Foundation
public protocol LocaleConvertible {
func toLocale() -> Locale
}
extension Locale: LocaleConvertible {
public func toLocale() -> Locale {
return self
}
}
// swiftlint:disable type_body_length
public enum Locales: String, LocaleConvertible {
case current = "current"
case autoUpdating = "currentAutoUpdating"
case afrikaans = "af"
case afrikaansNamibia = "af_NA"
case afrikaansSouthAfrica = "af_ZA"
case aghem = "agq"
case aghemCameroon = "agq_CM"
case akan = "ak"
case akanGhana = "ak_GH"
case albanian = "sq"
case albanianAlbania = "sq_AL"
case albanianKosovo = "sq_XK"
case albanianMacedonia = "sq_MK"
case amharic = "am"
case amharicEthiopia = "am_ET"
case arabic = "ar"
case arabicAlgeria = "ar_DZ"
case arabicBahrain = "ar_BH"
case arabicChad = "ar_TD"
case arabicComoros = "ar_KM"
case arabicDjibouti = "ar_DJ"
case arabicEgypt = "ar_EG"
case arabicEritrea = "ar_ER"
case arabicIraq = "ar_IQ"
case arabicIsrael = "ar_IL"
case arabicJordan = "ar_JO"
case arabicKuwait = "ar_KW"
case arabicLebanon = "ar_LB"
case arabicLibya = "ar_LY"
case arabicMauritania = "ar_MR"
case arabicMorocco = "ar_MA"
case arabicOman = "ar_OM"
case arabicPalestinianTerritories = "ar_PS"
case arabicQatar = "ar_QA"
case arabicSaudiArabia = "ar_SA"
case arabicSomalia = "ar_SO"
case arabicSouthSudan = "ar_SS"
case arabicSudan = "ar_SD"
case arabicSyria = "ar_SY"
case arabicTunisia = "ar_TN"
case arabicUnitedArabEmirates = "ar_AE"
case arabicWesternSahara = "ar_EH"
case arabicWorld = "ar_001"
case arabicYemen = "ar_YE"
case armenian = "hy"
case armenianArmenia = "hy_AM"
case assamese = "as"
case assameseIndia = "as_IN"
case asu = "asa"
case asuTanzania = "asa_TZ"
case azerbaijani = "az_Latn"
case azerbaijaniAzerbaijan = "az_Latn_AZ"
case azerbaijaniCyrillic = "az_Cyrl"
case azerbaijaniCyrillicAzerbaijan = "az_Cyrl_AZ"
case bafia = "ksf"
case bafiaCameroon = "ksf_CM"
case bambara = "bm_Latn"
case bambaraMali = "bm_Latn_ML"
case basaa = "bas"
case basaaCameroon = "bas_CM"
case basque = "eu"
case basqueSpain = "eu_ES"
case belarusian = "be"
case belarusianBelarus = "be_BY"
case bemba = "bem"
case bembaZambia = "bem_ZM"
case bena = "bez"
case benaTanzania = "bez_TZ"
case bengali = "bn"
case bengaliBangladesh = "bn_BD"
case engaliIndia = "bn_IN"
case bodo = "brx"
case bodoIndia = "brx_IN"
case bosnian = "bs_Latn"
case bosnianBosniaHerzegovina = "bs_Latn_BA"
case bosnianCyrillic = "bs_Cyrl"
case bosnianCyrillicBosniaHerzegovina = "bs_Cyrl_BA"
case breton = "br"
case bretonFrance = "br_FR"
case bulgarian = "bg"
case bulgarianBulgaria = "bg_BG"
case burmese = "my"
case burmeseMyanmarBurma = "my_MM"
case catalan = "ca"
case catalanAndorra = "ca_AD"
case catalanFrance = "ca_FR"
case catalanItaly = "ca_IT"
case catalanSpain = "ca_ES"
case centralAtlasTamazight = "tzm_Latn"
case centralAtlasTamazightMorocco = "tzm_Latn_MA"
case centralKurdish = "ckb"
case centralKurdishIran = "ckb_IR"
case centralKurdishIraq = "ckb_IQ"
case cherokee = "chr"
case cherokeeUnitedStates = "chr_US"
case chiga = "cgg"
case chigaUganda = "cgg_UG"
case chinese = "zh"
case chineseChina = "zh_Hans_CN"
case chineseHongKongSarChina = "zh_Hant_HK"
case chineseMacauSarChina = "zh_Hant_MO"
case chineseSimplified = "zh_Hans"
case chineseSimplifiedHongKongSarChina = "zh_Hans_HK"
case chineseSimplifiedMacauSarChina = "zh_Hans_MO"
case chineseSingapore = "zh_Hans_SG"
case chineseTaiwan = "zh_Hant_TW"
case chineseTraditional = "zh_Hant"
case colognian = "ksh"
case colognianGermany = "ksh_DE"
case cornish = "kw"
case cornishUnitedKingdom = "kw_GB"
case croatian = "hr"
case croatianBosniaHerzegovina = "hr_BA"
case croatianCroatia = "hr_HR"
case czech = "cs"
case czechCzechRepublic = "cs_CZ"
case danish = "da"
case danishDenmark = "da_DK"
case danishGreenland = "da_GL"
case duala = "dua"
case dualaCameroon = "dua_CM"
case dutch = "nl"
case dutchAruba = "nl_AW"
case dutchBelgium = "nl_BE"
case dutchCaribbeanNetherlands = "nl_BQ"
case dutchCuraao = "nl_CW"
case dutchNetherlands = "nl_NL"
case dutchSintMaarten = "nl_SX"
case dutchSuriname = "nl_SR"
case dzongkha = "dz"
case dzongkhaBhutan = "dz_BT"
case embu = "ebu"
case embuKenya = "ebu_KE"
case english = "en"
case englishAlbania = "en_AL"
case englishAmericanSamoa = "en_AS"
case englishAndorra = "en_AD"
case englishAnguilla = "en_AI"
case englishAntiguaBarbuda = "en_AG"
case englishAustralia = "en_AU"
case englishAustria = "en_AT"
case englishBahamas = "en_BS"
case englishBarbados = "en_BB"
case englishBelgium = "en_BE"
case englishBelize = "en_BZ"
case englishBermuda = "en_BM"
case englishBosniaHerzegovina = "en_BA"
case englishBotswana = "en_BW"
case englishBritishIndianOceanTerritory = "en_IO"
case englishBritishVirginIslands = "en_VG"
case englishCameroon = "en_CM"
case englishCanada = "en_CA"
case englishCaymanIslands = "en_KY"
case englishChristmasIsland = "en_CX"
case englishCocosKeelingIslands = "en_CC"
case englishCookIslands = "en_CK"
case englishCroatia = "en_HR"
case englishCyprus = "en_CY"
case englishCzechRepublic = "en_CZ"
case englishDenmark = "en_DK"
case englishDiegoGarcia = "en_DG"
case englishDominica = "en_DM"
case englishEritrea = "en_ER"
case englishEstonia = "en_EE"
case englishEurope = "en_150"
case englishFalklandIslands = "en_FK"
case englishFiji = "en_FJ"
case englishFinland = "en_FI"
case englishFrance = "en_FR"
case englishGambia = "en_GM"
case englishGermany = "en_DE"
case englishGhana = "en_GH"
case englishGibraltar = "en_GI"
case englishGreece = "en_GR"
case englishGrenada = "en_GD"
case englishGuam = "en_GU"
case englishGuernsey = "en_GG"
case englishGuyana = "en_GY"
case englishHongKongSarChina = "en_HK"
case englishHungary = "en_HU"
case englishIceland = "en_IS"
case englishIndia = "en_IN"
case englishIreland = "en_IE"
case englishIsleOfMan = "en_IM"
case englishIsrael = "en_IL"
case englishItaly = "en_IT"
case englishJamaica = "en_JM"
case englishJersey = "en_JE"
case englishKenya = "en_KE"
case englishKiribati = "en_KI"
case englishLatvia = "en_LV"
case englishLesotho = "en_LS"
case englishLiberia = "en_LR"
case englishLithuania = "en_LT"
case englishLuxembourg = "en_LU"
case englishMacauSarChina = "en_MO"
case englishMadagascar = "en_MG"
case englishMalawi = "en_MW"
case englishMalaysia = "en_MY"
case englishMalta = "en_MT"
case englishMarshallIslands = "en_MH"
case englishMauritius = "en_MU"
case englishMicronesia = "en_FM"
case englishMontenegro = "en_ME"
case englishMontserrat = "en_MS"
case englishNamibia = "en_NA"
case englishNauru = "en_NR"
case englishNetherlands = "en_NL"
case englishNewZealand = "en_NZ"
case englishNigeria = "en_NG"
case englishNiue = "en_NU"
case englishNorfolkIsland = "en_NF"
case englishNorthernMarianaIslands = "en_MP"
case englishNorway = "en_NO"
case englishPakistan = "en_PK"
case englishPalau = "en_PW"
case englishPapuaNewGuinea = "en_PG"
case englishPhilippines = "en_PH"
case englishPitcairnIslands = "en_PN"
case englishPoland = "en_PL"
case englishPortugal = "en_PT"
case englishPuertoRico = "en_PR"
case englishRomania = "en_RO"
case englishRussia = "en_RU"
case englishRwanda = "en_RW"
case englishSamoa = "en_WS"
case englishSeychelles = "en_SC"
case englishSierraLeone = "en_SL"
case englishSingapore = "en_SG"
case englishSintMaarten = "en_SX"
case englishSlovakia = "en_SK"
case englishSlovenia = "en_SI"
case englishSolomonIslands = "en_SB"
case englishSouthAfrica = "en_ZA"
case englishSouthSudan = "en_SS"
case englishSpain = "en_ES"
case englishStHelena = "en_SH"
case englishStKittsNevis = "en_KN"
case englishStLucia = "en_LC"
case englishStVincentGrenadines = "en_VC"
case englishSudan = "en_SD"
case englishSwaziland = "en_SZ"
case englishSweden = "en_SE"
case englishSwitzerland = "en_CH"
case englishTanzania = "en_TZ"
case englishTokelau = "en_TK"
case englishTonga = "en_TO"
case englishTrinidadTobago = "en_TT"
case englishTurkey = "en_TR"
case englishTurksCaicosIslands = "en_TC"
case englishTuvalu = "en_TV"
case englishUSOutlyingIslands = "en_UM"
case englishUSVirginIslands = "en_VI"
case englishUganda = "en_UG"
case englishUnitedKingdom = "en_GB"
case englishUnitedStates = "en_US"
case englishUnitedStatesComputer = "en_US_POSIX"
case englishVanuatu = "en_VU"
case englishWorld = "en_001"
case englishZambia = "en_ZM"
case englishZimbabwe = "en_ZW"
case esperanto = "eo"
case estonian = "et"
case estonianEstonia = "et_EE"
case ewe = "ee"
case eweGhana = "ee_GH"
case eweTogo = "ee_TG"
case ewondo = "ewo"
case ewondoCameroon = "ewo_CM"
case faroese = "fo"
case faroeseFaroeIslands = "fo_FO"
case filipino = "fil"
case filipinoPhilippines = "fil_PH"
case finnish = "fi"
case finnishFinland = "fi_FI"
case french = "fr"
case frenchAlgeria = "fr_DZ"
case frenchBelgium = "fr_BE"
case frenchBenin = "fr_BJ"
case frenchBurkinaFaso = "fr_BF"
case frenchBurundi = "fr_BI"
case frenchCameroon = "fr_CM"
case frenchCanada = "fr_CA"
case frenchCentralAfricanRepublic = "fr_CF"
case frenchChad = "fr_TD"
case frenchComoros = "fr_KM"
case frenchCongoBrazzaville = "fr_CG"
case frenchCongoKinshasa = "fr_CD"
case frenchCteDivoire = "fr_CI"
case frenchDjibouti = "fr_DJ"
case frenchEquatorialGuinea = "fr_GQ"
case frenchFrance = "fr_FR"
case frenchFrenchGuiana = "fr_GF"
case frenchFrenchPolynesia = "fr_PF"
case frenchGabon = "fr_GA"
case frenchGuadeloupe = "fr_GP"
case frenchGuinea = "fr_GN"
case frenchHaiti = "fr_HT"
case frenchLuxembourg = "fr_LU"
case frenchMadagascar = "fr_MG"
case frenchMali = "fr_ML"
case frenchMartinique = "fr_MQ"
case frenchMauritania = "fr_MR"
case frenchMauritius = "fr_MU"
case frenchMayotte = "fr_YT"
case frenchMonaco = "fr_MC"
case frenchMorocco = "fr_MA"
case frenchNewCaledonia = "fr_NC"
case frenchNiger = "fr_NE"
case frenchRunion = "fr_RE"
case frenchRwanda = "fr_RW"
case frenchSenegal = "fr_SN"
case frenchSeychelles = "fr_SC"
case frenchStBarthlemy = "fr_BL"
case frenchStMartin = "fr_MF"
case frenchStPierreMiquelon = "fr_PM"
case frenchSwitzerland = "fr_CH"
case frenchSyria = "fr_SY"
case frenchTogo = "fr_TG"
case frenchTunisia = "fr_TN"
case frenchVanuatu = "fr_VU"
case frenchWallisFutuna = "fr_WF"
case friulian = "fur"
case friulianItaly = "fur_IT"
case fulah = "ff"
case fulahCameroon = "ff_CM"
case fulahGuinea = "ff_GN"
case fulahMauritania = "ff_MR"
case fulahSenegal = "ff_SN"
case galician = "gl"
case galicianSpain = "gl_ES"
case ganda = "lg"
case gandaUganda = "lg_UG"
case georgian = "ka"
case georgianGeorgia = "ka_GE"
case german = "de"
case germanAustria = "de_AT"
case germanBelgium = "de_BE"
case germanGermany = "de_DE"
case germanLiechtenstein = "de_LI"
case germanLuxembourg = "de_LU"
case germanSwitzerland = "de_CH"
case greek = "el"
case greekCyprus = "el_CY"
case greekGreece = "el_GR"
case gujarati = "gu"
case gujaratiIndia = "gu_IN"
case gusii = "guz"
case gusiiKenya = "guz_KE"
case hausa = "ha_Latn"
case hausaGhana = "ha_Latn_GH"
case hausaNiger = "ha_Latn_NE"
case hausaNigeria = "ha_Latn_NG"
case hawaiian = "haw"
case hawaiianUnitedStates = "haw_US"
case hebrew = "he"
case hebrewIsrael = "he_IL"
case hindi = "hi"
case hindiIndia = "hi_IN"
case hungarian = "hu"
case hungarianHungary = "hu_HU"
case icelandic = "is"
case icelandicIceland = "is_IS"
case igbo = "ig"
case igboNigeria = "ig_NG"
case inariSami = "smn"
case inariSamiFinland = "smn_FI"
case indonesian = "id"
case indonesianIndonesia = "id_ID"
case inuktitut = "iu"
case inuktitutUnifiedCanadianAboriginalSyllabics = "iu_Cans"
case inuktitutUnifiedCanadianAboriginalSyllabicsCanada = "iu_Cans_CA"
case irish = "ga"
case irishIreland = "ga_IE"
case italian = "it"
case italianItaly = "it_IT"
case italianSanMarino = "it_SM"
case italianSwitzerland = "it_CH"
case japanese = "ja"
case japaneseJapan = "ja_JP"
case jolaFonyi = "dyo"
case jolaFonyiSenegal = "dyo_SN"
case kabuverdianu = "kea"
case kabuverdianuCapeVerde = "kea_CV"
case kabyle = "kab"
case kabyleAlgeria = "kab_DZ"
case kako = "kkj"
case kakoCameroon = "kkj_CM"
case kalaallisut = "kl"
case kalaallisutGreenland = "kl_GL"
case kalenjin = "kln"
case kalenjinKenya = "kln_KE"
case kamba = "kam"
case kambaKenya = "kam_KE"
case kannada = "kn"
case kannadaIndia = "kn_IN"
case kashmiri = "ks"
case kashmiriArabic = "ks_Arab"
case kashmiriArabicIndia = "ks_Arab_IN"
case kazakh = "kk_Cyrl"
case kazakhKazakhstan = "kk_Cyrl_KZ"
case khmer = "km"
case khmerCambodia = "km_KH"
case kikuyu = "ki"
case kikuyuKenya = "ki_KE"
case kinyarwanda = "rw"
case kinyarwandaRwanda = "rw_RW"
case konkani = "kok"
case konkaniIndia = "kok_IN"
case korean = "ko"
case koreanNorthKorea = "ko_KP"
case koreanSouthKorea = "ko_KR"
case koyraChiini = "khq"
case koyraChiiniMali = "khq_ML"
case koyraboroSenni = "ses"
case koyraboroSenniMali = "ses_ML"
case kwasio = "nmg"
case kwasioCameroon = "nmg_CM"
case kyrgyz = "ky_Cyrl"
case kyrgyzKyrgyzstan = "ky_Cyrl_KG"
case lakota = "lkt"
case lakotaUnitedStates = "lkt_US"
case langi = "lag"
case langiTanzania = "lag_TZ"
case lao = "lo"
case laoLaos = "lo_LA"
case latvian = "lv"
case latvianLatvia = "lv_LV"
case lingala = "ln"
case lingalaAngola = "ln_AO"
case lingalaCentralAfricanRepublic = "ln_CF"
case lingalaCongoBrazzaville = "ln_CG"
case lingalaCongoKinshasa = "ln_CD"
case lithuanian = "lt"
case lithuanianLithuania = "lt_LT"
case lowerSorbian = "dsb"
case lowerSorbianGermany = "dsb_DE"
case lubaKatanga = "lu"
case lubaKatangaCongoKinshasa = "lu_CD"
case luo = "luo"
case luoKenya = "luo_KE"
case luxembourgish = "lb"
case luxembourgishLuxembourg = "lb_LU"
case luyia = "luy"
case luyiaKenya = "luy_KE"
case macedonian = "mk"
case macedonianMacedonia = "mk_MK"
case machame = "jmc"
case machameTanzania = "jmc_TZ"
case makhuwaMeetto = "mgh"
case makhuwaMeettoMozambique = "mgh_MZ"
case makonde = "kde"
case makondeTanzania = "kde_TZ"
case malagasy = "mg"
case malagasyMadagascar = "mg_MG"
case malay = "ms_Latn"
case malayArabic = "ms_Arab"
case malayArabicBrunei = "ms_Arab_BN"
case malayArabicMalaysia = "ms_Arab_MY"
case malayBrunei = "ms_Latn_BN"
case malayMalaysia = "ms_Latn_MY"
case malaySingapore = "ms_Latn_SG"
case malayalam = "ml"
case malayalamIndia = "ml_IN"
case maltese = "mt"
case malteseMalta = "mt_MT"
case manx = "gv"
case manxIsleOfMan = "gv_IM"
case marathi = "mr"
case marathiIndia = "mr_IN"
case masai = "mas"
case masaiKenya = "mas_KE"
case masaiTanzania = "mas_TZ"
case meru = "mer"
case meruKenya = "mer_KE"
case meta = "mgo"
case metaCameroon = "mgo_CM"
case mongolian = "mn_Cyrl"
case mongolianMongolia = "mn_Cyrl_MN"
case morisyen = "mfe"
case morisyenMauritius = "mfe_MU"
case mundang = "mua"
case mundangCameroon = "mua_CM"
case nama = "naq"
case namaNamibia = "naq_NA"
case nepali = "ne"
case nepaliIndia = "ne_IN"
case nepaliNepal = "ne_NP"
case ngiemboon = "nnh"
case ngiemboonCameroon = "nnh_CM"
case ngomba = "jgo"
case ngombaCameroon = "jgo_CM"
case northNdebele = "nd"
case northNdebeleZimbabwe = "nd_ZW"
case northernSami = "se"
case northernSamiFinland = "se_FI"
case northernSamiNorway = "se_NO"
case northernSamiSweden = "se_SE"
case norwegianBokml = "nb"
case norwegianBokmlNorway = "nb_NO"
case norwegianBokmlSvalbardJanMayen = "nb_SJ"
case norwegianNynorsk = "nn"
case norwegianNynorskNorway = "nn_NO"
case nuer = "nus"
case nuerSudan = "nus_SD"
case nyankole = "nyn"
case nyankoleUganda = "nyn_UG"
case oriya = "or"
case oriyaIndia = "or_IN"
case oromo = "om"
case oromoEthiopia = "om_ET"
case oromoKenya = "om_KE"
case ossetic = "os"
case osseticGeorgia = "os_GE"
case osseticRussia = "os_RU"
case pashto = "ps"
case pashtoAfghanistan = "ps_AF"
case persian = "fa"
case persianAfghanistan = "fa_AF"
case persianIran = "fa_IR"
case polish = "pl"
case polishPoland = "pl_PL"
case portuguese = "pt"
case portugueseAngola = "pt_AO"
case portugueseBrazil = "pt_BR"
case portugueseCapeVerde = "pt_CV"
case portugueseGuineaBissau = "pt_GW"
case portugueseMacauSarChina = "pt_MO"
case portugueseMozambique = "pt_MZ"
case portuguesePortugal = "pt_PT"
case portugueseSoTomPrncipe = "pt_ST"
case portugueseTimorLeste = "pt_TL"
case punjabi = "pa_Guru"
case punjabiArabic = "pa_Arab"
case punjabiArabicPakistan = "pa_Arab_PK"
case punjabiIndia = "pa_Guru_IN"
case quechua = "qu"
case quechuaBolivia = "qu_BO"
case quechuaEcuador = "qu_EC"
case quechuaPeru = "qu_PE"
case romanian = "ro"
case romanianMoldova = "ro_MD"
case romanianRomania = "ro_RO"
case romansh = "rm"
case romanshSwitzerland = "rm_CH"
case rombo = "rof"
case romboTanzania = "rof_TZ"
case rundi = "rn"
case rundiBurundi = "rn_BI"
case russian = "ru"
case russianBelarus = "ru_BY"
case russianKazakhstan = "ru_KZ"
case russianKyrgyzstan = "ru_KG"
case russianMoldova = "ru_MD"
case russianRussia = "ru_RU"
case russianUkraine = "ru_UA"
case rwa = "rwk"
case rwaTanzania = "rwk_TZ"
case sakha = "sah"
case sakhaRussia = "sah_RU"
case samburu = "saq"
case samburuKenya = "saq_KE"
case sango = "sg"
case sangoCentralAfricanRepublic = "sg_CF"
case sangu = "sbp"
case sanguTanzania = "sbp_TZ"
case scottishGaelic = "gd"
case scottishGaelicUnitedKingdom = "gd_GB"
case sena = "seh"
case senaMozambique = "seh_MZ"
case serbian = "sr_Cyrl"
case serbianBosniaHerzegovina = "sr_Cyrl_BA"
case serbianKosovo = "sr_Cyrl_XK"
case serbianLatin = "sr_Latn"
case serbianLatinBosniaHerzegovina = "sr_Latn_BA"
case serbianLatinKosovo = "sr_Latn_XK"
case serbianLatinMontenegro = "sr_Latn_ME"
case serbianLatinSerbia = "sr_Latn_RS"
case serbianMontenegro = "sr_Cyrl_ME"
case serbianSerbia = "sr_Cyrl_RS"
case shambala = "ksb"
case shambalaTanzania = "ksb_TZ"
case shona = "sn"
case shonaZimbabwe = "sn_ZW"
case sichuanYi = "ii"
case sichuanYiChina = "ii_CN"
case sinhala = "si"
case sinhalaSriLanka = "si_LK"
case slovak = "sk"
case slovakSlovakia = "sk_SK"
case slovenian = "sl"
case slovenianSlovenia = "sl_SI"
case soga = "xog"
case sogaUganda = "xog_UG"
case somali = "so"
case somaliDjibouti = "so_DJ"
case somaliEthiopia = "so_ET"
case somaliKenya = "so_KE"
case somaliSomalia = "so_SO"
case spanish = "es"
case spanishArgentina = "es_AR"
case spanishBolivia = "es_BO"
case spanishCanaryIslands = "es_IC"
case spanishCeutaMelilla = "es_EA"
case spanishChile = "es_CL"
case spanishColombia = "es_CO"
case spanishCostaRica = "es_CR"
case spanishCuba = "es_CU"
case spanishDominicanRepublic = "es_DO"
case spanishEcuador = "es_EC"
case spanishElSalvador = "es_SV"
case spanishEquatorialGuinea = "es_GQ"
case spanishGuatemala = "es_GT"
case spanishHonduras = "es_HN"
case spanishLatinAmerica = "es_419"
case spanishMexico = "es_MX"
case spanishNicaragua = "es_NI"
case spanishPanama = "es_PA"
case spanishParaguay = "es_PY"
case spanishPeru = "es_PE"
case spanishPhilippines = "es_PH"
case spanishPuertoRico = "es_PR"
case spanishSpain = "es_ES"
case spanishUnitedStates = "es_US"
case spanishUruguay = "es_UY"
case spanishVenezuela = "es_VE"
case standardMoroccanTamazight = "zgh"
case standardMoroccanTamazightMorocco = "zgh_MA"
case swahili = "sw"
case swahiliCongoKinshasa = "sw_CD"
case swahiliKenya = "sw_KE"
case swahiliTanzania = "sw_TZ"
case swahiliUganda = "sw_UG"
case swedish = "sv"
case swedishlandIslands = "sv_AX"
case swedishFinland = "sv_FI"
case swedishSweden = "sv_SE"
case swissGerman = "gsw"
case swissGermanFrance = "gsw_FR"
case swissGermanLiechtenstein = "gsw_LI"
case swissGermanSwitzerland = "gsw_CH"
case tachelhit = "shi_Latn"
case tachelhitMorocco = "shi_Latn_MA"
case tachelhitTifinagh = "shi_Tfng"
case tachelhitTifinaghMorocco = "shi_Tfng_MA"
case taita = "dav"
case taitaKenya = "dav_KE"
case tajik = "tg_Cyrl"
case tajikTajikistan = "tg_Cyrl_TJ"
case tamil = "ta"
case tamilIndia = "ta_IN"
case tamilMalaysia = "ta_MY"
case tamilSingapore = "ta_SG"
case tamilSriLanka = "ta_LK"
case tasawaq = "twq"
case tasawaqNiger = "twq_NE"
case telugu = "te"
case teluguIndia = "te_IN"
case teso = "teo"
case tesoKenya = "teo_KE"
case tesoUganda = "teo_UG"
case thai = "th"
case thaiThailand = "th_TH"
case tibetan = "bo"
case tibetanChina = "bo_CN"
case tibetanIndia = "bo_IN"
case tigrinya = "ti"
case tigrinyaEritrea = "ti_ER"
case tigrinyaEthiopia = "ti_ET"
case tongan = "to"
case tonganTonga = "to_TO"
case turkish = "tr"
case turkishCyprus = "tr_CY"
case turkishTurkey = "tr_TR"
case turkmen = "tk_Latn"
case turkmenTurkmenistan = "tk_Latn_TM"
case ukrainian = "uk"
case ukrainianUkraine = "uk_UA"
case upperSorbian = "hsb"
case upperSorbianGermany = "hsb_DE"
case urdu = "ur"
case urduIndia = "ur_IN"
case urduPakistan = "ur_PK"
case uyghur = "ug"
case uyghurArabic = "ug_Arab"
case uyghurArabicChina = "ug_Arab_CN"
case uzbek = "uz_Cyrl"
case uzbekArabic = "uz_Arab"
case uzbekArabicAfghanistan = "uz_Arab_AF"
case uzbekLatin = "uz_Latn"
case uzbekLatinUzbekistan = "uz_Latn_UZ"
case uzbekUzbekistan = "uz_Cyrl_UZ"
case vai = "vai_Vaii"
case vaiLatin = "vai_Latn"
case vaiLatinLiberia = "vai_Latn_LR"
case vaiLiberia = "vai_Vaii_LR"
case vietnamese = "vi"
case vietnameseVietnam = "vi_VN"
case vunjo = "vun"
case vunjoTanzania = "vun_TZ"
case walser = "wae"
case walserSwitzerland = "wae_CH"
case welsh = "cy"
case welshUnitedKingdom = "cy_GB"
case westernFrisian = "fy"
case westernFrisianNetherlands = "fy_NL"
case yangben = "yav"
case yangbenCameroon = "yav_CM"
case yiddish = "yi"
case yiddishWorld = "yi_001"
case yoruba = "yo"
case yorubaBenin = "yo_BJ"
case yorubaNigeria = "yo_NG"
case zarma = "dje"
case zarmaNiger = "dje_NE"
case zulu = "zu"
case zuluSouthAfrica = "zu_ZA"
/// Return a valid `Locale` instance from current selected locale enum
public func toLocale() -> Locale {
switch self {
case .current: return Locale.current
case .autoUpdating: return Locale.autoupdatingCurrent
default: return Locale(identifier: rawValue)
}
}
}

View File

@@ -0,0 +1,152 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
import Foundation
// MARK: - Weekday
/// This define the weekdays for some functions.
public enum WeekDay: Int {
case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
/// Returns the name of the day given a specific locale.
/// For example, for the `Friday` enum value, the en_AU locale would return "Friday" and fr_FR would return "samedi"
///
/// - Parameter locale: locale of the output, omit to use the `defaultRegion`'s locale.
/// - Returns: display name
public func name(style: SymbolFormatStyle = .`default`, locale: LocaleConvertible = SwiftDate.defaultRegion.locale) -> String {
let region = Region(calendar: SwiftDate.defaultRegion.calendar, zone: SwiftDate.defaultRegion.timeZone, locale: locale)
let formatter = DateFormatter.sharedFormatter(forRegion: region, format: nil)
let idx = (self.rawValue - 1)
switch style {
case .default: return formatter.weekdaySymbols[idx]
case .defaultStandalone: return formatter.standaloneWeekdaySymbols[idx]
case .short: return formatter.shortWeekdaySymbols[idx]
case .standaloneShort: return formatter.shortStandaloneWeekdaySymbols[idx]
case .veryShort: return formatter.veryShortWeekdaySymbols[idx]
case .standaloneVeryShort: return formatter.veryShortStandaloneWeekdaySymbols[idx]
}
}
/// Adds a number of days to the current weekday and returns the new weekday.
///
/// - Parameter months: number of months to add
/// - Returns: new month.
public func add(days: Int) -> WeekDay {
let normalized = days % 7
return WeekDay(rawValue: ((self.rawValue + normalized + 7 - 1) % 7) + 1)!
}
/// Subtracts a number of days from the current weekday and returns the new weekday.
///
/// - Parameter months: number of days to subtract. May be negative, in which case it will be added
/// - Returns: new weekday.
public func subtract(days: Int) -> WeekDay {
return add(days: -(days % 7))
}
}
// MARK: - Year
public struct Year: CustomStringConvertible, Equatable {
let year: Int
public var description: String {
return "\(self.year)"
}
/// Constructs a `Year` from the passed value.
///
/// - Parameter year: year value. Can be negative.
public init(_ year: Int) {
self.year = year
}
/// Returns whether this year is a leap year
///
/// - Returns: A boolean indicating whether this year is a leap year
public func isLeap() -> Bool {
return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0)
}
/// Returns the number of days in this year
///
/// - Returns: The number of days in this year
public func numberOfDays() -> Int {
return self.isLeap() ? 366 : 365
}
}
// MARK: - Month
/// Defines months in a year
public enum Month: Int, CustomStringConvertible, Equatable {
case january = 0, february, march, april, may, june, july, august, september, october, november, december
public var description: String {
return self.name()
}
/// Returns the name of the month given a specific locale.
/// For example, for the `January` enum value, the en_AU locale would return "January" and fr_FR would return "janvier"
///
/// - Parameter locale: locale of the output, omit to use the `defaultRegion`'s locale.
/// - Returns: display name
public func name(style: SymbolFormatStyle = .`default`, locale: LocaleConvertible = SwiftDate.defaultRegion.locale) -> String {
let region = Region(calendar: SwiftDate.defaultRegion.calendar, zone: SwiftDate.defaultRegion.timeZone, locale: locale)
let formatter = DateFormatter.sharedFormatter(forRegion: region, format: nil)
switch style {
case .default: return formatter.monthSymbols[self.rawValue]
case .defaultStandalone: return formatter.standaloneMonthSymbols[self.rawValue]
case .short: return formatter.shortMonthSymbols[self.rawValue]
case .standaloneShort: return formatter.shortStandaloneMonthSymbols[self.rawValue]
case .veryShort: return formatter.veryShortMonthSymbols[self.rawValue]
case .standaloneVeryShort: return formatter.veryShortStandaloneMonthSymbols[self.rawValue]
}
}
/// Adds a number of months to the current month and returns the new month.
///
/// - Parameter months: number of months to add
/// - Returns: new month.
public func add(months: Int) -> Month {
let normalized = months % 12
return Month(rawValue: (self.rawValue + normalized + 12) % 12)!
}
/// Subtracts a number of months from the current month and returns the new month.
///
/// - Parameter months: number of months to subtract. May be negative, in which case it will be added
/// - Returns: new month.
public func subtract(months: Int) -> Month {
return add(months: -(months % 12))
}
/// Returns the number of days in a this month for a given year
///
/// - Parameter year: reference year.
/// - Returns: The number of days in this month.
public func numberOfDays(year: Int) -> Int {
switch self {
case .february:
return Year(year).isLeap() ? 29 : 28
case .april, .june, .september, .november:
return 30
default:
return 31
}
}
}

View File

@@ -0,0 +1,465 @@
//
// SwiftDate
// Parse, validate, manipulate, and display dates, time and timezones in Swift
//
// Created by Daniele Margutti
// - Web: https://www.danielemargutti.com
// - Twitter: https://twitter.com/danielemargutti
// - Mail: hello@danielemargutti.com
//
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
//
import Foundation
public protocol ZoneConvertible {
func toTimezone() -> TimeZone
}
extension TimeZone: ZoneConvertible {
public func toTimezone() -> TimeZone {
return self
}
}
// swiftlint:disable type_body_length
public enum Zones: String, ZoneConvertible {
case current = "Current"
case autoUpdating = "CurrentAutoUpdating"
case africaAbidjan = "Africa/Abidjan"
case africaAccra = "Africa/Accra"
case africaAddisAbaba = "Africa/Addis_Ababa"
case africaAlgiers = "Africa/Algiers"
case africaAsmara = "Africa/Asmara"
case africaBamako = "Africa/Bamako"
case africaBangui = "Africa/Bangui"
case africaBanjul = "Africa/Banjul"
case africaBissau = "Africa/Bissau"
case africaBlantyre = "Africa/Blantyre"
case africaBrazzaville = "Africa/Brazzaville"
case africaBujumbura = "Africa/Bujumbura"
case africaCairo = "Africa/Cairo"
case africaCasablanca = "Africa/Casablanca"
case africaCeuta = "Africa/Ceuta"
case africaConakry = "Africa/Conakry"
case africaDakar = "Africa/Dakar"
case africaDarEsSalaam = "Africa/Dar_es_Salaam"
case africaDjibouti = "Africa/Djibouti"
case africaDouala = "Africa/Douala"
case africaElAaiun = "Africa/El_Aaiun"
case africaFreetown = "Africa/Freetown"
case africaGaborone = "Africa/Gaborone"
case africaHarare = "Africa/Harare"
case africaJohannesburg = "Africa/Johannesburg"
case africaJuba = "Africa/Juba"
case africaKampala = "Africa/Kampala"
case africaKhartoum = "Africa/Khartoum"
case fricaKigali = "Africa/Kigali"
case africaKinshasa = "Africa/Kinshasa"
case africaLagos = "Africa/Lagos"
case africaLibreville = "Africa/Libreville"
case africaLome = "Africa/Lome"
case africaLuanda = "Africa/Luanda"
case africaLubumbashi = "Africa/Lubumbashi"
case africaLusaka = "Africa/Lusaka"
case africaMalabo = "Africa/Malabo"
case africaMaputo = "Africa/Maputo"
case africaMaseru = "Africa/Maseru"
case africaMbabane = "Africa/Mbabane"
case africaMogadishu = "Africa/Mogadishu"
case africaMonrovia = "Africa/Monrovia"
case africaNairobi = "Africa/Nairobi"
case africaNdjamena = "Africa/Ndjamena"
case africaNiamey = "Africa/Niamey"
case africaNouakchott = "Africa/Nouakchott"
case africaOuagadougou = "Africa/Ouagadougou"
case africaPortoNovo = "Africa/Porto-Novo"
case africaSaoTome = "Africa/Sao_Tome"
case africaTripoli = "Africa/Tripoli"
case africaTunis = "Africa/Tunis"
case africaWindhoek = "Africa/Windhoek"
case americaAdak = "America/Adak"
case americaAnchorage = "America/Anchorage"
case americaAnguilla = "America/Anguilla"
case americaAntigua = "America/Antigua"
case americaAraguaina = "America/Araguaina"
case americaArgentinaBuenosAires = "America/Argentina/Buenos_Aires"
case americaArgentinaCatamarca = "America/Argentina/Catamarca"
case americaArgentinaCordoba = "America/Argentina/Cordoba"
case americaArgentinaJujuy = "America/Argentina/Jujuy"
case americaArgentinaLaRioja = "America/Argentina/La_Rioja"
case americaArgentinaMendoza = "America/Argentina/Mendoza"
case americaArgentinaRioGallegos = "America/Argentina/Rio_Gallegos"
case americaArgentinaSalta = "America/Argentina/Salta"
case americaArgentinaSanJuan = "America/Argentina/San_Juan"
case americaArgentinaSanLuis = "America/Argentina/San_Luis"
case americaArgentinaTucuman = "America/Argentina/Tucuman"
case americaArgentinaUshuaia = "America/Argentina/Ushuaia"
case americaAruba = "America/Aruba"
case americaAsuncion = "America/Asuncion"
case americaAtikokan = "America/Atikokan"
case americaBahia = "America/Bahia"
case americaBahiaBanderas = "America/Bahia_Banderas"
case americaBarbados = "America/Barbados"
case americaBelem = "America/Belem"
case americaBelize = "America/Belize"
case americaBlancSablon = "America/Blanc-Sablon"
case americaBoaVista = "America/Boa_Vista"
case americaBogota = "America/Bogota"
case americaBoise = "America/Boise"
case americaCambridgeBay = "America/Cambridge_Bay"
case americaCampoGrande = "America/Campo_Grande"
case americaCancun = "America/Cancun"
case americaCaracas = "America/Caracas"
case americaCayenne = "America/Cayenne"
case americaCayman = "America/Cayman"
case americaChicago = "America/Chicago"
case americaChihuahua = "America/Chihuahua"
case americaCostaRica = "America/Costa_Rica"
case americaCreston = "America/Creston"
case americaCuiaba = "America/Cuiaba"
case americaCuracao = "America/Curacao"
case americaDanmarkshavn = "America/Danmarkshavn"
case americaDawson = "America/Dawson"
case americaDawsonCreek = "America/Dawson_Creek"
case americaDenver = "America/Denver"
case americaDetroit = "America/Detroit"
case americaDominica = "America/Dominica"
case americaEdmonton = "America/Edmonton"
case americaEirunepe = "America/Eirunepe"
case americaElSalvador = "America/El_Salvador"
case americaFortNelson = "America/Fort_Nelson"
case americaFortaleza = "America/Fortaleza"
case americaGlaceBay = "America/Glace_Bay"
case americaGodthab = "America/Godthab"
case americaGooseBay = "America/Goose_Bay"
case americaGrandTurk = "America/Grand_Turk"
case americaGrenada = "America/Grenada"
case americaGuadeloupe = "America/Guadeloupe"
case americaGuatemala = "America/Guatemala"
case americaGuayaquil = "America/Guayaquil"
case americaGuyana = "America/Guyana"
case americaHalifax = "America/Halifax"
case americaHavana = "America/Havana"
case americaHermosillo = "America/Hermosillo"
case americaIndianaIndianapolis = "America/Indiana/Indianapolis"
case americaIndianaKnox = "America/Indiana/Knox"
case americaIndianaMarengo = "America/Indiana/Marengo"
case americaIndianaPetersburg = "America/Indiana/Petersburg"
case americaIndianaTellCity = "America/Indiana/Tell_City"
case americaIndianaVevay = "America/Indiana/Vevay"
case americaIndianaVincennes = "America/Indiana/Vincennes"
case americaIndianaWinamac = "America/Indiana/Winamac"
case americaInuvik = "America/Inuvik"
case americaIqaluit = "America/Iqaluit"
case americaJamaica = "America/Jamaica"
case americaJuneau = "America/Juneau"
case americaKentuckyLouisville = "America/Kentucky/Louisville"
case americaKentuckyMonticello = "America/Kentucky/Monticello"
case americaKralendijk = "America/Kralendijk"
case americaLaPaz = "America/La_Paz"
case americaLima = "America/Lima"
case americaLosAngeles = "America/Los_Angeles"
case americaLowerPrinces = "America/Lower_Princes"
case americaMaceio = "America/Maceio"
case americaManagua = "America/Managua"
case americaManaus = "America/Manaus"
case americaMarigot = "America/Marigot"
case americaMartinique = "America/Martinique"
case americaMatamoros = "America/Matamoros"
case americaMazatlan = "America/Mazatlan"
case americaMenominee = "America/Menominee"
case americaMerida = "America/Merida"
case americaMetlakatla = "America/Metlakatla"
case americaMexicoCity = "America/Mexico_City"
case americaMiquelon = "America/Miquelon"
case americaMoncton = "America/Moncton"
case americaMonterrey = "America/Monterrey"
case americaMontevideo = "America/Montevideo"
case americaMontreal = "America/Montreal"
case americaMontserrat = "America/Montserrat"
case americaNassau = "America/Nassau"
case americaNewYork = "America/New_York"
case americaNipigon = "America/Nipigon"
case americaNome = "America/Nome"
case americaNoronha = "America/Noronha"
case americaNorthDakotaBeulah = "America/North_Dakota/Beulah"
case americaNorthDakotaCenter = "America/North_Dakota/Center"
case americaNorthDakotaNewSalem = "America/North_Dakota/New_Salem"
case americaOjinaga = "America/Ojinaga"
case americaPanama = "America/Panama"
case americaPangnirtung = "America/Pangnirtung"
case americaParamaribo = "America/Paramaribo"
case americaPhoenix = "America/Phoenix"
case americaPortAuPrince = "America/Port-au-Prince"
case americaPortOfSpain = "America/Port_of_Spain"
case americaPortoVelho = "America/Porto_Velho"
case americaPuertoRico = "America/Puerto_Rico"
case americaRainyRiver = "America/Rainy_River"
case americaRankinInlet = "America/Rankin_Inlet"
case americaRecife = "America/Recife"
case americaRegina = "America/Regina"
case americaResolute = "America/Resolute"
case americaRioBranco = "America/Rio_Branco"
case americaSantaIsabel = "America/Santa_Isabel"
case americaSantarem = "America/Santarem"
case americaSantiago = "America/Santiago"
case americaSantoDomingo = "America/Santo_Domingo"
case americaSaoPaulo = "America/Sao_Paulo"
case americaScoresbysund = "America/Scoresbysund"
case americaShiprock = "America/Shiprock"
case americaSitka = "America/Sitka"
case americaStBarthelemy = "America/St_Barthelemy"
case americaStJohns = "America/St_Johns"
case americaStKitts = "America/St_Kitts"
case americaStLucia = "America/St_Lucia"
case americaStThomas = "America/St_Thomas"
case americaStVincent = "America/St_Vincent"
case americaSwiftCurrent = "America/Swift_Current"
case americaTegucigalpa = "America/Tegucigalpa"
case americaThule = "America/Thule"
case americaThunderBay = "America/Thunder_Bay"
case americaTijuana = "America/Tijuana"
case americaToronto = "America/Toronto"
case americaTortola = "America/Tortola"
case americaVancouver = "America/Vancouver"
case americaWhitehorse = "America/Whitehorse"
case americaWinnipeg = "America/Winnipeg"
case americaYakutat = "America/Yakutat"
case americaYellowknife = "America/Yellowknife"
case antarcticaCasey = "Antarctica/Casey"
case antarcticaDavis = "Antarctica/Davis"
case antarcticaDumontdurville = "Antarctica/DumontDUrville"
case antarcticaMacquarie = "Antarctica/Macquarie"
case antarcticaMawson = "Antarctica/Mawson"
case antarcticaMcmurdo = "Antarctica/McMurdo"
case antarcticaPalmer = "Antarctica/Palmer"
case antarcticaRothera = "Antarctica/Rothera"
case antarcticaSouthPole = "Antarctica/South_Pole"
case antarcticaSyowa = "Antarctica/Syowa"
case antarcticaTroll = "Antarctica/Troll"
case antarcticaVostok = "Antarctica/Vostok"
case arcticLongyearbyen = "Arctic/Longyearbyen"
case asiaAden = "Asia/Aden"
case asiaAlmaty = "Asia/Almaty"
case asiaAmman = "Asia/Amman"
case asiaAnadyr = "Asia/Anadyr"
case asiaAqtau = "Asia/Aqtau"
case asiaAqtobe = "Asia/Aqtobe"
case asiaAshgabat = "Asia/Ashgabat"
case asiaBaghdad = "Asia/Baghdad"
case asiaBahrain = "Asia/Bahrain"
case asiaBaku = "Asia/Baku"
case asiaBangkok = "Asia/Bangkok"
case asiaBeirut = "Asia/Beirut"
case asiaBishkek = "Asia/Bishkek"
case asiaBrunei = "Asia/Brunei"
case asiaChita = "Asia/Chita"
case asiaChoibalsan = "Asia/Choibalsan"
case asiaChongqing = "Asia/Chongqing"
case asiaColombo = "Asia/Colombo"
case asiaDamascus = "Asia/Damascus"
case asiaDhaka = "Asia/Dhaka"
case asiaDili = "Asia/Dili"
case asiaDubai = "Asia/Dubai"
case asiaDushanbe = "Asia/Dushanbe"
case asiaGaza = "Asia/Gaza"
case asiaHarbin = "Asia/Harbin"
case asiaHebron = "Asia/Hebron"
case asiaHoChiMinh = "Asia/Ho_Chi_Minh"
case asiaSaigon = "Asia/Saigon"
case asiaHongKong = "Asia/Hong_Kong"
case asiaHovd = "Asia/Hovd"
case asiaIrkutsk = "Asia/Irkutsk"
case asiaJakarta = "Asia/Jakarta"
case asiaJayapura = "Asia/Jayapura"
case asiaJerusalem = "Asia/Jerusalem"
case asiaKabul = "Asia/Kabul"
case asiaKamchatka = "Asia/Kamchatka"
case asiaKarachi = "Asia/Karachi"
case asiaKashgar = "Asia/Kashgar"
case asiaKathmandu = "Asia/Kathmandu"
case asiaKatmandu = "Asia/Katmandu"
case asiaKhandyga = "Asia/Khandyga"
case asiaKolkata = "Asia/Kolkata"
case asiaKrasnoyarsk = "Asia/Krasnoyarsk"
case asiaKualaLumpur = "Asia/Kuala_Lumpur"
case asiaKuching = "Asia/Kuching"
case asiaKuwait = "Asia/Kuwait"
case asiaMacau = "Asia/Macau"
case asiaMagadan = "Asia/Magadan"
case asiaMakassar = "Asia/Makassar"
case asiaManila = "Asia/Manila"
case asiaMuscat = "Asia/Muscat"
case asiaNicosia = "Asia/Nicosia"
case asiaNovokuznetsk = "Asia/Novokuznetsk"
case asiaNovosibirsk = "Asia/Novosibirsk"
case asiaOmsk = "Asia/Omsk"
case asiaOral = "Asia/Oral"
case asiaPhnomPenh = "Asia/Phnom_Penh"
case asiaPontianak = "Asia/Pontianak"
case asiaPyongyang = "Asia/Pyongyang"
case asiaQatar = "Asia/Qatar"
case asiaQyzylorda = "Asia/Qyzylorda"
case asiaRangoon = "Asia/Rangoon"
case asiaRiyadh = "Asia/Riyadh"
case asiaSakhalin = "Asia/Sakhalin"
case asiaSamarkand = "Asia/Samarkand"
case asiaSeoul = "Asia/Seoul"
case asiaShanghai = "Asia/Shanghai"
case asiaSingapore = "Asia/Singapore"
case asiaSrednekolymsk = "Asia/Srednekolymsk"
case asiaTaipei = "Asia/Taipei"
case asiaTashkent = "Asia/Tashkent"
case asiaTbilisi = "Asia/Tbilisi"
case asiaTehran = "Asia/Tehran"
case asiaThimphu = "Asia/Thimphu"
case asiaTokyo = "Asia/Tokyo"
case asiaUlaanbaatar = "Asia/Ulaanbaatar"
case asiaUrumqi = "Asia/Urumqi"
case asiaUstNera = "Asia/Ust-Nera"
case asiaVientiane = "Asia/Vientiane"
case asiaVladivostok = "Asia/Vladivostok"
case asiaYakutsk = "Asia/Yakutsk"
case asiaYekaterinburg = "Asia/Yekaterinburg"
case asiaYerevan = "Asia/Yerevan"
case atlanticAzores = "Atlantic/Azores"
case atlanticBermuda = "Atlantic/Bermuda"
case atlanticCanary = "Atlantic/Canary"
case atlanticCapeVerde = "Atlantic/Cape_Verde"
case atlanticFaroe = "Atlantic/Faroe"
case atlanticMadeira = "Atlantic/Madeira"
case atlanticReykjavik = "Atlantic/Reykjavik"
case atlanticSouthGeorgia = "Atlantic/South_Georgia"
case atlanticStHelena = "Atlantic/St_Helena"
case atlanticStanley = "Atlantic/Stanley"
case australiaAdelaide = "Australia/Adelaide"
case australiaBrisbane = "Australia/Brisbane"
case australiaBrokenHill = "Australia/Broken_Hill"
case australiaCurrie = "Australia/Currie"
case australiaDarwin = "Australia/Darwin"
case australiaEucla = "Australia/Eucla"
case australiaHobart = "Australia/Hobart"
case australiaLindeman = "Australia/Lindeman"
case australiaLordHowe = "Australia/Lord_Howe"
case australiaMelbourne = "Australia/Melbourne"
case australiaPerth = "Australia/Perth"
case australiaSydney = "Australia/Sydney"
case europeAmsterdam = "Europe/Amsterdam"
case europeAndorra = "Europe/Andorra"
case europeAthens = "Europe/Athens"
case europeBelgrade = "Europe/Belgrade"
case europeBerlin = "Europe/Berlin"
case europeBratislava = "Europe/Bratislava"
case europeBrussels = "Europe/Brussels"
case europeBucharest = "Europe/Bucharest"
case europeBudapest = "Europe/Budapest"
case europeBusingen = "Europe/Busingen"
case europeChisinau = "Europe/Chisinau"
case europeCopenhagen = "Europe/Copenhagen"
case europeDublin = "Europe/Dublin"
case europeGibraltar = "Europe/Gibraltar"
case europeGuernsey = "Europe/Guernsey"
case europeHelsinki = "Europe/Helsinki"
case europeIsleOfMan = "Europe/Isle_of_Man"
case europeIstanbul = "Europe/Istanbul"
case europeJersey = "Europe/Jersey"
case europeKaliningrad = "Europe/Kaliningrad"
case europeKiev = "Europe/Kiev"
case europeLisbon = "Europe/Lisbon"
case europeLjubljana = "Europe/Ljubljana"
case europeLondon = "Europe/London"
case europeLuxembourg = "Europe/Luxembourg"
case europeMadrid = "Europe/Madrid"
case europeMalta = "Europe/Malta"
case europeMariehamn = "Europe/Mariehamn"
case europeMinsk = "Europe/Minsk"
case europeMonaco = "Europe/Monaco"
case europeMoscow = "Europe/Moscow"
case europeOslo = "Europe/Oslo"
case europeParis = "Europe/Paris"
case europePodgorica = "Europe/Podgorica"
case europePrague = "Europe/Prague"
case europeRiga = "Europe/Riga"
case europeRome = "Europe/Rome"
case europeSamara = "Europe/Samara"
case europeSanMarino = "Europe/San_Marino"
case europeSarajevo = "Europe/Sarajevo"
case europeSimferopol = "Europe/Simferopol"
case europeSkopje = "Europe/Skopje"
case europeSofia = "Europe/Sofia"
case europeStockholm = "Europe/Stockholm"
case europeTallinn = "Europe/Tallinn"
case europeTirane = "Europe/Tirane"
case europeUzhgorod = "Europe/Uzhgorod"
case europeVaduz = "Europe/Vaduz"
case europeVatican = "Europe/Vatican"
case europeVienna = "Europe/Vienna"
case europeVilnius = "Europe/Vilnius"
case europeVolgograd = "Europe/Volgograd"
case europeWarsaw = "Europe/Warsaw"
case europeZagreb = "Europe/Zagreb"
case europeZaporozhye = "Europe/Zaporozhye"
case europeZurich = "Europe/Zurich"
case gmt = "GMT"
case indianAntananarivo = "Indian/Antananarivo"
case indianChagos = "Indian/Chagos"
case indianChristmas = "Indian/Christmas"
case indianCocos = "Indian/Cocos"
case indianComoro = "Indian/Comoro"
case indianKerguelen = "Indian/Kerguelen"
case indianMahe = "Indian/Mahe"
case indianMaldives = "Indian/Maldives"
case indianMauritius = "Indian/Mauritius"
case indianMayotte = "Indian/Mayotte"
case indianReunion = "Indian/Reunion"
case pacificApia = "Pacific/Apia"
case pacificAuckland = "Pacific/Auckland"
case pacificBougainville = "Pacific/Bougainville"
case pacificChatham = "Pacific/Chatham"
case pacificChuuk = "Pacific/Chuuk"
case pacificEaster = "Pacific/Easter"
case pacificEfate = "Pacific/Efate"
case pacificEnderbury = "Pacific/Enderbury"
case pacificFakaofo = "Pacific/Fakaofo"
case pacificFiji = "Pacific/Fiji"
case pacificFunafuti = "Pacific/Funafuti"
case pacificGalapagos = "Pacific/Galapagos"
case pacificGambier = "Pacific/Gambier"
case pacificGuadalcanal = "Pacific/Guadalcanal"
case pacificGuam = "Pacific/Guam"
case pacificHonolulu = "Pacific/Honolulu"
case pacificJohnston = "Pacific/Johnston"
case pacificKiritimati = "Pacific/Kiritimati"
case pacificKosrae = "Pacific/Kosrae"
case pacificKwajalein = "Pacific/Kwajalein"
case pacificMajuro = "Pacific/Majuro"
case pacificMarquesas = "Pacific/Marquesas"
case pacificMidway = "Pacific/Midway"
case pacificNauru = "Pacific/Nauru"
case pacificNiue = "Pacific/Niue"
case pacificNorfolk = "Pacific/Norfolk"
case pacificNoumea = "Pacific/Noumea"
case pacificPagoPago = "Pacific/Pago_Pago"
case pacificPalau = "Pacific/Palau"
case pacificPitcairn = "Pacific/Pitcairn"
case pacificPohnpei = "Pacific/Pohnpei"
case pacificPonape = "Pacific/Ponape"
case pacificPortMoresby = "Pacific/Port_Moresby"
case pacificRarotonga = "Pacific/Rarotonga"
case pacificSaipan = "Pacific/Saipan"
case pacificTahiti = "Pacific/Tahiti"
case pacificTarawa = "Pacific/Tarawa"
case pacificTongatapu = "Pacific/Tongatapu"
case pacificTruk = "Pacific/Truk"
case pacificWake = "Pacific/Wake"
case pacificWallis = "Pacific/Wallis"
public func toTimezone() -> TimeZone {
switch self {
case .current: return TimeZone.current
case .autoUpdating: return TimeZone.autoupdatingCurrent
default: return TimeZone(identifier: rawValue)!
}
}
}