在 Objective-C 中获取一年中的第一天
Get first day of week of year in Objective-C
我正在尝试使用 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);
}
我得到了这个输出:
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
如您所见,2015
的第 53
周与 2016
的第 1
周在同一天 (This site告诉我2015年有53周).
实际上,从 2016
开始的 1
周是从 04.01.2016
开始的。
另外,请注意 dateWithString:formatString:
给出了一周第一天的前一天。这是为什么?我可以简单地使用 dateByAddingDays:1
但我不知道它是否有问题并且应该在其他地方解决问题。
我尝试使用 NSDateComponents
作为@DarkDust 提到的,但无济于事。所以这个:
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]);
}
给我这个:
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
这是 DateTools
' dateWithString: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];
}
关于重复报告:
The top 3 are wrong, 2 of them with downvotes, and they don't even do what I need at all.
你的做法很糟糕。您必须了解日期是一个时间戳,可以根据您使用的时区和日历进行不同的解释。正如评论中已经提到的那样,您应该为您的解决方案使用日期组件。请注意,打印日期可能会使用不同的格式,并且结果可能不是预期的。
接下来一年中的第一个工作日取决于定义。如果我没记错的话,某些标准(或所有标准)将根据一周中的哪一天是第一天来对待一年中的第一周。换句话说,如果 1.1 是星期日,那么一年的第一周就是十二月,但如果是星期二,那么就是一月。
所以如果你想找到给定年份的第一个星期一的开始,代码应该看起来像这样(我没有测试它):
+ (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;
}
因此您需要选择日历,创建具有目标年份的日期组件,从具有日历的组件中获取日期以获得年初。然后找出是星期几,然后增加这样的天数,结果就是一年中第一个星期一的开始。
我终于明白了。 @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];
}
我正在尝试使用 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);
}
我得到了这个输出:
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
如您所见,2015
的第 53
周与 2016
的第 1
周在同一天 (This site告诉我2015年有53周).
实际上,从 2016
开始的 1
周是从 04.01.2016
开始的。
另外,请注意 dateWithString:formatString:
给出了一周第一天的前一天。这是为什么?我可以简单地使用 dateByAddingDays:1
但我不知道它是否有问题并且应该在其他地方解决问题。
我尝试使用 NSDateComponents
作为@DarkDust 提到的,但无济于事。所以这个:
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]);
}
给我这个:
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
这是 DateTools
' dateWithString: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];
}
关于重复报告:
The top 3 are wrong, 2 of them with downvotes, and they don't even do what I need at all.
你的做法很糟糕。您必须了解日期是一个时间戳,可以根据您使用的时区和日历进行不同的解释。正如评论中已经提到的那样,您应该为您的解决方案使用日期组件。请注意,打印日期可能会使用不同的格式,并且结果可能不是预期的。
接下来一年中的第一个工作日取决于定义。如果我没记错的话,某些标准(或所有标准)将根据一周中的哪一天是第一天来对待一年中的第一周。换句话说,如果 1.1 是星期日,那么一年的第一周就是十二月,但如果是星期二,那么就是一月。
所以如果你想找到给定年份的第一个星期一的开始,代码应该看起来像这样(我没有测试它):
+ (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;
}
因此您需要选择日历,创建具有目标年份的日期组件,从具有日历的组件中获取日期以获得年初。然后找出是星期几,然后增加这样的天数,结果就是一年中第一个星期一的开始。
我终于明白了。 @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];
}