Skip to content

Commit

Permalink
Merge pull request #1 from malcommac/develop
Browse files Browse the repository at this point in the history
Updated develop
  • Loading branch information
RomanPodymov authored Sep 14, 2019
2 parents ad9fff8 + 4d4e255 commit f760ed2
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 7 deletions.
60 changes: 60 additions & 0 deletions Documentation/3.Manipulate_Date.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
- [3.13 - Sort Dates](3.Manipulate_Date.md#sort)
- [3.14 - Get the next weekday](3.Manipulate_Date.md#nextWeekDay)
- [3.15 - Get date at given week number/weekday](3.Manipulate_Date.md#dateAtWeeknumberWeekday)
- [3.16 - Difference between dates with components](3.Manipulate_Date.md#differenceBetweenDates)
- [3.17 - Create date at components preserving small components](3.Manipulate_Date.md#dateAtComponents)
- [3.18 - Date at given weekday after # weeks](3.Manipulate_Date.md#dateAfterWeeks)
- [3.19 - Next Date](3.Manipulate_Date.md#nextDate)

Dates can be manipulated as you need by using classic math operators and readable time units.

Expand Down Expand Up @@ -505,4 +509,60 @@ let date = DateInRegion("2019-05-11 00:00:00", format: dateFormat, region: regio
let _ = date1.dateAt(weekdayOrdinal: 3, weekday: .friday, monthNumber: date1.month + 1) // 2019-06-21T00:00:00+02:00
```

<a name="differenceBetweenDates"/>

## 3.16 - Difference between dates with components

To get differences between two dates using given time components you can choose between two methods:

- `difference(in:from:)`: Returns the difference in the calendar component given (like day, month or year) with respect to the other date as a positive integer.
- `differences(in:from:)`: Returns the differences in the calendar components given (like day, month and year) with respect to the other date as dictionary with the calendar component as the key and the diffrence as a positive integer as the value.


Example:

```swift
let format = "yyyy-MM-dd HH:mm"
let d1 = "2019-01-01 00:00".toDate(format, region: Region.current)
let d2 = "2019-01-10 14:20".toDate(format, region: Region.current)
let diff = d1!.differences(in: [.day, .hour], from: d2!) // 9 days, 14 hours
```
[^ Top](#index)

<a name="dateAtComponents"/>

## 3.17 - Create date at components preserving small components

You can create a derivated date from a receiver by preserving small components (hour, minute and second) by using the: `dateAt(dayOfMonth:monthNumber:yearNumber:)` method:

```swift
let date = "2019-01-01 00:00".toDate("yyyy-MM-dd HH:mm", region: Region.current)! // Rome zone
let onMarch = date.dateAt(dayOfMonth: 31, monthNumber: 3) // 2019-03-31T00:00:00+01:00
```

[^ Top](#index)

<a name="dateAfterWeeks"/>

## 3.18 - Date at given weekday after # weeks

Returns the date after given number of weeks on the given day of week using `dateAfter(weeks:on:)` function.

```swift
let d = "2019-09-14 00:00".toDate("yyyy-MM-dd HH:mm", region: Region.current)! // Rome Region
let nextTwoMondays = d.dateAfter(weeks: 2, on: .monday) // 2019-09-23T00:00:00+02:00
```

[^ Top](#index)

<a name="nextDate"/>

## 3.19 - Next Date

There are 3 functions to get the next date starting from a receiver date:

- `nextWeekday()`: Returns the next weekday preserving smaller components
- `nextWeekday(:withWeekOfMonth:andMonthNumber)`: Returns next date with the given weekday and the given week number
- `next(dayOfMonth:monthOfYear:)`: Returns the next day of month preserving smaller components (hour, minute, seconds)

[**Next Chapter**: Compare Dates](#4.CompareDates.md)
1 change: 1 addition & 0 deletions Documentation/4.Compare_Dates.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,5 @@ let _ = testDate.isInRange(date: lowerBound, and: upperBound, orEqual: true, gra

[^ Top](#index)


[**Next Chapter**: Date Formatting](#5.Date_Formatting.md)
9 changes: 6 additions & 3 deletions Documentation/Index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

## Documentation

- Reference Version: **5.0.0**
- Last Update: **July 1, 2018**
- Code Coverage: **90.68%**
- Reference Version: **6.1.0**
- Last Update: **Sept 2019**

The following documentation explore all the major features of the library. If you are interested in a detailed, method by method documentation you can refeer to the Jazzy documentation generated by CocoaPods (you can also install in Dash).

Expand Down Expand Up @@ -54,6 +53,10 @@ The following documentation explore all the major features of the library. If yo
- [3.13 - Sort Dates](3.Manipulate_Date.md#sort)
- [3.14 - Get the next weekday](3.Manipulate_Date.md#nextWeekDay)
- [3.15 - Get date at given week number/weekday](3.Manipulate_Date.md#dateAtWeeknumberWeekday)
- [3.16 - Difference between dates with components](3.Manipulate_Date.md#differenceBetweenDates)
- [3.17 - Create date at components preserving small components](3.Manipulate_Date.md#dateAtComponents)
- [3.18 - Date at given weekday after # weeks](3.Manipulate_Date.md#dateAfterWeeks)
- [3.19 - Next Date](3.Manipulate_Date.md#nextDate)

### [4 - Compare Dates](4.Compare_Dates.md)

Expand Down
75 changes: 75 additions & 0 deletions Sources/SwiftDate/Date/Date+Compare.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,78 @@ public extension Date {
}

}

extension Date {

/// Returns the difference in the calendar component given (like day, month or year)
/// with respect to the other date as a positive integer
public func difference(in component: Calendar.Component, from other: Date) -> Int? {
let (max, min) = orderDate(with: other)
let result = calendar.dateComponents([component], from: min, to: max)
return getValue(of: component, from: result)
}

/// Returns the differences in the calendar components given (like day, month and year)
/// with respect to the other date as dictionary with the calendar component as the key
/// and the diffrence as a positive integer as the value
public func differences(in components: Set<Calendar.Component>, from other: Date) -> [Calendar.Component: Int] {
let (max, min) = orderDate(with: other)
let differenceInDates = calendar.dateComponents(components, from: min, to: max)
var result = [Calendar.Component: Int]()
for component in components {
if let value = getValue(of: component, from: differenceInDates) {
result[component] = value
}
}
return result
}

private func getValue(of component: Calendar.Component, from dateComponents: DateComponents) -> Int? {
switch component {
case .era:
return dateComponents.era
case .year:
return dateComponents.year
case .month:
return dateComponents.month
case .day:
return dateComponents.day
case .hour:
return dateComponents.hour
case .minute:
return dateComponents.minute
case .second:
return dateComponents.second
case .weekday:
return dateComponents.weekday
case .weekdayOrdinal:
return dateComponents.weekdayOrdinal
case .quarter:
return dateComponents.quarter
case .weekOfMonth:
return dateComponents.weekOfMonth
case .weekOfYear:
return dateComponents.weekOfYear
case .yearForWeekOfYear:
return dateComponents.yearForWeekOfYear
case .nanosecond:
return dateComponents.nanosecond
case .calendar, .timeZone:
return nil
@unknown default:
assert(false, "unknown date component")
}
return nil
}

private func orderDate(with other: Date) -> (Date, Date) {
let first = self.timeIntervalSince1970
let second = other.timeIntervalSince1970

if first >= second {
return (self, other)
}

return (other, self)
}
}
13 changes: 13 additions & 0 deletions Sources/SwiftDate/DateInRegion/DateInRegion+Compare.swift
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,17 @@ public extension DateInRegion {
return self.date.timeIntervalSince(date.date) >= 0 ? self : date
}

/// Returns the difference in the calendar component given (like day, month or year)
/// with respect to the other date as a positive integer
func difference(in component: Calendar.Component, from other: DateInRegion) -> Int? {
return self.date.difference(in: component, from: other.date)
}

/// Returns the differences in the calendar components given (like day, month and year)
/// with respect to the other date as dictionary with the calendar component as the key
/// and the diffrence as a positive integer as the value
func differences(in components: Set<Calendar.Component>, from other: DateInRegion) -> [Calendar.Component: Int] {
return self.date.differences(in: components, from: other.date)
}

}
62 changes: 61 additions & 1 deletion Sources/SwiftDate/DateInRegion/DateInRegion+Create.swift
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,31 @@ public extension DateInRegion {
return result
}

/// Returns the next weekday preserving smaller components (hour, minute, seconds)
/// Returns the date on the given day of month preserving smaller components
func dateAt(dayOfMonth: Int, monthNumber: Int? = nil,
yearNumber: Int? = nil) -> DateInRegion {
let monthNum = monthNumber ?? month
let yearNum = yearNumber ?? year

let result = DateInRegion(year: yearNum, month: monthNum, day: dayOfMonth,
hour: hour, minute: minute, second: second,
nanosecond: nanosecond, region: region)

return result
}

/// Returns the date after given number of weeks on the given day of week
func dateAfter(weeks count: Int, on weekday: WeekDay) -> DateInRegion {
var result = self.dateByAdding(count, .weekOfMonth)
if result.weekday == weekday.rawValue {
return result
} else if result.weekday > weekday.rawValue {
result = result.dateByAdding(-1, .weekOfMonth)
}
return result.nextWeekday(weekday)
}

/// Returns the next weekday preserving smaller components
///
/// - Parameters:
/// - weekday: weekday to get.
Expand All @@ -587,4 +611,40 @@ public extension DateInRegion {

return DateInRegion(next, region: region)
}

/// Returns next date with the given weekday and the given week number
func next(_ weekday: WeekDay, withWeekOfMonth weekNumber: Int,
andMonthNumber monthNumber: Int? = nil) -> DateInRegion {
var result = self.dateAt(weekdayOrdinal: weekNumber, weekday: weekday, monthNumber: monthNumber)

if result <= self {

if let monthNum = monthNumber {
result = self.dateAt(weekdayOrdinal: weekNumber, weekday: weekday,
monthNumber: monthNum, yearNumber: self.year + 1)
} else {
result = self.dateAt(weekdayOrdinal: weekNumber, weekday: weekday, monthNumber: self.month + 1)
}

}

return result
}

/// Returns the next day of month preserving smaller components (hour, minute, seconds)
func next(dayOfMonth: Int, monthOfYear: Int? = nil) -> DateInRegion {
var components = DateComponents()
components.day = dayOfMonth
components.month = monthOfYear
components.hour = hour
components.second = second
components.minute = minute

guard let next = region.calendar.nextDate(after: date, matching: components,
matchingPolicy: .nextTimePreservingSmallerComponents) else {
return self
}

return DateInRegion(next, region: region)
}
}
4 changes: 2 additions & 2 deletions Sources/SwiftDate/TimePeriod/Groups/TimePeriodGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ open class TimePeriodGroup: Sequence, Equatable {
return false // No need to sorting if they already have different counts
}

var compArray1: [TimePeriodProtocol] = array1.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in
let compArray1: [TimePeriodProtocol] = array1.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in
if period1.start == nil && period2.start == nil {
return false
} else if period1.start == nil {
Expand All @@ -102,7 +102,7 @@ open class TimePeriodGroup: Sequence, Equatable {
return period2.start! < period1.start!
}
}
var compArray2: [TimePeriodProtocol] = array2.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in
let compArray2: [TimePeriodProtocol] = array2.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in
if period1.start == nil && period2.start == nil {
return false
} else if period1.start == nil {
Expand Down
2 changes: 1 addition & 1 deletion SwiftDate.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SwiftDate"
s.version = "6.0.3"
s.version = "6.1.0"
s.summary = "The best way to deal with Dates & Time Zones in Swift"
s.homepage = "https://github.com/malcommac/SwiftDate.git"
s.license = { :type => "MIT", :file => "LICENSE" }
Expand Down
4 changes: 4 additions & 0 deletions SwiftDate.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
64EF3E0F20D65478002793C6 /* TestDateInRegion+Compare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EF3E0E20D65478002793C6 /* TestDateInRegion+Compare.swift */; };
64EF3E1020D65478002793C6 /* TestDateInRegion+Compare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EF3E0E20D65478002793C6 /* TestDateInRegion+Compare.swift */; };
64EF3E1120D65478002793C6 /* TestDateInRegion+Compare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EF3E0E20D65478002793C6 /* TestDateInRegion+Compare.swift */; };
A89F3FAF22A00019002D1BD0 /* TestDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A89F3FAE22A00019002D1BD0 /* TestDate.swift */; };
DD7502881C68FEDE006590AF /* SwiftDate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6DA0F1BF000BD002C0205 /* SwiftDate.framework */; };
DD7502921C690C7A006590AF /* SwiftDate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D9F01BEFFFBE002C0205 /* SwiftDate.framework */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -319,6 +320,7 @@
64EF3E0620D56038002793C6 /* TestDateInRegion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDateInRegion.swift; sourceTree = "<group>"; };
64EF3E0A20D65329002793C6 /* TestDateInRegion+Create.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TestDateInRegion+Create.swift"; sourceTree = "<group>"; };
64EF3E0E20D65478002793C6 /* TestDateInRegion+Compare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TestDateInRegion+Compare.swift"; sourceTree = "<group>"; };
A89F3FAE22A00019002D1BD0 /* TestDate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDate.swift; sourceTree = "<group>"; };
AD2FAA261CD0B6D800659CF4 /* SwiftDate.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SwiftDate.plist; sourceTree = "<group>"; };
AD2FAA281CD0B6E100659CF4 /* SwiftDateTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SwiftDateTests.plist; sourceTree = "<group>"; };
DD75027A1C68FCFC006590AF /* SwiftDate-macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftDate-macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -566,6 +568,7 @@
6439232520D91D170098EC03 /* TestFormatters.swift */,
64BAB12720E6411100FEED79 /* TestSwiftDate.swift */,
647AD65B21F4851F00CF787E /* TestDataStructures.swift */,
A89F3FAE22A00019002D1BD0 /* TestDate.swift */,
);
name = Tests;
path = Tests/SwiftDateTests;
Expand Down Expand Up @@ -1161,6 +1164,7 @@
files = (
64BAB12520E63A3A00FEED79 /* TestDateInRegion+Langs.swift in Sources */,
647AD65D21F4851F00CF787E /* TestDataStructures.swift in Sources */,
A89F3FAF22A00019002D1BD0 /* TestDate.swift in Sources */,
6439232320D912670098EC03 /* TestDateInRegion+Math.swift in Sources */,
64EF3E1020D65478002793C6 /* TestDateInRegion+Compare.swift in Sources */,
6439232720D91D170098EC03 /* TestFormatters.swift in Sources */,
Expand Down
35 changes: 35 additions & 0 deletions Tests/SwiftDateTests/TestDate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// TestDate.swift
// SwiftDate-macOS Tests
//
// Created by Imthath M on 30/05/19.
// Copyright © 2019 SwiftDate. All rights reserved.
//

import XCTest

class TestDate: XCTestCase {

override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}

func testDifferencesBetweenDates() {
let date = Date()
let date2 = "2019-01-05".toDate()!.date
let result = date.differences(in: [.hour, .day, .month], from: date2)
print(result)
}

func testDifferenceBetweenDates() {
let date = Date()
let date2 = "2019-01-05".toDate()!.date
let result = date.difference(in: .day, from: date2)
print(result!)
}

}

0 comments on commit f760ed2

Please sign in to comment.