Swift - 检查日期是否在下周/月。 (isDateInNextWeek()isDateInNextMonth())

问题描述 投票:1回答:3

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

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

但我错过了那两个:

  • calendar.isDateInNextWeek(日期)
  • calendar.isDateInNextMonth(日期)

正如@Rob所提到的那样,意思是:“在今天星期日开始的日历周中,通过下一个星期六”

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

有人可以提供助手吗?

xcode swift nsdate nscalendar
3个回答
4
投票

算法不是很壮观:

  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本月”

听起来不错。

如果你想使用<===<等而不是丑陋(和令人困惑的)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)

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


0
投票

我想出了这个天真的代码:

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
        }
    }
}

但我必须在这里遗漏一些边缘案例。

© www.soinside.com 2019 - 2024. All rights reserved.