【问题标题】:Swift - Check if date is in next week / month. ( isDateInNextWeek() isDateInNextMonth() )Swift - 检查日期是否在下周/下个月。 ( isDateInNextWeek() isDateInNextMonth() )
【发布时间】:2015-05-17 07:37:23
【问题描述】:

我们在日历中有那些方便的功能:

let calendar = NSCalendar.currentCalendar()
calendar.isDateInToday(date)
calendar.isDateInTomorrow(date)

但我错过了这两个:

  • calendar.isDateInNextWeek(日期)

  • calendar.isDateInNextMonth(日期)

正如@Rob 提到的,意思是:“在接下来的星期日开始的日历周中,经过下一个星期六”

我很难弄清楚如何以一种涵盖所有极端情况的稳健方式来实现这些功能。

有人可以提供助手吗?

【问题讨论】:

  • @Rob 我的意思是“在接下来的星期日开始的日历周内,一直到下一个星期六”

标签: xcode swift nsdate nscalendar


【解决方案1】:

使用Swift 5 和扩展Calendar 解决了问题。

extension Calendar {
  private var currentDate: Date { return Date() }

  func isDateInThisWeek(_ date: Date) -> Bool {
    return isDate(date, equalTo: currentDate, toGranularity: .weekOfYear)
  }

  func isDateInThisMonth(_ date: Date) -> Bool {
    return isDate(date, equalTo: currentDate, toGranularity: .month)
  }

  func isDateInNextWeek(_ date: Date) -> Bool {
    guard let nextWeek = self.date(byAdding: DateComponents(weekOfYear: 1), to: currentDate) else {
      return false
    }
    return isDate(date, equalTo: nextWeek, toGranularity: .weekOfYear)
  }

  func isDateInNextMonth(_ date: Date) -> Bool {
    guard let nextMonth = self.date(byAdding: DateComponents(month: 1), to: currentDate) else {
      return false
    }
    return isDate(date, equalTo: nextMonth, toGranularity: .month)
  }

  func isDateInFollowingMonth(_ date: Date) -> Bool {
    guard let followingMonth = self.date(byAdding: DateComponents(month: 2), to: currentDate) else {
      return false
    }
    return isDate(date, equalTo: followingMonth, toGranularity: .month)
  }
}

用法:

let day: Double = 60 * 60 * 24
let currentDate = Date() // Thu 25 Apr 2019
let futureDate = Date(timeInterval: 3 * day, since: currentDate) // Sun 28 Apr 2019
if Calendar.current.isDateInThisWeek(futureDate) { 
    // this will be executed if first day of week is Monday
} else {
    // this will be executed if first day of week is Sunday
}

代码根据Calendar 实例评估日期是否在范围(sameWeek、nextWeek)内。

如果Calendar 实例为current,它将根据设备设置确定一周的开始时间(周一或周日),但如果您想要不同的行为,您可以更改Calendar 实例: Calendar(identifier: .chinese).isDateInNextWeek(someDate)

如果我们尝试使用不正确的值创建DateComponents,此代码也可以工作,例如:DateComponents(year: 2019, month: 13)。 在这种情况下,它会创建日期01 Jan 2020

【讨论】:

    【解决方案2】:

    算法不是很壮观:

    1. 计算本周开始
    2. 使用 1 的结果来计算下周开始
    3. 使用 2 的结果来计算下周之后的一周开始
    4. 如果日期在下周开始或之后,并且在下周之后的一周开始之前,则日期为下周

    NSCalendar 为我们完成了大部分工作。但它看起来还是有点吓人,至少如果你不经常使用这些日期方法的话。您应该阅读所有这些方法的文档以了解它们。

    let calendar = NSCalendar.currentCalendar()
    let date = NSDate()
    
    var startOfThisWeek: NSDate?
    if !calendar.rangeOfUnit(.CalendarUnitWeekOfMonth, startDate: &startOfThisWeek, interval: nil, forDate: date) {
        fatalError("Can't calculate start of this week")
    }
    let startOfNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfThisWeek!, options: nil)!
    let startOfNextNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfNextWeek, options: nil)!
    

    只需将.CalendarUnitWeekOfMonth.CalendarUnitMonth 切换,您就可以获得下个月和下个月的计算。

    var startOfThisMonth: NSDate?
    if !calendar.rangeOfUnit(.CalendarUnitMonth, startDate: &startOfThisMonth, interval: nil, forDate: date) {
        fatalError("Can't calculate start of this month")
    }
    let startOfNextMonth = calendar.dateByAddingUnit(.CalendarUnitMonth, value: 1, toDate: startOfThisMonth!, options: nil)!
    let startOfNextNextMonth = calendar.dateByAddingUnit(.CalendarUnitMonth, value: 1, toDate: startOfNextMonth, options: nil)!
    

     

    还有测试:

    let testDate = NSDate(timeIntervalSinceNow: 7*24*60*60)
    
    if startOfThisWeek <= testDate && testDate < startOfNextWeek {
        println("\(testDate) is this week")
    }
    if startOfNextWeek <= testDate && testDate < startOfNextNextWeek {
        println("\(testDate) is next week")
    }
    if startOfThisMonth <= testDate && testDate < startOfNextMonth {
        println("\(testDate) is this month")
    }
    if startOfNextMonth <= testDate && testDate < startOfNextNextMonth {
        println("\(testDate) is next month")
    }
    

    结果:

    “2015-03-22 02:55:19 +0000 是下周”
    "2015-03-22 02:55:19 +0000 是这个月"

    听起来不错。

    如果您想使用&lt;===&lt; 等而不是丑陋(且令人困惑)NSComparisonResult,您也需要这个:

    public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
        return lhs === rhs || lhs.compare(rhs) == .OrderedSame
    }
    
    public func <(lhs: NSDate, rhs: NSDate) -> Bool {
        return lhs.compare(rhs) == .OrderedAscending
    }
    
    extension NSDate: Comparable { }
    

    这是 iOS8 代码。如果你想编写适用于旧版本的代码,你必须用旧的 NSDateComponents 替换 dateByAddingUnit:value::toDate:options:。即:

    let offSetComponents = NSDateComponents()
    offSetComponents.weekOfMonth = 1
    let startOfNextWeek = calendar.dateByAddingComponents(offSetComponents, toDate: startOfThisWeek, options: nil)
    

    【讨论】:

      【解决方案3】:

      我想出了这个幼稚的代码:

      extension NSCalendar
      {
          func isDateInNextWeek(value: NSDate) -> Bool
          {
              let componentsValue = self.components(.WeekOfYearCalendarUnit | .YearCalendarUnit,  fromDate: value)
              let componentsToday = self.components(.WeekOfYearCalendarUnit | .YearCalendarUnit,  fromDate: NSDate())
      
              let weekOfYearValue = componentsValue.weekOfYear
              let weekOfYearToday = componentsToday.weekOfYear
              let yearValue = componentsValue.year
              let yearToday = componentsToday.year
      
              if(yearValue < yearToday)
              {
                  return false
              }
              else if(yearValue == yearToday && weekOfYearValue - weekOfYearToday == 1)
              {
                 return true
              }
              else if(yearValue - yearToday == 1 && weekOfYearValue == 1 && weekOfYearToday == 52)
              {
                  return true
              }
              else
              {
                  return false
              }
          }
      }
      

      但我必须在这里遗漏一些边缘情况。

      【讨论】:

        猜你喜欢
        • 2018-09-01
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-01
        • 2020-12-10
        • 1970-01-01
        相关资源
        最近更新 更多