简体   繁体   English

在Objective-C中获取一年中的第一天

[英]Get first day of week of year in Objective-C

I'm trying to find the first day of weeks using DateTools like so: 我正在尝试使用DateTools查找星期几,如下所示:

for (NSInteger week = 46; week <= 53; week++) {
    NSDate *tempDate = [NSDate dateWithString:[NSString stringWithFormat:@"2015-%d", (int)week] formatString:@"Y-w"];

    NSLog(@"INFO: tempDate: %@, day: %.2d, week: %d", tempDate, (int)[tempDate day], (int)week);
}

for (NSInteger week = 1; week <= 5; week++) {
    NSDate *tempDate = [NSDate dateWithString:[NSString stringWithFormat:@"2016-%d", (int)week] formatString:@"Y-w"];

    NSLog(@"INFO: tempDate: %@, day: %.2d, week: %d", tempDate, (int)[tempDate day], (int)week);
}

and I get this output: 我得到以下输出:

INFO: tempDate: 2015-11-07 22:00:00 +0000, day: 08, week: 46
INFO: tempDate: 2015-11-14 22:00:00 +0000, day: 15, week: 47
INFO: tempDate: 2015-11-21 22:00:00 +0000, day: 22, week: 48
INFO: tempDate: 2015-11-28 22:00:00 +0000, day: 29, week: 49
INFO: tempDate: 2015-12-05 22:00:00 +0000, day: 06, week: 50
INFO: tempDate: 2015-12-12 22:00:00 +0000, day: 13, week: 51
INFO: tempDate: 2015-12-19 22:00:00 +0000, day: 20, week: 52
INFO: tempDate: 2015-12-26 22:00:00 +0000, day: 27, week: 53
INFO: tempDate: 2015-12-26 22:00:00 +0000, day: 27, week: 1
INFO: tempDate: 2016-01-02 22:00:00 +0000, day: 03, week: 2
INFO: tempDate: 2016-01-09 22:00:00 +0000, day: 10, week: 3
INFO: tempDate: 2016-01-16 22:00:00 +0000, day: 17, week: 4
INFO: tempDate: 2016-01-23 22:00:00 +0000, day: 24, week: 5

and as you can see, the week 53 from 2015 has the same day as the week 1 from 2016 ( This site tells me that there are 53 weeks in 2015) . 并且您可以看到, 2015的第53周与2016的第1周具有同一天该网站告诉我2015年有53周)

Actually, the week 1 from 2016 starts from 04.01.2016 . 实际上,从2016开始的第1周从04.01.2016开始。

Also, notice the dateWithString:formatString: gives me the previous day of the first day of the week. 另外,请注意dateWithString:formatString:给了我一周的第一天的前一天。 Why is that? 这是为什么? I can simply use dateByAddingDays:1 but I don't know if it's hackish and the problem should be solved somewhere else. 我可以简单地使用dateByAddingDays:1但是我不知道它是否是hackish,应该在其他地方解决该问题。

I tried using NSDateComponents as @DarkDust mentioned, to no avail. 我尝试使用NSDateComponents作为@DarkDust提到,但无济于事。 So this: 所以这:

for (NSInteger week = 1; week <= 5; week++) {
    NSDate *tempDate = [NSDate dateWithString:[NSString stringWithFormat:@"2016-%d", (int)week] formatString:@"Y-w"];

    NSDateComponents *dateComponents = [NSDateComponents new];

    dateComponents.year = 2016;
    dateComponents.weekOfYear = week;

    NSLog(@"INFO: tempDate: %@, day: %.2d, week: %d = %@", tempDate, (int)[tempDate day], (int)week, [calendar dateFromComponents:dateComponents]);
}

gives me this: 给我这个:

INFO: tempDate: 2015-12-26 22:00:00 +0000, day: 27, week: 1 = 2015-12-31 22:00:00 +0000
INFO: tempDate: 2016-01-02 22:00:00 +0000, day: 03, week: 2 = 2015-12-31 22:00:00 +0000
INFO: tempDate: 2016-01-09 22:00:00 +0000, day: 10, week: 3 = 2015-12-31 22:00:00 +0000
INFO: tempDate: 2016-01-16 22:00:00 +0000, day: 17, week: 4 = 2015-12-31 22:00:00 +0000
INFO: tempDate: 2016-01-23 22:00:00 +0000, day: 24, week: 5 = 2015-12-31 22:00:00 +0000

