如何在特定月份的每个星期四或其他星期获取日期?

时间:2017-05-03 12:51:35

标签: ios swift

我希望每周都能获得特定日期的日期。

假设我有一个日期:2017-04-13。这是4月,4月13日是Thursday。我需要在4月份获得Thursday的每个日期。

我该怎么做?

输出应为:2017-04-062017-04-132017-04-202017-04-27

5 个答案:

答案 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())!))