Swift 如何从NSDate开始查找一周的开始?
我正在实现一个日历视图,我希望它从包含特定日期的周初开始。如果目标日期是2016年2月29日星期一,当前日历设置为周日开始,我希望我的视图从2月28日周日开始 这似乎应该是直截了当的:Swift 如何从NSDate开始查找一周的开始?,swift,date,calendar,Swift,Date,Calendar,我正在实现一个日历视图,我希望它从包含特定日期的周初开始。如果目标日期是2016年2月29日星期一,当前日历设置为周日开始,我希望我的视图从2月28日周日开始 这似乎应该是直截了当的: let calendar = NSCalendar.currentCalendar() let firstDate = calendar.nextDateAfterDate(targetDate, matchingUnit: .Weekday,
let calendar = NSCalendar.currentCalendar()
let firstDate = calendar.nextDateAfterDate(targetDate,
matchingUnit: .Weekday,
value: calendar.firstWeekday,
options: .SearchBackwards)
但这在以下方面失败:
由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“必须指定集合{NSCalendarMatchPreviousTimePreservingSmallerUnits,NSCalendarMatchNextTimePreservingSmallerUnits,NSCalendarMatchNextTime}中的一个选项。”
我基本上可以通过以下方式获得我想要的:
let firstDate = calendar.nextDateAfterDate(firstDate,
matchingUnit: .Weekday,
value: calendar.firstWeekday,
options: .MatchPreviousTimePreservingSmallerUnits)?
.dateByAddingTimeInterval(-7 * 84600)
但这似乎是一个糟糕的做法,因为有时一天的秒数不是86400
有更好的方法吗?基本上使用
压片机
及
dateByAddingComponents
。要解决您的问题,请尝试使用以下代码示例:
let cal = NSCalendar.currentCalendar()
let components = NSDateComponents()
components.weekOfYear -= 1
if let date = cal.dateByAddingComponents(components, toDate: NSDate(), options: NSCalendarOptions(0)) {
var beginningOfWeek: NSDate?
var weekDuration = NSTimeInterval()
if cal.rangeOfUnit(.CalendarUnitWeekOfYear, startDate: &beginningOfWeek, interval: &weekDuration, forDate: date) {
print(beginningOfWeek)
}
}
您可以使用
Calendar
方法date(from:DateComponents)
从任何日期传递[.yearForWeekOfYear.weekOfYear]
组件它将返回所用日历中一周的第一天。所以,如果你想得到周日,就用公历吧。如果您想将周一作为一周的第一天,可以使用Calendar.iso8601
,如图所示
Xcode 12•Swift 5.3或更高版本(也适用于以前的Swift版本)
用法:
Date().startOfWeek() // "Sep 20, 2020 at 12:00 AM"
如果您希望在特定时区获得一周的开始时间,您只需要使用自定义日历:
var gregorianUTC = Calendar.gregorian
gregorianUTC.timeZone = TimeZone(identifier: "UTC")!
print(Date().startOfWeek(using: gregorianUTC)) // "2020-09-20 00:00:00 +0000\n"
日历有一种机制,用于在包含给定日期的给定时间间隔(如一年中的一周或一个月)的开始处查找日期:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = dateFormatter.date(from: "2017-01-07")
if let date = date {
let calendar = Calendar(identifier: .gregorian)
var startDate : Date = Date()
var interval : TimeInterval = 0
if calendar.dateInterval(of: .weekOfYear, start: &startDate, interval: &interval, for: date) {
print("Start of week is \(startDate)")
// prints "Start of week is 2017-01-01 06:00:00 +0000"
}
}
Swift 4解决方案 我已经根据我的要求计算出了,我已经找到了下面的日期
1. Today
2. Tomorrow
3. This Week
4. This Weekend
5. Next Week
6. Next Weekend
因此,我创建了日期扩展
,以获取本周和下周的日期
代码
extension Date {
func getWeekDates() -> (thisWeek:[Date],nextWeek:[Date]) {
var tuple: (thisWeek:[Date],nextWeek:[Date])
var arrThisWeek: [Date] = []
for i in 0..<7 {
arrThisWeek.append(Calendar.current.date(byAdding: .day, value: i, to: startOfWeek)!)
}
var arrNextWeek: [Date] = []
for i in 1...7 {
arrNextWeek.append(Calendar.current.date(byAdding: .day, value: i, to: arrThisWeek.last!)!)
}
tuple = (thisWeek: arrThisWeek,nextWeek: arrNextWeek)
return tuple
}
var tomorrow: Date {
return Calendar.current.date(byAdding: .day, value: 1, to: noon)!
}
var noon: Date {
return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
var startOfWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 1, to: sunday!)!
}
func toDate(format: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: self)
}
}
您可以根据需要修改扩展名
谢谢我以前的所有解决方案都有问题,因为它们没有考虑用户的日历设置。下一个代码将考虑到这一点
extension Date {
var startOfWeek: Date? {
let calendar = Calendar.current
var components: DateComponents? = calendar.dateComponents([.weekday, .year, .month, .day], from: self)
var modifiedComponent = components
modifiedComponent?.day = (components?.day ?? 0) - ((components?.weekday ?? 0) - 1)
return calendar.date(from: modifiedComponent!)
}
var endOfWeek: Date? {
let calendar = Calendar.current
var components: DateComponents? = calendar.dateComponents([.weekday, .year, .month, .day], from: self)
var modifiedComponent = components
modifiedComponent?.day = (components?.day ?? 0) + (7 - (components?.weekday ?? 0))
modifiedComponent?.hour = 23
modifiedComponent?.minute = 59
modifiedComponent?.second = 59
return calendar.date(from: modifiedComponent!)
}
}
您可以将其实现为日期类扩展或其他内容。它应该返回类似于
2020-01-06 00:00:00+0000的值
Xcode 11.3 Swift 5
func firstDayOfWeek() -> Date {
var c = Calendar(identifier: .iso8601)
c.timeZone = TimeZone(secondsFromGMT: 0)!
print(
c.date(from: c.dateComponents([.weekOfYear, .yearForWeekOfYear], from: Date()))!
)
}
谢谢这是一个优雅的方式,这是一个很酷的方式,但它有一个小问题,夏令时。这可以通过以下代码修复:var startOfWeek:NSDate{let date=Calendar.gregorian.datefrom组件(Calendar.gregorian.components([.YearForWeekOfYear.WeekOfYear],fromDate:self));let dsltimecoffset=NSTimeZone.local.daylightsavingtimecoffset(for:date);return date.addingTimeInterval(dsltimecoffset);}
最好使用NSCalendar.autoupdateingcurrent而不是gregorian您必须使用Calendar.current而不是Calendar(标识符:.gregorian)可能不是,但我更喜欢将其保留为可选,并使用guard作为常用的hanks!虽然我用另一种方法来解决这个问题,但这个答案帮助我更好地理解了如何使用DATEYBADION组件。别忘了你可以设定你想考虑哪一天是第一天使用:var GRGGORION =日历(标识符:GRGORION)gregorian.firstWeekday=2//monday这将返回UTC时间而非本地时间的一周开始时间。
let arrWeekDates = Date().getWeekDates() // Get dates of Current and Next week.
let dateFormat = "MMM dd" // Date format
let thisMon = arrWeekDates.thisWeek.first!.toDate(format: dateFormat)
let thisSat = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 2].toDate(format: dateFormat)
let thisSun = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 1].toDate(format: dateFormat)
let nextMon = arrWeekDates.nextWeek.first!.toDate(format: dateFormat)
let nextSat = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 2].toDate(format: dateFormat)
let nextSun = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 1].toDate(format: dateFormat)
print("Today: \(Date().toDate(format: dateFormat))") // Sep 26
print("Tomorrow: \(Date().tomorrow.toDate(format: dateFormat))") // Sep 27
print("This Week: \(thisMon) - \(thisSun)") // Sep 24 - Sep 30
print("This Weekend: \(thisSat) - \(thisSun)") // Sep 29 - Sep 30
print("Next Week: \(nextMon) - \(nextSun)") // Oct 01 - Oct 07
print("Next Weekend: \(nextSat) - \(nextSun)") // Oct 06 - Oct 07
extension Date {
var startOfWeek: Date? {
let calendar = Calendar.current
var components: DateComponents? = calendar.dateComponents([.weekday, .year, .month, .day], from: self)
var modifiedComponent = components
modifiedComponent?.day = (components?.day ?? 0) - ((components?.weekday ?? 0) - 1)
return calendar.date(from: modifiedComponent!)
}
var endOfWeek: Date? {
let calendar = Calendar.current
var components: DateComponents? = calendar.dateComponents([.weekday, .year, .month, .day], from: self)
var modifiedComponent = components
modifiedComponent?.day = (components?.day ?? 0) + (7 - (components?.weekday ?? 0))
modifiedComponent?.hour = 23
modifiedComponent?.minute = 59
modifiedComponent?.second = 59
return calendar.date(from: modifiedComponent!)
}
}
func firstDayOfWeek() -> Date {
var c = Calendar(identifier: .iso8601)
c.timeZone = TimeZone(secondsFromGMT: 0)!
print(
c.date(from: c.dateComponents([.weekOfYear, .yearForWeekOfYear], from: Date()))!
)
}