Here is the DateTools ' dateWithString:formatString: implementation: 这是DateToolsdateWithString:formatString:实现:

+ (NSDate *)dateWithString:(NSString *)dateString formatString:(NSString *)formatString {

    return [self dateWithString:dateString formatString:formatString timeZone:[NSTimeZone systemTimeZone]];
}

+ (NSDate *)dateWithString:(NSString *)dateString formatString:(NSString *)formatString timeZone:(NSTimeZone *)timeZone {

    static NSDateFormatter *parser = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        parser = [[NSDateFormatter alloc] init];
    });

    parser.dateStyle = NSDateFormatterNoStyle;
    parser.timeStyle = NSDateFormatterNoStyle;
    parser.timeZone = timeZone;
    parser.dateFormat = formatString;

    return [parser dateFromString:dateString];
}

As for the duplicate report: 至于重复的报告:

The top 3 are wrong, 2 of them with downvotes, and they don't even do what I need at all. 前3名是错误的,其中2名投了反对票,他们甚至根本没有做我需要的事情。

This is a bad idea what you are doing. 这是一个坏主意,您在做什么。 You must understand a date is a time stamp which can be interpreted differently depending on the time zone and the calendar you are using. 您必须了解日期是一个时间戳,可以根据所使用的时区和日历对日期进行不同的解释。 As it was already mentioned in comments you should use date components for your solution. 正如评论中已经提到的那样,您应该为解决方案使用日期组件。 Note that printing out the date may use a different format and the result may not be expected. 请注意,打印出日期可能会使用其他格式,并且可能无法预期结果。

Next a first weekday in a year depends on definition. 一年中的下一个工作日取决于定义。 If I remember correctly some standards (or all) will treat the first week of the year depending on what day of week is the first day. 如果我没记错的话,某些标准(或全部标准)将根据一年中的第一天来处理一年的第一周。 In other words if 1.1 is sunday then the first week of the year is in december but if it is tuesday then it is in january. 换句话说,如果1.1是星期日,那么一年的第一周是在12月,但是如果是星期二,则是在一月。

So if you want to find the beginning of the first monday of the given year the code should look something like this (I did not test it): 因此,如果要查找给定年份的第一个星期一的开始,则代码应如下所示(我没有对其进行测试):

+ (NSDate *)firstWeekInYear:(NSInteger)year {

        NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];

        NSDate *toReturn = nil;
        NSDateComponents *components = [[NSDateComponents alloc] init];
        components.year = year;
        NSDate *beginningOfTheYear = [calendar dateFromComponents:components];
        NSInteger day = [calendar component:NSCalendarUnitWeekday fromDate:beginningOfTheYear];
        NSInteger daysToAdd = (8-day)%7;

        toReturn = [calendar dateByAddingUnit:NSCalendarUnitDay value:daysToAdd toDate:beginningOfTheYear options:kNilOptions];

        return toReturn;
    }

So you need to choose the calendar, create date components with a target year, get the date from those components with the calendar to get the beginning of the year. 因此,您需要选择日历,使用目标年份创建日期组件,使用日历从这些组件中获取日期以获取年初。 Then find out what weekday that is and increase such a number of days so the result is the beginning of the first monday in a year. 然后找出是哪个工作日,并增加这样的天数,以便结果是一年中第一个星期一的开始。

I finally figured it out. 我终于弄明白了。 @Matic's solution doesn't work in iOS 7 and it's hard to understand, so I managed to find a simpler solution that works on iOS 7 too: @Matic的解决方案在iOS 7中不起作用,很难理解,因此我设法找到了一种在iOS 7上也可以使用的更简单的解决方案:

+ (NSDate *)getFirstDayInWeek:(NSInteger)week ofYear:(NSInteger)year {

    /* create the calendar only once */

    static NSCalendar *calendar = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

        calendar.firstWeekday = 2;
        calendar.minimumDaysInFirstWeek = 4;
    });

    NSDateComponents *components = [NSDateComponents new]; // create an empty date components object

    components.year = year;
    components.weekOfYear = week; // set the number of the week in the year
    components.weekday = calendar.firstWeekday; // important! set the result date's day of week

    return [calendar dateFromComponents:components];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM