Skip to content

Commit

Permalink
Merge branch 'release/4.0.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
malcommac committed Oct 2, 2016
2 parents cb8fe40 + e243484 commit f6b9add
Show file tree
Hide file tree
Showing 35 changed files with 651 additions and 374 deletions.
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<p align="center" >
<img src="https://raw.githubusercontent.com/malcommac/SwiftDate/master/swiftdate-4-logo.png" width=189px height=191 alt="SwiftDate" title="SwiftDate">
</p>

[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CI Status](https://travis-ci.org/malcommac/SwiftDate.svg)](https://travis-ci.org/malcommac/SwiftDate) [![Version](https://img.shields.io/cocoapods/v/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![License](https://img.shields.io/cocoapods/l/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![Platform](https://img.shields.io/cocoapods/p/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate)

## CHANGELOG

### SwiftDate 4.0.3
Released on: Monday Oct 3, 2016, [Download](https://github.com/malcommac/SwiftDate/releases/tag/4.0.3)

Changes:
* [#271](https://github.com/malcommac/SwiftDate/issues/271): Added fallback to english translation when required translation is not available for colloquial functions
* [#112](https://github.com/malcommac/SwiftDate/issues/112): Fixed an issue when optimization level is `-fast`
* [#269](https://github.com/malcommac/SwiftDate/issues/269): Fixed unnecessary strings printed in console when using `.timeComponents()` function
* [#266](https://github.com/malcommac/SwiftDate/issues/266): Removed unnecessary `Region.copy()` function
* [#267](https://github.com/malcommac/SwiftDate/issues/267): `.absoluteDate` is now a public property for `DateInRegion`
* [#268](https://github.com/malcommac/SwiftDate/issues/268): Added new german translation to `SwiftDate.bundle`
* [#272](https://github.com/malcommac/SwiftDate/issues/272): Failed to calculate a colloquial date when diff in seconds = 0. It throw a `.FailedToCalculate` exception.
* [#274](https://github.com/malcommac/SwiftDate/issues/274): Fixed a bug with padding in Time Components formatter. Now SwiftDate uses `DateComponentsFormatter` internally; old timeComponents/timeComponentsSinceNow (in Date and DateInRegion) are now deprecated (there are other functions with the same name which takes a `ComponentsFormatterOptions` struct as input). Also `.string()` function in `TimeInterval` is now replaced by a counterpart which take `ComponentsFormatterOptions` struct.
* [#275](https://github.com/malcommac/SwiftDate/issues/275): `.formatter.useSharedFormatters` in `DateInRegion` is now accessible so, if strictly needed user can user a custom instance of DateTime Formatters per single `DateInRegion`.

### SwiftDate 4.0.2
Released on: 2016-09-30, [Download](https://github.com/malcommac/SwiftDate/releases/tag/4.0.2)

Changes:
- Minor fix for cocoapods compatibility (SwiftDate.bundle was not copied)

### SwiftDate 4.0.0
Released on: 2016-09-29, [Download](https://github.com/malcommac/SwiftDate/releases/tag/4.0.0)

Changes:
- Major rewrite, fully compatible with Swift 3.0
- Function names and parameter now fully adopt Swift conventions (*we should make a complete list of changes soon*)
- Various fixes with locale management and timezones
- Web site and complete documentation
- Jazzy support
- Unit tests now compiles under XCode 8 and Swift 3
5 changes: 5 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import PackageDescription

let package = Package(
name: "SwiftDate"
)
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CI Status](https://travis-ci.org/malcommac/SwiftDate.svg)](https://travis-ci.org/malcommac/SwiftDate) [![Version](https://img.shields.io/cocoapods/v/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![License](https://img.shields.io/cocoapods/l/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![Platform](https://img.shields.io/cocoapods/p/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate)

We really ❤ Swift and we use it since the beginning.

We also think that dates and timezones management should be painless: this is the reason we made SwiftDate, probability the best way to manage date and time in Swift.
We really ♥ Swift and we think that dates and timezones management should be painless: this is the reason we made SwiftDate, probability the best way to manage date and time in Swift.

Choose SwiftDate for your next project, or migrate over your existing projects—you'll be happy you did!

## SwiftDate [website is here](http://malcommac.github.io/SwiftDate)
<p align="center" >★★ <b>Star our github repository to help us!</b> ★★</p>
<p align="center" ><h2><a href="http://malcommac.github.io/SwiftDate">SwiftDate website</a></h2></p>

## Main features
That's an highlight of the main features you can found in SwiftDate:
Expand All @@ -32,7 +31,7 @@ That's an highlight of the main features you can found in SwiftDate:

## Documentation
* **On [http://malcommac.github.io/SwiftDate/index.html](http://malcommac.github.io/SwiftDate/index.html) to learn more about all available functions with a comprehensive list of examples**
* The **latest [full class documentation is available here](http://malcommac.github.io/SwiftDate/docs-latest/)**
* The **latest [full class documentation is available here](http://cocoadocs.org/docsets/SwiftDate/4.0.2/)**

Code is documented for Xcode, so you can use built in documentation panel to learn more about the library.

Expand All @@ -45,10 +44,24 @@ You can also generate latest documentation using [Jazzy](https://github.com/real
- If you **have a feature request**, [open an issue](https://github.com/malcommac/SwiftDate/issues/new).
- If you **want to contribute**, [submit a pull request](https://github.com/malcommac/SwiftDate/compare).

## Current Release

Last release is: 4.0.3 [Download here](https://github.com/malcommac/SwiftDate/releases/tag/4.0.3) released on Mon, Oct 3, 2016.

A complete list of changes for each release is available in [CHANGELOG](CHANGELOG.md) file.

## Help Us!
Currently we need translations for [SwiftDate.bundle](https://github.com/malcommac/SwiftDate/tree/master/src/Support/SwiftDate.bundle).
Help us with a pull request!

Currently SwiftDate supports:
* English
* Italian
* German (made by to [hackolein](https://github.com/hackolein), since 4.0.3)
* Dutch (made by [hout](https://github.com/Hout))

Make a pull request and add your language!

## Installation

SwiftDate supports multiple methods for installing the library in a project.
Expand Down
File renamed without changes.
63 changes: 62 additions & 1 deletion src/Support/Commons.swift → Sources/SwiftDate/Commons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import Foundation


/// Provide a mechanism to create and return local-thread object you can share.
///
/// Basically you assign a key to the object and return the initializated instance in `create`
Expand Down Expand Up @@ -80,3 +79,65 @@ public enum DateFormat {
case rss(alt: Bool)
case dotNET
}

/// This struct group the options you can choose to output a string which represent
/// the interval between two dates.
public struct ComponentsFormatterOptions {
/// The default formatting behavior. When using positional units, this behavior drops leading zeroes but pads middle and trailing values with zeros as needed. For example, with hours, minutes, and seconds displayed, the value for one hour and 10 seconds is “1:00:10”. For all other unit styles, this behavior drops all units whose values are 0. For example, when days, hours, minutes, and seconds are allowed, the abbreviated version of one hour and 10 seconds is displayed as “1h 10s”.*
public var zeroBehavior: DateComponentsFormatter.ZeroFormattingBehavior = .pad

// The maximum number of time units to include in the output string.
// By default is nil, which does not cause the elimination of any units.
public var maxUnitCount: Int? = nil

// Configures the strings to use (if any) for unit names such as days, hours, minutes, and seconds.
// By default is `positional`.
public var style: DateComponentsFormatter.UnitsStyle = .positional

// Setting this property to true results in output strings like “30 minutes remaining”. The default value of this property is false.
public var includeTimeRemaining: Bool = false

/// The bitmask of calendrical units such as day and month to include in the output string
/// Allowed components are: `year,month,weekOfMonth,day,hour,minute,second`.
/// By default it's set as nil which means set automatically based upon the interval.
public var allowedUnits: NSCalendar.Unit? = nil

/// The locale to use to format the string.
/// If `ComponentsFormatterOptions` is used from a `TimeInterval` object the default value
/// value is set to the current device's locale.
/// If `ComponentsFormatterOptions` is used from a `DateInRegion` object the default value
/// is set the `DateInRegion`'s locale.
public var locale: Locale = LocaleName.current.locale

/// Initialize a new ComponentsFormatterOptions struct
/// - parameter allowedUnits: allowed units or nil if you want to keep the default value
/// - parameter style: units style or nil if you want to keep the default value
/// - parameter zero: zero behavior or nil if you want to keep the default value
public init(allowedUnits: NSCalendar.Unit? = nil, style: DateComponentsFormatter.UnitsStyle? = nil, zero: DateComponentsFormatter.ZeroFormattingBehavior? = nil) {
if allowedUnits != nil { self.allowedUnits = allowedUnits! }
if style != nil { self.style = style! }
if zero != nil { self.zeroBehavior = zero! }
}

/// Evaluate the best allowed units to workaround NSException of the DateComponentsFormatter
internal func bestAllowedUnits(forInterval interval: TimeInterval) -> NSCalendar.Unit {
switch interval {
case 0...(SECONDS_IN_MINUTE-1):
return [.second]
case SECONDS_IN_MINUTE...(SECONDS_IN_HOUR-1):
return [.minute,.second]
case SECONDS_IN_HOUR...(SECONDS_IN_DAY-1):
return [.hour,.minute,.second]
case SECONDS_IN_DAY...(SECONDS_IN_WEEK-1):
return [.day,.hour,.minute,.second]
default:
return [.year,.month,.weekOfMonth,.day,.hour,.minute,.second]
}
}
}

private let SECONDS_IN_MINUTE: TimeInterval = 60
private let SECONDS_IN_HOUR: TimeInterval = SECONDS_IN_MINUTE * 60
private let SECONDS_IN_DAY: TimeInterval = SECONDS_IN_HOUR * 24
private let SECONDS_IN_WEEK: TimeInterval = SECONDS_IN_DAY * 7

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,26 @@ public extension Date {
/// - throws: throw an exception if time components cannot be evaluated
///
/// - returns: string with each time component
@available(*, deprecated: 4.0.3, message: "Use timeComponentsSinceNow(options:shared:) instead")
public func timeComponentsSinceNow(unitStyle: DateComponentsFormatter.UnitsStyle = .short, max: Int? = nil, zero: DateZeroBehaviour? = nil, separator: String? = nil) throws -> String {
return try self.timeComponents(to: Date(), unitStyle: unitStyle, max: max, zero: zero, separator: separator)
}

/// This method produces a string by printing the interval between self and current Date and output a string where each
/// calendar component is printed.
///
/// - parameter options: options to format the output. Keep in mind: `.locale` will be overwritten by self's `region.locale`.
/// - parameter shared: `true` to use a shared (per thread) instance. Unless specific needs you should not instantiate
/// lots of Date Formatters due to the high cost. SwiftDate share a single formatter in each thread
/// which cover the most commom scenarios.
///
/// - throws: throw an exception if time components cannot be evaluated
///
/// - returns: string with each time component
public func timeComponentsSinceNow(options: ComponentsFormatterOptions? = nil, shared: Bool? = true) throws -> String {
return try self.timeComponents(to: Date(), options: options, shared: shared)
}

/// This method produces a string by printing the interval between self and another date and output a string where each
/// calendar component is printed.
///
Expand All @@ -142,11 +158,29 @@ public extension Date {
/// - throws: throw an exception if time components cannot be evaluated
///
/// - returns: string with each time component
@available(*, deprecated: 4.0.3, message: "Use timeComponents(to:options:shared:) instead")
public func timeComponents(to: Date, in region: Region? = nil, unitStyle: DateComponentsFormatter.UnitsStyle = .short, max: Int? = nil, zero: DateZeroBehaviour? = nil, separator: String? = nil) throws -> String {

let srcRegion = region ?? DateDefaultRegion
let fromDateInRegion = DateInRegion(absoluteDate: self, in: srcRegion)
let toDateInRegion = DateInRegion(absoluteDate: to, in: srcRegion)
return try fromDateInRegion.timeComponents(toDate: toDateInRegion, unitStyle: unitStyle, max: max, zero: zero, separator: separator)
}

/// This method produces a string by printing the interval between self and another date and output a string where each
/// calendar component is printed.
///
///
/// - parameter to: date to compare
/// - parameter options: options to format the output. Keep in mind: `.locale` will be overwritten by self's `region.locale`.
/// - parameter shared: `true` to use a shared (per thread) instance. Unless specific needs you should not instantiate
/// lots of Date Formatters due to the high cost. SwiftDate share a single formatter in each thread
/// which cover the most commom scenarios.
///
/// - throws: throw an exception if time components cannot be evaluated
///
/// - returns: string with each time component
public func timeComponents(to: Date, options: ComponentsFormatterOptions? = nil, shared: Bool? = true) throws -> String {
return try self.timeIntervalSince(to).string(options: options, shared: shared)
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public extension DateComponents {
guard let absDate = dateInRegion.region.calendar.date(byAdding: self, to: dateInRegion.absoluteDate) else {
return nil
}
let newDateInRegion = DateInRegion(absoluteDate: absDate, in: dateInRegion.region.copy())
let newDateInRegion = DateInRegion(absoluteDate: absDate, in: dateInRegion.region)
return newDateInRegion
}

Expand All @@ -172,7 +172,7 @@ public extension DateComponents {
guard let absDate = date.region.calendar.date(byAdding: -self, to: date.absoluteDate) else {
return nil
}
let newDateInRegion = DateInRegion(absoluteDate: absDate, in: date.region.copy())
let newDateInRegion = DateInRegion(absoluteDate: absDate, in: date.region)
return newDateInRegion
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ extension DateInRegion {
/// Return the instance representing the first moment date of the given date expressed in the context of the calendar of the receiver
public var startOfDay: DateInRegion {
let absoluteDate = self.region.calendar.startOfDay(for: self.absoluteDate)
return DateInRegion(absoluteDate: absoluteDate, in: self.region.copy())
return DateInRegion(absoluteDate: absoluteDate, in: self.region)
}

/// Return the instance representing the last moment date of the given date expressed in the context of the calendar of the receiver
Expand All @@ -359,21 +359,21 @@ extension DateInRegion {
var dCmps = DateComponents()
dCmps.day = 1
let nextDay = cal.startOfDay(for: cal.date(byAdding: dCmps, to: self.absoluteDate)!)
return DateInRegion(absoluteDate: nextDay.addingTimeInterval(-0.001), in: self.region.copy())
return DateInRegion(absoluteDate: nextDay.addingTimeInterval(-0.001), in: self.region)
}

/// Return a new instance of the date plus one month
public var nextMonth: DateInRegion {
let refDate = self.startOfDay.absoluteDate
let nextMonth = self.region.calendar.date(byAdding: .month, value: 1, to: refDate)
return DateInRegion(absoluteDate: nextMonth!, in: self.region.copy())
return DateInRegion(absoluteDate: nextMonth!, in: self.region)
}

/// Return a new instance of the date minus one month
public var prevMonth: DateInRegion {
let refDate = self.startOfDay.absoluteDate
let prevMonth = self.region.calendar.date(byAdding: .month, value: -1, to: refDate)
return DateInRegion(absoluteDate: prevMonth!, in: self.region.copy())
return DateInRegion(absoluteDate: prevMonth!, in: self.region)
}


Expand All @@ -384,7 +384,7 @@ extension DateInRegion {
/// - returns: the date representing that start of that unit
public func startOf(component: Calendar.Component) -> DateInRegion {
let absoluteTime = self.region.calendar.rangex(of: component, for: self.absoluteDate)!.start
return DateInRegion(absoluteDate: absoluteTime, in: self.region.copy())
return DateInRegion(absoluteDate: absoluteTime, in: self.region)
}


Expand All @@ -398,7 +398,7 @@ extension DateInRegion {
// second
let startOfNextUnit = self.region.calendar.rangex(of: component, for: self.absoluteDate)!.end
let endOfThisUnit = Date(timeInterval: -0.001, since: startOfNextUnit)
return DateInRegion(absoluteDate: endOfThisUnit, in: self.region.copy())
return DateInRegion(absoluteDate: endOfThisUnit, in: self.region)
}


Expand Down Expand Up @@ -436,7 +436,7 @@ extension DateInRegion {
guard let newDate = self.region.calendar.date(bySettingHour: hour, minute: minute, second: second, of: self.absoluteDate) else {
throw DateError.FailedToCalculate
}
return DateInRegion(absoluteDate: newDate, in: self.region.copy())
return DateInRegion(absoluteDate: newDate, in: self.region)
}


Expand All @@ -453,7 +453,7 @@ extension DateInRegion {
guard let newDate = self.region.calendar.date(bySetting: unit, value: value, of: self.absoluteDate) else {
throw DateError.FailedToCalculate
}
return DateInRegion(absoluteDate: newDate, in: self.region.copy())
return DateInRegion(absoluteDate: newDate, in: self.region)
}


Expand All @@ -476,7 +476,7 @@ extension DateInRegion {
calculatedDate = newDate
}
}
return DateInRegion(absoluteDate: calculatedDate, in: self.region.copy())
return DateInRegion(absoluteDate: calculatedDate, in: self.region)
}


Expand Down
Loading

0 comments on commit f6b9add

Please sign in to comment.