两个国家安全局之间的时间过得很快

我想知道是否有一些新的和令人敬畏的可能性获得两个 NSDates 之间的天数在 Swift/“新的”Cocoa?

例如,在 Ruby 中,我会这样做:

(end_date - start_date).to_i
136351 次浏览

迅速的东西仍然是非常基本的。他们应该在这个早期阶段。但是您可以添加自己的内容,这样会带来重载操作符和全局域函数的风险。但是它们将是本地的模块。

let now = NSDate()
let seventies = NSDate(timeIntervalSince1970: 0)


// Standard solution still works
let days = NSCalendar.currentCalendar().components(.CalendarUnitDay,
fromDate: seventies, toDate: now, options: nil).day


// Flashy swift... maybe...
func -(lhs:NSDate, rhs:NSDate) -> DateRange {
return DateRange(startDate: rhs, endDate: lhs)
}


class DateRange {
let startDate:NSDate
let endDate:NSDate
var calendar = NSCalendar.currentCalendar()
var days: Int {
return calendar.components(.CalendarUnitDay,
fromDate: startDate, toDate: endDate, options: nil).day
}
var months: Int {
return calendar.components(.CalendarUnitMonth,
fromDate: startDate, toDate: endDate, options: nil).month
}
init(startDate:NSDate, endDate:NSDate) {
self.startDate = startDate
self.endDate = endDate
}
}


// Now you can do this...
(now - seventies).months
(now - seventies).days

目前几乎还没有任何特定于 Swift 的标准库; 只有简单的基本数字、字符串和集合类型。

使用扩展完全可以定义这样的快捷方式,但是就实际开箱即用的 API 而言,没有“新的”Cocoa; Swift 只是直接映射到已经存在的旧的冗长 Cocoa API。

我翻译了我的 目标 C 答案

let start = "2010-09-01"
let end = "2010-09-05"


let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"


let startDate:NSDate = dateFormatter.dateFromString(start)
let endDate:NSDate = dateFormatter.dateFromString(end)


let cal = NSCalendar.currentCalendar()




let unit:NSCalendarUnit = .Day


let components = cal.components(unit, fromDate: startDate, toDate: endDate, options: nil)




println(components)

结果

<NSDateComponents: 0x10280a8a0>
Day: 4

最困难的部分是,自动完成坚持 from Date 和 toDate 将是 NSDate?,但实际上它们必须是 NSDate!,如参考文献所示。

我看不出使用操作符的好解决方案会是什么样子,因为您希望在每种情况下都以不同的方式指定单元。您可以返回时间间隔,但是不会获得太多。

你还得考虑时差。例如,如果比较日期 2015-01-01 10:002015-01-02 09:00,那么这两个日期之间的天数将返回0(零) ,因为这两个日期之间的差异小于24小时(23小时)。

如果你的目的是得到两次约会之间的确切日期,你可以这样解决这个问题:

// Assuming that firstDate and secondDate are defined
// ...


let calendar = NSCalendar.currentCalendar()


// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)


let flags = NSCalendarUnit.Day
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: [])


components.day  // This will return the number of day(s) between dates

Swift 3和 Swift 4版本

let calendar = Calendar.current


// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)


let components = calendar.dateComponents([.day], from: date1, to: date2)

我将添加我的版本,即使这个线程已经有一年的历史了,我的代码是这样的:

    var name = txtName.stringValue // Get the users name


// Get the date components from the window controls
var dateComponents = NSDateComponents()
dateComponents.day = txtDOBDay.integerValue
dateComponents.month = txtDOBMonth.integerValue
dateComponents.year = txtDOBYear.integerValue


// Make a Gregorian calendar
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)


// Get the two dates we need
var birthdate = calendar?.dateFromComponents(dateComponents)
let currentDate = NSDate()


var durationDateComponents = calendar?.components(NSCalendarUnit.CalendarUnitDay, fromDate: birthdate!, toDate: currentDate, options: nil)


let numberOfDaysAlive = durationDateComponents?.day


println("\(numberOfDaysAlive!)")


txtGreeting.stringValue = "Hello \(name), You have been alive for \(numberOfDaysAlive!) days."

我希望能帮到别人。

干杯,

以下是我对 Swift 2的回答:

func daysBetweenDates(startDate: NSDate, endDate: NSDate) -> Int
{
let calendar = NSCalendar.currentCalendar()


let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])


return components.day
}
let calendar = NSCalendar.currentCalendar();
let component1 = calendar.component(.Day, fromDate: fromDate)
let component2 = calendar.component(.Day, fromDate: toDate)
let difference  = component1 - component2

