我希望每周都能获得特定日期的日期。
假设我有一个日期:2017-04-13
。这是4月,4月13日是Thursday
。我需要在4月份获得Thursday
的每个日期。
我该怎么做?
输出应为:2017-04-06
,2017-04-13
,2017-04-20
,2017-04-27
答案 0 :(得分:2)
简短解决方案:
<击> //获取当前日历和当前日期 let calendar = Calendar.current 现在让我们= Date() //获取年,月,工作日和工作日序号的当前日期组件 var components = calendar.dateComponents([。year,.month,.weekdayOrdinal,.weekday],from:now) //获取当月特定工作日的范围(出现次数) let range = calendar.range(of:。weekdayOrdinal,in:。month,for:now)! //循环通过范围,将组件设置为适当的工作日序数并获取日期 对于range.lowerBound中的序数.. 击>
请注意print
始终以UTC格式打印日期。
修改:
range(of: .weekdayOrdinal, in: .month
不起作用,无论日期如何,都会返回1..<6
。
这是一个可行的替代方案。它会检查日期是否超过月份范围
// Get current calendar and date for 2017/4/13
let calendar = Calendar.current
let april13Components = DateComponents(year:2017, month:4, day:13)
let april13Date = calendar.date(from: april13Components)!
// Get the current date components for year, month, weekday and weekday ordinal
var components = calendar.dateComponents([.year, .month, .weekdayOrdinal, .weekday], from: april13Date)
// Loop thru the range, set the components to the appropriate weekday ordinal and get the date
for ordinal in 1..<6 { // maximum 5 occurrences
components.weekdayOrdinal = ordinal
let date = calendar.date(from: components)!
if calendar.component(.month, from: date) != components.month! { break }
print(calendar.date(from: components)!)
}
答案 1 :(得分:0)
这段代码完成了这项工作。我添加了一些日志来理解它背后的一些逻辑。
您可以根据需要设置dateInit
,其余代码将查找同月同一工作日的所有日期。
我打印了两个版本的日期表示(NSDate
个对象和NSString
个对象),对于那个遇到时区问题和“不是同一天”哭泣的人来说。
它使用enumerateDatesStartingAfterDate:matchingComponents:options:usingBlock:
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
NSString *dateStr = @"2017-04-13";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
NSDate *dateInit = [dateFormatter dateFromString:dateStr];
NSLog(@"dateInit: %@", dateInit);
NSDateComponents *componentsToMatch = [calendar components:(NSCalendarUnitMonth|NSCalendarUnitWeekday) fromDate:dateInit];
NSDate *startOfMonth = [calendar dateFromComponents:[calendar components:(NSCalendarUnitYear|NSCalendarUnitMonth) fromDate:dateInit]];
NSLog(@"StartOfTheMonth: %@", startOfMonth);
NSArray *daysToFind = @[@"2017-04-06", @"2017-04-13", @"2017-04-20", @"2017-04-27"]; //According to author
NSLog(@"DaysToFind: %@", daysToFind);
NSMutableArray *allDaysInMonthMatchingWeekDay = [[NSMutableArray alloc] init];
[calendar enumerateDatesStartingAfterDate:startOfMonth
matchingComponents:componentsToMatch
options:NSCalendarMatchStrictly
usingBlock:^(NSDate * _Nullable date, BOOL exactMatch, BOOL * _Nonnull stop) {
NSLog(@"DateBlock: %@", date);
[allDaysInMonthMatchingWeekDay addObject:date];
}];
NSLog(@"allDaysInMonthMatchingWeekDay: %@",allDaysInMonthMatchingWeekDay);
for (NSDate *aDate in allDaysInMonthMatchingWeekDay)
{
NSLog(@"Found: %@", [dateFormatter stringFromDate:aDate]);
}
日志:
$>dateInit: 2017-04-12 22:00:00 +0000
$>StartOfTheMonth: 2017-03-31 22:00:00 +0000
$>DaysToFind: (
"2017-04-06",
"2017-04-13",
"2017-04-20",
"2017-04-27"
)
$>DateBlock: 2017-04-05 22:00:00 +0000
$>DateBlock: 2017-04-12 22:00:00 +0000
$>DateBlock: 2017-04-19 22:00:00 +0000
$>DateBlock: 2017-04-26 22:00:00 +0000
$>allDaysInMonthMatchingWeekDay: (
"2017-04-05 22:00:00 +0000",
"2017-04-12 22:00:00 +0000",
"2017-04-19 22:00:00 +0000",
"2017-04-26 22:00:00 +0000"
)
$>Found: 2017-04-06
$>Found: 2017-04-13
$>Found: 2017-04-20
$>Found: 2017-04-27
注意:对于componentsToMatch
,我尝试设置Year / Month / WeekDay标志单元,但枚举在第一次出现时停止,没有搜索多长时间,为什么我只想出月和工作日标志让它工作。也许是我错过的一些小问题。
编辑: 在Swift 3中(它可以工作,但由于我是Objective-C开发人员,而不是Swift版本,它可能会出现问题,例如包装/解包等)
let calendar = NSCalendar.init(calendarIdentifier: .gregorian)
let dateStr = "2017-04-13"
let dateFormatter = DateFormatter.init()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateInit = dateFormatter.date(from: dateStr)!
print("dateInit: \(dateInit)")
let componentsToMatch = calendar?.components([.month,.weekday], from: dateInit)
let startOfMonth = calendar?.date(from: (calendar?.components([.year,.month], from: dateInit))!)
print("StartOfTheMonth:\(startOfMonth)")
calendar?.enumerateDates(startingAfter: startOfMonth!, matching: componentsToMatch!, options: .matchStrictly, using: { (date, extactMatch, stop) in
print("DateBlock: \(date)")
})
答案 2 :(得分:0)
正如评论中所建议的那样。看到更新的代码。以工作日更新
func getNumberOfDaysInMonth (month : Int , Year : Int, weekday: Int) -> [String]{
let dateComponents = NSDateComponents()
dateComponents.year = Year
dateComponents.month = month
let calendar = Calendar.current
let date = calendar.date(from: dateComponents as DateComponents)
let range = calendar.range(of: .day, in: .month, for: date!)
let numDays:Int = (range?.upperBound)!
let thuFormatter = DateFormatter()
var dateArray:[String] = [String]()
thuFormatter.dateFormat = "yyyy-MM-dd"
for day in 1...numDays {
dateComponents.day = day
let date2 = calendar.date(from: dateComponents as DateComponents)
print(calendar.component(.weekday, from: date2!))
if calendar.component(.weekday, from: date2!) == weekday
{
let dateThu = thuFormatter.string(from: date2!)
dateArray.append(dateThu)
}
}
return dateArray
}
然后将其称为
let myThu:[String] = getNumberOfDaysInMonth(month: 4, Year: 2017,weekday: 3)
print(myThu)
答案 3 :(得分:0)
试试这个游乐场:
import UIKit
let dateString = "2017-04-13"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let referenceDate = dateFormatter.date(from: dateString)!
let calendar = Calendar.current
let firstDayComponents = calendar.dateComponents([.year, .month], from: referenceDate)
let monthFirst = calendar.date(from: firstDayComponents)!
let weekDay = calendar.component(.weekday, from: referenceDate)
var oneDay = DateComponents()
oneDay.day = 1
var checkDate = monthFirst
while calendar.component(.month, from: checkDate) == calendar.component(.month, from: referenceDate) {
if calendar.component(.weekday, from: checkDate) == weekDay {
let thisDay = dateFormatter.string(from: checkDate)
print(thisDay)
}
checkDate = calendar.date(byAdding: oneDay, to: checkDate)!
}
答案 4 :(得分:0)
我会在任何给定的时间范围内为Calendar
写一个扩展名,并使用枚举来命名工作日
enum WeekDay: Int {
case sunday = 1
case monday
case tuesday
case wednesday
case thursday
case friday
case saturday
}
struct TimeSpan {
let startDate: Date
let endDate: Date
}
extension Calendar {
func allOccurrenceOf(day: WeekDay, in timeSpan:TimeSpan) -> [Date] {
let startDateWeekDay = Int(self.component(.weekday, from: timeSpan.startDate))
let desiredDay = day.rawValue
let offset = (desiredDay - startDateWeekDay + 7) % 7
let firstOccurrence = self.startOfDay(for:self.date(byAdding: DateComponents(day:offset), to: timeSpan.startDate)!)
guard firstOccurrence.timeIntervalSince1970 < timeSpan.endDate.timeIntervalSince1970 else {
return []
}
var filtered = [firstOccurrence]
while true {
let nextDate = self.date(byAdding: DateComponents(day: 7), to: filtered.last!)!
if nextDate < timeSpan.endDate {
filtered.append(nextDate)
break
}
}
return filtered
}
}
请注意,我这很快就会被攻击。我相信这可以表达得更加迅速。在实际生产代码中,我也会尝试从中消除所有!
。
用法:
let tuesdays = Calendar.autoupdatingCurrent.allOccurrenceOf(day: .tuesday, in: TimeSpan(startDate: Date(), endDate: Calendar.autoupdatingCurrent.date(byAdding: DateComponents(month:1), to: Date())!))