Determine NSDate for Memorial Day in a given year

柔情痞子 提交于 2020-01-13 20:16:47

问题


Is there a better way to determine the NSDate for Memorial Day (the last Monday in May) in a given year?

NSInteger aGivenYear = 2013 ;

NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDateComponents* firstMondayInJuneComponents = [NSDateComponents new] ;
firstMondayInJuneComponents.month = 6 ;
// Thanks, Martin R., for pointing out that `weekOfMonth` is wrong for returning the first Monday in June.
firstMondayInJuneComponents.weekOfMonth = 1 ;
firstMondayInJuneComponents.weekday = 2 ; //Monday
firstMondayInJuneComponents.year = aGivenYear ;
NSDate* firstMondayInJune = [calendar dateFromComponents:firstMondayInJuneComponents] ;

NSDateComponents* subtractAWeekComponents = [NSDateComponents new] ;
subtractAWeekComponents.week = 0 ;
NSDate* memorialDay = [calendar dateByAddingComponents:subtractAWeekComponents toDate:firstMondayInJune options:0] ;

Edit

I see now that firstMondayInJune in the above example doesn't work for all years; it returns May 28 for the year 2012.

Thanks, Martin R. weekdayOrdinal does exactly what I hoped, and it returns Memorial Day with 3 fewer lines of code:

NSInteger aGivenYear = 2013 ;

NSDateComponents* memorialDayComponents = [NSDateComponents new] ;
memorialDayComponents.year = aGivenYear ;
memorialDayComponents.month = 5 ;
memorialDayComponents.weekday = 2 ; //Monday
memorialDayComponents.weekdayOrdinal = -1 ; //The last instance of the specified weekday in the specified month & year.
NSDate* memorialDay = [calendar dateFromComponents:memorialDayComponents] ;

回答1:


To get the first Monday in a month, set weekdayOrdinal = 1 instead of weekOfMonth = 1:

NSInteger aGivenYear = 2012 ;

NSCalendar* calendar = [NSCalendar currentCalendar] ;
NSDateComponents* firstMondayInJuneComponents = [NSDateComponents new] ;
firstMondayInJuneComponents.month = 6 ;
firstMondayInJuneComponents.weekdayOrdinal = 1 ;
firstMondayInJuneComponents.weekday = 2 ; //Monday
firstMondayInJuneComponents.year = aGivenYear ;
NSDate* firstMondayInJune = [calendar dateFromComponents:firstMondayInJuneComponents] ;
// --> 2012-06-04

NSDateComponents* subtractAWeekComponents = [NSDateComponents new] ;
subtractAWeekComponents.week = -1 ;
NSDate* memorialDay = [calendar dateByAddingComponents:subtractAWeekComponents toDate:firstMondayInJune options:0] ;
// --> 2012-05-28

From the NSDateComponents documentation:

Weekday ordinal units represent the position of the weekday within the next larger calendar unit, such as the month. For example, 2 is the weekday ordinal unit for the second Friday of the month.




回答2:


What I'd probably do is get the day of the week of the first of the month (perhaps using NSDateFormatter), then calculate the date of the first Monday/Tuesday/Thursday/whatever of the month, then add (week# - 1) x 7 to that date to get the Nth Monday/whatever of the month.

For Memorial day you'd first check if the 5th Monday was still in May, if not use the 4th. (Or check going in, knowing that if Memorial day is on the 31st then the first Monday must be on the 3rd or earlier.)



来源:https://stackoverflow.com/questions/14147450/determine-nsdate-for-memorial-day-in-a-given-year

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!