以下是 Swift 3(测试了 IOS 10 Beta)的答案

func daysBetweenDates(startDate: Date, endDate: Date) -> Int
{
let calendar = Calendar.current
let components = calendar.components([.day], from: startDate, to: endDate, options: [])
return components.day!
}

那你可以这么说

let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
print("Num of Days: \(NumOfDays)")

Swift 3 iOS 10 Beta 4更新

func daysBetweenDates(startDate: Date, endDate: Date) -> Int {
let calendar = Calendar.current
let components = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
return components.day!
}

我看到了一些 Swift3的答案,所以我要加上我自己的:

public static func daysBetween(start: Date, end: Date) -> Int {
Calendar.current.dateComponents([.day], from: start, to: end).day!
}

命名感觉更迅捷,它是一行,并使用最新的 dateComponents()方法。

Erin 的方法更新到 Swift 3,这显示从今天开始的日子(不考虑时间)

func daysBetweenDates( endDate: Date) -> Int
let calendar: Calendar = Calendar.current
let date1 = calendar.startOfDay(for: Date())
let date2 = calendar.startOfDay(for: secondDate)
return calendar.dateComponents([.day], from: date1, to: date2).day!
}

以下是我对 Swift 3的回答:

func daysBetweenDates(startDate: NSDate, endDate: NSDate, inTimeZone timeZone: TimeZone? = nil) -> Int {
var calendar = Calendar.current
if let timeZone = timeZone {
calendar.timeZone = timeZone
}
let dateComponents = calendar.dateComponents([.day], from: startDate.startOfDay, to: endDate.startOfDay)
return dateComponents.day!
}

雨燕3天从今天到日期

func daysUntilDate(endDateComponents: DateComponents) -> Int
{
let cal = Calendar.current
var components = cal.dateComponents([.era, .year, .month, .day], from: NSDate() as Date)
let today = cal.date(from: components)
let otherDate = cal.date(from: endDateComponents)


components = cal.dateComponents([Calendar.Component.day], from: (today! as Date), to: otherDate!)
return components.day!
}

像这样调用函数

// Days from today until date
var examnDate = DateComponents()
examnDate.year = 2016
examnDate.month = 12
examnDate.day = 15
let daysCount = daysUntilDate(endDateComponents: examnDate)

更简单的选项是在 Date 上创建一个扩展

public extension Date {


public var currentCalendar: Calendar {
return Calendar.autoupdatingCurrent
}


public func daysBetween(_ date: Date) -> Int {
let components = currentCalendar.dateComponents([.day], from: self, to: date)
return components.day!
}
}

感谢上面的 Emin Bu ra SaralstartOfDay的建议。

extension Date {
    

func daysBetween(date: Date) -> Int {
return Date.daysBetween(start: self, end: date)
}
    

static func daysBetween(start: Date, end: Date) -> Int {
let calendar = Calendar.current
        

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: start)
let date2 = calendar.startOfDay(for: end)
        

let a = calendar.dateComponents([.day], from: date1, to: date2)
return a.value(for: .day)!
}
}

用法:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let start = dateFormatter.date(from: "2017-01-01")!
let end = dateFormatter.date(from: "2018-01-01")!


let diff = Date.daysBetween(start: start, end: end) // 365
// or
let diff = start.daysBetween(date: end) // 365

Swift 3.2

extension DateComponentsFormatter {
func difference(from fromDate: Date, to toDate: Date) -> String? {
self.allowedUnits = [.year,.month,.weekOfMonth,.day]
self.maximumUnitCount = 1
self.unitsStyle = .full
return self.string(from: fromDate, to: toDate)
}
}

2017版本,复制粘贴

func simpleIndex(ofDate: Date) -> Int {
    

// index here just means today 0, yesterday -1, tomorrow 1 etc.
    

let c = Calendar.current
let todayRightNow = Date()
    

let d = c.date(bySetting: .hour, value: 13, of: ofDate)
let t = c.date(bySetting: .hour, value: 13, of: todayRightNow)
    

if d == nil || today == nil {
    

print("weird problem simpleIndex#ofDate")
return 0
}
    

let r = c.dateComponents([.day], from: today!, to: d!)
// yesterday is negative one, tomorrow is one
    

if let o = r.value(for: .day) {
        

return o
}
else {
    

print("another weird problem simpleIndex#ofDate")
return 0
}
}

这里是非常好的,Date扩展得到日期之间的年,月,天,小时,分钟,秒的差异

extension Date {


func years(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.year], from: sinceDate, to: self).year
}


func months(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.month], from: sinceDate, to: self).month
}


func days(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.day], from: sinceDate, to: self).day
}


