Skip to content

Commit

Permalink
Time and Date formatters are made more flexible with a structs implem…
Browse files Browse the repository at this point in the history
…enting OptionSet protocol.

Added the ability to specify a separator for dates.
Added day of the week formatter.
Naming changes.
  • Loading branch information
Filipp Kosenko committed Sep 7, 2023
1 parent 1189371 commit 3e6a19f
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 56 deletions.
2 changes: 1 addition & 1 deletion DateFormatterConstructor.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "DateFormatterConstructor"
s.version = "1.0.0"
s.version = "1.0.1"
s.swift_version = "4.0"
s.summary = "DateFormatter extension which makes DateFormatter instance creation easier"
s.description = "This is simple DateFormatter extension which allows you to allows you to create a date formatter with a specific date pattern in one line"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
# ``DateFormatterConstructor``

<!--@START_MENU_TOKEN@-->Summary<!--@END_MENU_TOKEN@-->
This is simple DateFormatter extension which allows you to create a DateFormatter instance with a specific date pattern in one line.

## Overview

<!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@-->

## Topics

### <!--@START_MENU_TOKEN@-->Group<!--@END_MENU_TOKEN@-->

- <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@-->
So instead of writing:
```swift
let formatter = DateFormatter()
formatter.locale = .current
formatter.timeZone = .current
formatter.dateFormat = "HH:mm:ss"
```
you write:
```swift
let formatter = DateFormatter.custom(format: .fullTime(format: .twentyFour))
```
You can also optionally select the locale and timezone:
```swift
let formatter = DateFormatter.custom(format: DateFormatter.DateFormat, locale: Locale(identifier: "en-US"), timeZone: .gmt)
```
or leave them as default as
```swift
.current
```
if you do not specify a format, the
```swift
.fullTimeAndDate
```
format will be used by default:
```swift
let formatter = DateFormatter.custom()
```
40 changes: 25 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,45 @@ formatter.dateFormat = "HH:mm:ss"
```
you write:
```swift
let formatter = DateFormatter.customDateFormatter(format: .fullTime(format: .twentyFour))
let formatter = DateFormatter.custom(format: .fullTime(format: .twentyFour))
```
You can also optionally select the locale and timezone:
```swift
let formatter = DateFormatter.customDateFormatter(format: DateFormatter.DateFormat, locale: Locale(identifier: "en-US"), timeZone: .gmt)
let formatter = DateFormatter.custom(format: DateFormatter.DateFormat, locale: Locale(identifier: "en-US"), timeZone: .gmt)
```
or leave them as default as
```swift
.current
```
if you do not specify a format, the ```.fullTimeAndDate``` format will be used by default:
```swift
let formatter = DateFormatter.customDateFormatter()
let formatter = DateFormatter.custom()
```

| Available format templates | Representation |
| -------------------------- |:--------------:|
| .time(withOnly: .hours) | 23 |
| .time(withOnly: .hoursAndMinutes) | 23:59 |
| .time(withOnly: .minutes) | 59 |
| .time(withOnly: .minutesAndSeconds) | 59:59 |
| .time(withOnly: .seconds) | 59 |
| .fullTime(format: .twelve) | 11:59:59 |
| .fullTime(format: .twentyFour) | 23:59:59 |
| .date(format: .pointNumDate) | 11.08.2023 |
| .date(format: .slashNumDate) | 11/08/2023 |
| .date(format: .shortWordDate) | 11 Aug 2023 |
| .date(format: .fullWordDate) | 11 August 2023 |
| .fullTimeAndDate | 11 August 2023 23:59:59 |
| ```.time(withOnly: .hours)``` | 23 |
| ```.time(withOnly: .minutes)``` | 59 |
| ```.time(withOnly: .seconds)``` | 59 |
| ```.time(withOnly: [.hours, .minutes])``` | 23:59 |
| ```.fullTime(format: .twelve)``` | 11:59:59 |
| ```.fullTime(format: .twentyFour)``` | 23:59:59 |
| ```.fullTime(format: .withAMPM)``` | 11:59:59 PM |
| ```.date(withOnly: .day)``` | 11 |
| ```.date(withOnly: .numMonth)``` | 08 |
| ```.date(withOnly: .shortMonth)``` | Aug |
| ```.date(withOnly: .wideMonth)``` | August |
| ```.date(withOnly: .shortYear)``` | 23 |
| ```.date(withOnly: .wideYear)``` | 2023 |
| ```.date(withOnly: [.day, .shortMonth, .shortYear])``` | 11 Aug 23 |
| ```.fullDate(format: .numDate(separator: ","))``` | 11,08,2023 |
| ```.fullDate(format: .shortWordDate)``` | 11 Aug 2023 |
| ```.fullDate(format: .fullWordDate)``` | 11 August 2023 |
| ```.dayOfWeek(format: .number)``` | 5 |
| ```.dayOfWeek(format: .letter)``` | F |
| ```.dayOfWeek(format: .abbreviation)``` | Fri |
| ```.dayOfWeek(format: .word)``` | Friday |
| ```.fullTimeAndDate``` | 11 August 2023 23:59:59 |

## Requirements

Expand Down
133 changes: 101 additions & 32 deletions Source/DateFormatterConstructor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,140 @@ import Foundation
public extension DateFormatter {

enum DateFormat {
case time(withOnly: TimeUnit)
case fullTime(format: HoursQuantity)
case date(format: DateType)
case time(withOnly: TimeUnits)
case fullTime(format: FullTimeFormat)
case date(withOnly: DateUnits)
case fullDate(format: DateType)
case dayOfTheWeek(format: DayOfTheWeekType)
case fullTimeAndDate

var getFormat: String {
var format: String {
switch self {
case .time(withOnly: let withOnly):
switch withOnly {
case .hours:
return "HH"
case .hoursAndMinutes:
return "HH:mm"
case .minutes:
return "mm"
case .minutesAndSeconds:
return "mm:ss"
case .seconds:
return "ss"
}
return withOnly.description
case .fullTime(format: let format):
switch format {
case .twelve:
return "hh:mm:ss"
case .twentyFour:
return "HH:mm:ss"
case .withAMPM:
return "hh:mm:ss a"
}
case .date(format: let format):
case .date(withOnly: let withOnly):
return withOnly.description
case .fullDate(format: let format):
switch format {
case .pointNumDate:
return "dd.MM.yyyy"
case .slashNumDate:
return "dd/MM/yyyy"
case .numDate(separator: let separator):
return "dd\(separator)MM\(separator)yyyy"
case .shortWordDate:
return "dd MMM yyyy"
case .fullWordDate:
return "dd MMMM yyyy"
}
case .dayOfTheWeek(format: let format):
switch format {
case .number:
return "e"
case .letter:
return "EEEEE"
case .abbreviation:
return "EEE"
case .word:
return "EEEE"
}
case .fullTimeAndDate:
return "dd MMMM yyyy HH:mm:ss"
}
}
}

enum TimeUnit {
case hours
case hoursAndMinutes
case minutes
case minutesAndSeconds
case seconds
struct TimeUnits: OptionSet {
public let rawValue: Int8

static let hours = TimeUnits(rawValue: 1)
static let minutes = TimeUnits(rawValue: 1 << 1)
static let seconds = TimeUnits(rawValue: 1 << 2)

public init(rawValue: Int8) {
self.rawValue = rawValue
}

var description: String {
var units = [String]()
if self.contains(.hours) {
units.append("HH")
}
if self.contains(.minutes) {
units.append("mm")
}
if self.contains(.seconds) {
units.append("ss")
}

return units.joined(separator: ":")
}
}

enum HoursQuantity {
enum FullTimeFormat {
case twelve
case twentyFour
case withAMPM
}

struct DateUnits: OptionSet {
public let rawValue: Int8

static let day = DateUnits(rawValue: 1)
static let numMonth = DateUnits(rawValue: 1 << 2)
static let shortMonth = DateUnits(rawValue: 1 << 3)
static let wideMonth = DateUnits(rawValue: 1 << 4)
static let shortYear = DateUnits(rawValue: 1 << 5)
static let wideYear = DateUnits(rawValue: 1 << 6)

public init(rawValue: Int8) {
self.rawValue = rawValue
}

var description: String {
var units = [String]()
if self.contains(.day) {
units.append("dd")
}
if self.contains(.numMonth) {
units.append("MM")
}
if self.contains(.shortMonth) {
units.append("MMM")
}
if self.contains(.wideMonth) {
units.append("MMMM")
}
if self.contains(.shortYear) {
units.append("yy")
}
if self.contains(.wideYear) {
units.append("yyyy")
}

return units.joined(separator: " ")
}
}

enum DateType {
case pointNumDate
case slashNumDate
case numDate(separator: String)
case shortWordDate
case fullWordDate
}

static func customDateFormatter(
enum DayOfTheWeekType {
case number
case letter
case abbreviation
case word
}

static func custom(
format: DateFormat? = .fullTimeAndDate,
locale: Locale? = .current,
timeZone: TimeZone? = .current
Expand All @@ -85,7 +154,7 @@ public extension DateFormatter {
let dateFormatter = DateFormatter()
dateFormatter.locale = locale
dateFormatter.timeZone = timeZone
dateFormatter.dateFormat = format?.getFormat
dateFormatter.dateFormat = format?.format

return dateFormatter
}
Expand Down

0 comments on commit 3e6a19f

Please sign in to comment.