【问题标题】:Comparing NSDates without time component比较没有时间分量的 NSDates
【发布时间】:2014-08-25 22:59:12
【问题描述】:

在一个快速的操场上,我一直在使用

NSDate.date() 

但是,这总是带有附加的时间元素。对于我的应用程序,我需要忽略时间元素。这在 Swift 中可能吗?如何做呢?即使我可以将时间元素设置为每个日期的相同时间也可以。

另外,我正在尝试比较两个日期,目前我正在使用以下代码:

var earlierDate:NSDate = firstDate.earlierDate(secondDate)

这是唯一的方法还是我可以忽略时间元素的方式做到这一点?例如,如果它们是同一天但不同时间,我不想要结果。

【问题讨论】:

  • 您不想“忽略”对象的时间部分。似乎您想将日期格式化为不带时间部分的字符串。你可以使用NSDateFormatter来做到这一点。

标签: ios time swift nsdate foundation


【解决方案1】:

回答你的问题:

这在 Swift 中可行吗?

是的,有可能


啊,你现在也想HOW

let cal = NSCalendar.currentCalendar()
cal.rangeOfUnit(.DayCalendarUnit, startDate: &d1, interval: nil, forDate: d1) // d1 NSDate?
cal.rangeOfUnit(.DayCalendarUnit, startDate: &d2, interval: nil, forDate: d2) // d2 NSDate?

现在 d1 和 d2 将包含它们开始时的日期。

d1!.compare(d2!)比较

要在没有时间部分的情况下显示它们,请使用 NSDateFormatter。

【讨论】:

  • 谢谢,你能不能也回答一下?!?
  • @agf119105 使用谷歌,例如。
  • 它回答了问题,不是吗?
  • 问题的措辞:“这在 Swift 中是否可行?如何做到?”意思是需要什么代码? @user3477950 试过谷歌谢谢,但对 Swift 没有有用的结果......
【解决方案2】:

当您在操场上NSDate.date() 时,您会看到打印的默认说明。使用NSDateFormatter 打印日期对象的本地化描述,可能只有日期部分。

要将日期的特定部分归零(为了比较),请将NSDateComponentsNSCalendar 结合使用。

【讨论】:

  • 啊,来吧,字符串操作?
  • 这无济于事,因为我知道如何在没有时间元素的情况下打印本地化描述。我想忽略时间元素,因为我需要比较两个日期而不妨碍时间
  • @agf119105 在这种情况下,使用NSDateComponents
【解决方案3】:

在 iOS 8.0+ 中使用 Calendar 函数比较日期

func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult


.day为单位传递

按如下方式使用该函数:

let now = Date()
// "Sep 23, 2015, 10:26 AM"
let olderDate = Date(timeIntervalSinceNow: -10000)
// "Sep 23, 2015, 7:40 AM"

var order = Calendar.current.compare(now, to: olderDate, toGranularity: .hour)

switch order {
case .orderedDescending:
    print("DESCENDING")
case .orderedAscending:
    print("ASCENDING")
case .orderedSame:
    print("SAME")
}

// Compare to hour: DESCENDING

var order = Calendar.current.compare(now, to: olderDate, toGranularity: .day)


switch order {
case .orderedDescending:
    print("DESCENDING")
case .orderedAscending:
    print("ASCENDING")
case .orderedSame:
    print("SAME")
}

// Compare to day: SAME

【讨论】:

  • 这是来自 UIKit 的吗?我在 Foundation 项目中找不到它。
  • 这是新的 iOS 8.0 NSCalendar API 之一。请参阅 iOS 7.1 到 iOS 8.0 API 差异 中的NSCalendar.h
  • 最后,我总是错过。
  • @theReverend 这是旧版 Swift 的遗留问题。已更新 2.0 - 谢谢!
  • 我认为这两个cmet,说明预期的结果是错误的。 // Compare to day: DESCENDING 应该是 SAME,反之亦然。
【解决方案4】:

在 iOS 8.0+ 的 NSCalendar 中有几个有用的方法:

startOfDayForDate, isDateInToday, isDateInYesterday, isDateInTomorrow

甚至可以比较天数:

func isDate(date1: NSDate!, inSameDayAsDate date2: NSDate!) -> Bool

要忽略时间元素,您可以使用:

var toDay = Calendar.current.startOfDay(for: Date())

但是,如果您还必须支持 iOS 7,您可以随时编写扩展程序