func hours(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.hour], from: sinceDate, to: self).hour
}


func minutes(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.minute], from: sinceDate, to: self).minute
}


func seconds(sinceDate: Date) -> Int? {
return Calendar.current.dateComponents([.second], from: sinceDate, to: self).second
}


}

一切正常。但是对于本地化,我们需要在两个日期之间计算小数点后的天数。所以我们可以提供可持续的十进制格式。

// This method returns the fractional number of days between to dates
func getFractionalDaysBetweenDates(date1: Date, date2: Date) -> Double {


let components = Calendar.current.dateComponents([.day, .hour], from: date1, to: date2)


var decimalDays = Double(components.day!)
decimalDays += Double(components.hour!) / 24.0


return decimalDays
}
  func completeOffset(from date:Date) -> String? {


let formatter = DateComponentsFormatter()
formatter.unitsStyle = .brief


return  formatter.string(from: Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date, to: self))








}

如果您需要年月日和小时作为字符串使用此

Var tomorrow = Calendar.current.Date (byAdd: . day,value: 1,to: Date ()) !

Let dc = tomorrow.CompleteOffset (from: Date ())

很好用的一句话:

extension Date {
var daysFromNow: Int {
return Calendar.current.dateComponents([.day], from: Date(), to: self).day!
}
}

这就返回了某些 Date与今天的天数之间的绝对差值:

extension Date {
func daysFromToday() -> Int {
return abs(Calendar.current.dateComponents([.day], from: self, to: Date()).day!)
}
}

然后使用它:

if someDate.daysFromToday() >= 7 {
// at least a week from today
}
extension Date {
func daysFromToday() -> Int {
return Calendar.current.dateComponents([.day], from: self, to: Date()).day!
}
}

那就好好利用

    func dayCount(dateString: String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd,yyyy hh:mm a"
let fetchedDate = dateFormatter.date(from: dateString)




let day = fetchedDate?.daysFromToday()
if day! > -1{
return "\(day!) days passed."
}else{
return "\(day! * -1) days left."
}
}

您可以使用以下扩展:

public extension Date {
func daysTo(_ date: Date) -> Int? {
let calendar = Calendar.current


// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: self)
let date2 = calendar.startOfDay(for: date)


let components = calendar.dateComponents([.day], from: date1, to: date2)
return components.day  // This will return the number of day(s) between dates
}
}

然后,你可以这样称呼它:

startDate.daysTo(endDate)

这是 Emin 对 Swift 5的回答的更新版本,其中包含了将午夜而不是午夜作为比较日子的确定时间的建议。它还通过返回一个可选的。

///
/// This is an approximation; it does not account for time differences. It will set the time to 1200 (noon) and provide the absolute number
/// of days between now and the given date. If the result is negative, it should be read as "days ago" instead of "days from today."
/// Returns nil if something goes wrong initializing or adjusting dates.
///


func daysFromToday() -> Int?
{
let calendar = NSCalendar.current


// Replace the hour (time) of both dates with noon. (Noon is less likely to be affected by DST changes, timezones, etc. than midnight.)
guard let date1 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: Date())),
let date2 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: self)) else
{
return nil
}
    

return calendar.dateComponents([.day], from: date1, to: date2).day
}

Swift 5.2.4解决方案:

import UIKit


let calendar = Calendar.current


let start = "2010-09-01"
let end = "2010-09-05"


let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"


let firstDate = dateFormatter.date(from: start)!
let secondDate = dateFormatter.date(from: end)!


// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)


let components = calendar.dateComponents([Calendar.Component.day], from: date1, to: date2)


components.day  // This will return the number of day(s) between dates

Swift 5

工作时,你需要设置的时间是相同的两天,如果你错过了几秒钟,这将是错误的

func daysBetween(start: Date, end: Date) -> Int {
let start = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: start)!
let end = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: end)!
return Calendar.current.dateComponents([.day], from: start, to: end).day ?? 0
}
extension Date {
static func - (recent: Date, previous: Date) -> DateComponents {
var dateComponents = DateComponents()
dateComponents.year = Calendar.current.dateComponents([.day], from: previous, to: recent).year
dateComponents.month = Calendar.current.dateComponents([.month], from: previous, to: recent).month
dateComponents.day = Calendar.current.dateComponents([.day], from: previous, to: recent).day
dateComponents.hour = Calendar.current.dateComponents([.hour], from: previous, to: recent).hour
dateComponents.minute = Calendar.current.dateComponents([.minute], from: previous, to: recent).minute
dateComponents.second = Calendar.current.dateComponents([.second], from: previous, to: recent).second
return dateComponents
}
}