0

我正在制作一个 iPhone 倒计时应用程序,并且需要知道在用户设置的日期之前一个周末(如周六和周日)会发生多少次。

举个例子,我怎么知道从现在(8 月 6 日星期一)到下周有多少个周末?知道答案是 1 个周末,但我需要能够使用代码来解决这个问题。

我得到的最接近的是使用 NSDateComponents 和 NSCalender 并做一些接近以下的事情。

NSDateComponents *weekendsLeftComponents = [calendar components:NSWeekCalendarUnit
                                                    fromDate:targetDate
                                                      toDate:[NSDate date]
                                                     options:0];

但是从那里我已经碰到了可怕的编码员墙。

我的问题是不完全知道如何去做。听起来阵列可以工作,但我担心阵列可能会变得相当大,因为其中一些“东西”可能会持续几年。(我正在制作一个应用程序,它可以找出一个人毕业前还有多少天、周末等。)此外,我的受众主要是拥有 iPod 的孩子到青少年,还有年龄较大的。我不知道他们的内存(ram)在用完之前能达到多少。

非常感谢你,

亚历克斯·卡弗

4

2 回答 2

1

假设是在未来,它看起来像你的fromDate并且toDate是倒退的。targetDate

这是我解决这个问题的方法。

创建一个类别NSCalendar以计算特定工作日在两个日期之间出现的次数:

@interface NSCalendar (AlexCategory)

// The number of times weekday number `weekday` (1 = Sunday, 7 = Saturday)
// occurs between `fromDate` and `toDate`.  If `fromDate` falls on the desired
// weekday, it is counted.  If `toDate` falls on the desired weekday, it is NOT counted.
- (NSInteger)countOfWeekday:(NSInteger)weekday fromDate:(NSDate *)fromDate toDate:(NSDate *)toDate;

@end

为了实现这个新方法,我们将首先获取 的年、月、日和工作日fromDate

@implementation NSCalendar (AlexCategory)

- (NSInteger)countOfWeekday:(NSInteger)weekday fromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
    NSDateComponents *components = [self components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit fromDate:fromDate];

fromDate接下来,我们计算从下一个期望的工作日到多少天:

    NSInteger daysUntilDesiredWeekday = weekday - components.weekday;
    // If fromDate is a Wednesday and weekday is Monday (for example),
    // daysUntilDesiredWeekday is negative.  Fix that.
    NSRange weekdayRange = [self minimumRangeOfUnit:NSWeekdayCalendarUnit];
    if (daysUntilDesiredWeekday < weekdayRange.location) {
        daysUntilDesiredWeekday += weekdayRange.length;
    }

请注意,如果落在所需的工作日,daysUntilDesiredWeekday它将为零。fromDate

现在我们可以NSDateComponents在 或之后创建一个表示第一个所需的工作日fromDate

    NSDateComponents *firstDesiredWeekday = [[NSDateComponents alloc] init];
    firstDesiredWeekday.year = components.year;
    firstDesiredWeekday.month = components.month;
    firstDesiredWeekday.day = components.day + daysUntilDesiredWeekday;

我们更新fromDate为第一个期望的工作日,如果它是 on 或之后返回 0 toDate

    fromDate = [self dateFromComponents:firstDesiredWeekday];
    if ([fromDate compare:toDate] != NSOrderedAscending) {
        return 0;
    }

fromDate接下来我们计算从更新到的所有天数(不仅仅是所需的工作日)toDate

    NSInteger allDaysCount = [self components:NSDayCalendarUnit
        fromDate:fromDate toDate:toDate options:0].day;

我们可以将其除以一周中的天数,以仅计算所需的工作日数。由于我们从所需的工作日开始计数,任何部分周余数也将包含所需的工作日,因此我们需要四舍五入:

    // Adding weekdayRange.length - 1 makes the integer division round up.
    return (allDaysCount + weekdayRange.length - 1) / weekdayRange.length;
}

@end

我们可以这样测试方法:

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components = [[NSDateComponents alloc] init];
components.year = 2012;
components.month = 1;
components.day = 1;
NSDate *fromDate = [calendar dateFromComponents:components];

for (NSUInteger i = 1; i <= 365; ++i) {
    components.day = i;
    NSDate *toDate = [calendar dateFromComponents:components];
    NSLog(@"%@ to %@: %ld Mondays", fromDate, toDate, [calendar countOfWeekday:2 fromDate:fromDate toDate:toDate]);
}

输出开始如下:

2012-08-06 16:27:05.751 tuesdays[81152:403] 0 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-01 06:00:00 +0000
2012-08-06 16:27:05.754 tuesdays[81152:403] 0 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-02 06:00:00 +0000
2012-08-06 16:27:05.756 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-03 06:00:00 +0000
2012-08-06 16:27:05.758 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-04 06:00:00 +0000
2012-08-06 16:27:05.759 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-05 06:00:00 +0000
2012-08-06 16:27:05.760 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-06 06:00:00 +0000
2012-08-06 16:27:05.762 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-07 06:00:00 +0000
2012-08-06 16:27:05.763 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-08 06:00:00 +0000
2012-08-06 16:27:05.763 tuesdays[81152:403] 1 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-09 06:00:00 +0000
2012-08-06 16:27:05.764 tuesdays[81152:403] 2 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-10 06:00:00 +0000
2012-08-06 16:27:05.765 tuesdays[81152:403] 2 Mondays from 2012-01-01 06:00:00 +0000 to 2012-01-11 06:00:00 +0000

根据以下输出,这看起来是正确的cal 1 2012

    January 2012
Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

(请记住,toDate没有计算在内,因此从 2012-1-1 到 2012-1-2 有 0 个星期一,即使 2012-1-2 是星期一。)

于 2012-08-06T21:29:09.263 回答
0

您需要说明您的问题。定义什么是周末?对我来说周末是周六和周日。所以每次出现星期天都是一个周末(请记住,星期天不是整个周末 - 我只是想简化要求)。

那么你怎么能在代码中做到这一点呢?有很多方法。一种快速的方法是创建一个包含每天的数组 [Monday,Tuesday,...,Sunday]

现在您想知道在 3 周内这个星期二和星期二之间出现了多少个周末。你将通过减去 得到数字三targetDateComponent.week-currentDateComponent.week。您只需遍历此数组,直到星期二出现 3 次并计算所有星期日。

真的很简单。我不确定这是否完全符合您的问题。但是有很多方法。

试着谨慎地思考

于 2012-08-06T20:57:26.417 回答