extension NSCalendar {
    func myStartOfDayForDate(date: NSDate!) -> NSDate!
    {
        let systemVersion:NSString = UIDevice.currentDevice().systemVersion
        if systemVersion.floatValue >= 8.0 {
            return self.startOfDayForDate(date)
        } else {
            return self.dateFromComponents(self.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date))
        }
    }
}

【讨论】:

    【解决方案5】:

    swift 中的两个日期比较。

        // Date comparision to compare current date and end date.
        var dateComparisionResult:NSComparisonResult = currentDate.compare(endDate)
    
        if dateComparisionResult == NSComparisonResult.OrderedAscending
        {
            // Current date is smaller than end date.
        }
        else if dateComparisionResult == NSComparisonResult.OrderedDescending
        {
            // Current date is greater than end date.
        }
        else if dateComparisionResult == NSComparisonResult.OrderedSame
        {
            // Current date and end date are same.
        }
    

    【讨论】:

    • 不完全。 NSDate 类型代表一个时间点;它包含日期元素和时间元素。因此,您的代码会比较两个时间点,而不是原始问题中的预期日历日期。
    【解决方案6】:

    根据我的经验,大多数人在使用 NSDate 时遇到的问题来自错误的假设,即 NSDate 可用于表示“正常”意义上的日期(即从本地时区午夜开始的 24 点)。在正常(日常/非编程)使用中,伦敦的 2014 年 1 月 1 日与北京或纽约的 1 月 1 日是同一日期即使它们实时涵盖不同的时期。更夸张地说,圣诞岛的时间是 UTC+14,而中途岛的时间是 UTC-11。因此,这两个岛上的 2014 年 1 月 1 日是同一日期,即使一个甚至在另一个完成一个小时后才开始。

    如果这是您正在记录的日期类型(如果您没有记录时间部分,可能是这样),那么不要使用 NSDate(它只存储 2001-01-01 00:00 UTC 之后的秒数,没有别的),而是将年月日存储为整数 - 可能通过创建您自己的 CivilDate 类来包装这些值 - 并使用它来代替。

    仅进入 NSDate 以比较日期,然后确保在两个 NSDate 上明确声明时区为“UTC”以进行比较。

    【讨论】:

      【解决方案7】:

      为了支持 iOS7

      let dateFormatter = NSDateFormatter()
      dateFormatter.dateFormat = "yyyy-MM-dd"
      let date1String = dateFormatter.stringFromDate(date1)
      let date2String = dateFormatter.stringFromDate(date2)
      if date1String == date2String {
          println("Equal date")
      }
      

      【讨论】:

      • 其他逻辑运算符,如<>>=<=,也可以。
      【解决方案8】:

      您可以使用它的描述比较两个日期。

      let date1 = NSDate()
      let date2 = NSDate(timeIntervalSinceNow: 120)
      if date1.description == date2.description {
          print(true)
      } else {
          print(false)   // false (I have added 2 seconds between them)
      }
      

      如果您想将日期的时间元素设置为不同的时间,您可以执行以下操作:

      extension NSDate {
          struct Calendar {
              static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
          }
          var day:    Int { return Calendar.gregorian.component(.Day,    fromDate: self)   }
          var month:  Int { return Calendar.gregorian.component(.Month,  fromDate: self)  }
          var year:   Int { return Calendar.gregorian.component(.Year,   fromDate: self)  }
      
          var noon: NSDate {
              return Calendar.gregorian.dateWithEra(1, year: year, month: month, day: day, hour: 12, minute: 0, second: 0, nanosecond: 0)!
          }
      }
      
      let date1 = NSDate()
      let date2 = NSDate(timeIntervalSinceNow: 120)
      print(date1.noon == date2.noon)   // true
      

      或者你也可以使用 NSDateFormatter:

      extension NSDate {
          struct Date {
              static let formatterYYYYMMDD: NSDateFormatter = {
                  let formatter = NSDateFormatter()
                  formatter.dateFormat = "yyyyMMdd"
                  return formatter
              }()
          }
          var yearMonthDay: String {
              return Date.formatterYYYYMMDD.stringFromDate(self)
          }
          func isSameDayAs(date:NSDate) -> Bool {
              return yearMonthDay == date.yearMonthDay
          }
      }
      
      let date1 = NSDate()
      let date2 = NSDate(timeIntervalSinceNow: 120)
      print(date1.yearMonthDay == date2.yearMonthDay)   // true
      
      print(date1.isSameDayAs(date2))    // true
      

      另一种选择(iOS8+)是使用日历方法 isDate(inSameDayAsDate:):

      extension NSDate {
          struct Calendar {
              static let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
          }
          func isInSameDayAs(date date: NSDate) -> Bool {
              return Calendar.gregorian.isDate(self, inSameDayAsDate: date)
          }
      }
      let date1 = NSDate()
      let date2 = NSDate(timeIntervalSinceNow: 120)
      if date1.isInSameDayAs(date: date2 ){
          print(true)   // true
      } else {
          print(false)
      }
      

      【讨论】:

        【解决方案9】:

        斯威夫特:

        extension NSDate {
        
            /**
            Compares current date with the given one down to the seconds.
            If date==nil, then always return false
        
            :param: date date to compare or nil
        
            :returns: true if the dates has equal years, months, days, hours, minutes and seconds.
            */
            func sameDate(date: NSDate?) -> Bool {
                if let d = date {
                    let calendar = NSCalendar.currentCalendar()
                    if NSComparisonResult.OrderedSame == calendar.compareDate(self, toDate: d, toUnitGranularity: NSCalendarUnit.SecondCalendarUnit) {
                        return true
                    }
        
                }
                return false
            }
        }
        

        【讨论】:

          【解决方案10】:

          我通过借鉴 Ashley Mills 解决方案编写了以下方法来比较两个日期。它比较两个日期,如果两个日期相同(除去时间),则返回 true。

          func compareDate(date1:NSDate, date2:NSDate) -> Bool {
              let order = NSCalendar.currentCalendar().compareDate(date1, toDate: date2,
                  toUnitGranularity: .Day)
              switch order {
              case .OrderedSame:
                  return true
              default:
                  return false
              }
          }
          

          它是这样称呼的:

          if compareDate(today, date2: anotherDate) {
              // The two dates are on the same day.
          }
          

          【讨论】:

            【解决方案11】:

            对于 Swift3

            var order = NSCalendar.current.compare(firstDate, to: secondDate, toGranularity: .hour)
            
            if order == .orderedSame {
                //Both the dates are same. 
                //Your Logic.
            }
            

            【讨论】:

              【解决方案12】:

              斯威夫特 3

                      let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)
              
                      if order == .orderedAscending { 
                        // date 1 is older
                      }
                      else if order == .orderedDescending { 
                        // date 1 is newer
                      }
                      else if order == .orderedSame { 
                        // same day/hour depending on granularity parameter
                      }
              

              【讨论】:

                【解决方案13】:

                在 Swift 4 中:

                func compareDate(date1:Date, date2:Date) -> Bool {
                    let order = NSCalendar.current.compare(date1, to: date2, toGranularity: .day)
                    switch order {
                    case .orderedSame:
                        return true
                    default:
                        return false
                    }
                }
                

                【讨论】:

                  【解决方案14】:

                  我写了一个 Swift 4 扩展来比较两个日期:

                  import Foundation
                  
                  extension Date {      
                    func isSameDate(_ comparisonDate: Date) -> Bool {
                      let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
                      return order == .orderedSame
                    }
                  
                    func isBeforeDate(_ comparisonDate: Date) -> Bool {
                      let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
                      return order == .orderedAscending
                    }
                  
                    func isAfterDate(_ comparisonDate: Date) -> Bool {
                      let order = Calendar.current.compare(self, to: comparisonDate, toGranularity: .day)
                      return order == .orderedDescending
                    }
                  }
                  

                  用法:

                  startDate.isSameDateAs(endDate) // returns a true or false

                  【讨论】:

                    【解决方案15】:

                    斯威夫特 4

                    func compareDate(date1:Date, date2:Date) -> Bool {
                        let order = Calendar.current.compare(date1, to: date2,toGranularity: .day)
                        switch order {
                        case .orderedSame:
                            return true
                        default:
                            return false
                        }
                    }
                    

                    【讨论】:

                    • 这是 18 个月前 @zs2020 答案的相同副本
                    【解决方案16】:

                    Xcode 11.2.1、Swift 5 及以上

                    检查日期是否包含同一天。

                    Calendar.current.isDate(date1, equalTo: date2, toGranularity: .day)
                    

                    根据需要调整粒度。

                    【讨论】:

                      【解决方案17】:

                      如果您需要比较日期是否与其他日期在同一天,请使用:

                      Calendar.current.isDate(date1, inSameDayAs: date2)
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-07-22
                        • 2018-07-28
                        • 2013-11-15
                        • 2013-11-13
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多